public inbox for [email protected]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 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 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/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 --------------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. 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 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/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/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 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/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 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 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..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..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/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 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 | 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 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/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/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 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 --------------0E72B707603BED22B4040825-- ^ 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 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/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/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 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 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/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/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 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 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. 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 --------------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 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 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..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. 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 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 | 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 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/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 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/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 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. 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 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/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 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 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. 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 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/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 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 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 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 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 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 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..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/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 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 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/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/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 | 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 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 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 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. 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 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/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/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. 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 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 | 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/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 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/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 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/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..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 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 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..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 | 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/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 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/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/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 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 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 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 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 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 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 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 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/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/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 | 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 | 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 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 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 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 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 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. 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 | 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 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 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/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/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/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/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 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. 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/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 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 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/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/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 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/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/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/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 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 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/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 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 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/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/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 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 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..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 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/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 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 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/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 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 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 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 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/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/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 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 | 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/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/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 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 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/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 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 | 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 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..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. 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 --------------0E72B707603BED22B4040825-- ^ 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 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 | 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 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 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 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 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. 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 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 | 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 --------------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. 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 --------------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 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/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 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/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 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 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/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 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 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 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 --------------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. 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 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/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. 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. 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 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 | 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 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 | 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 | 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/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 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 | 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 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/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/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 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 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 --------------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 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 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..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 | 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/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 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 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/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/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/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/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 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..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 | 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/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/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 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. 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 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 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. 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/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 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..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. 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 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/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 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 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 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 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 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/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/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 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..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 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 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
* [PATCH 1/6] Add REPACK command @ 2026-01-22 08:23 Antonin Houska <[email protected]> 0 siblings, 0 replies; 280+ messages in thread From: Antonin Houska @ 2026-01-22 08:23 UTC (permalink / raw) REPACK absorbs the functionality of VACUUM FULL and CLUSTER in a single command. Because this functionality is completely different from regular VACUUM, having it separate from VACUUM makes it easier for users to understand; as for CLUSTER, the term is heavily overloaded in the IT world and even in Postgres itself, so it's good that we can avoid it. This also adds pg_repackdb, a new utility that can invoke the new commands. This is heavily based on vacuumdb. Author: Antonin Houska <[email protected]> Co-authored-by: =C3=81lvaro Herrera <[email protected]> Reviewed-by: Mihail Nikalayeu <[email protected]> Reviewed-by: Robert Treat <[email protected]> Reviewed-by: Euler Taveira <[email protected]> Reviewed-by: Matheus Alcantara <[email protected]> Reviewed-by: Junwang Zhao <[email protected]> Reviewed-by: jian he <[email protected]> Discussion: https://postgr.es/m/82651.1720540558@antos Discussion: https://postgr.es/m/[email protected] --- doc/src/sgml/monitoring.sgml | 223 +++++- doc/src/sgml/ref/allfiles.sgml | 2 + doc/src/sgml/ref/cluster.sgml | 97 +-- doc/src/sgml/ref/clusterdb.sgml | 5 + doc/src/sgml/ref/pg_repackdb.sgml | 488 +++++++++++++ doc/src/sgml/ref/repack.sgml | 328 +++++++++ doc/src/sgml/ref/vacuum.sgml | 33 +- doc/src/sgml/reference.sgml | 2 + src/backend/access/heap/heapam_handler.c | 32 +- src/backend/catalog/index.c | 2 +- src/backend/catalog/system_views.sql | 29 +- src/backend/commands/cluster.c | 842 +++++++++++++++-------- src/backend/commands/vacuum.c | 6 +- src/backend/parser/gram.y | 86 ++- src/backend/tcop/utility.c | 23 +- src/backend/utils/adt/pgstatfuncs.c | 4 +- src/bin/psql/tab-complete.in.c | 42 +- src/bin/scripts/Makefile | 3 + src/bin/scripts/meson.build | 2 + src/bin/scripts/pg_repackdb.c | 240 +++++++ src/bin/scripts/t/103_repackdb.pl | 47 ++ src/bin/scripts/vacuuming.c | 102 ++- src/bin/scripts/vacuuming.h | 3 + src/include/commands/cluster.h | 8 +- src/include/commands/progress.h | 50 +- src/include/nodes/parsenodes.h | 35 +- src/include/parser/kwlist.h | 1 + src/include/tcop/cmdtaglist.h | 1 + src/include/utils/backend_progress.h | 2 +- src/test/regress/expected/cluster.out | 134 +++- src/test/regress/expected/rules.out | 72 +- src/test/regress/sql/cluster.sql | 70 +- src/tools/pgindent/typedefs.list | 2 + 33 files changed, 2480 insertions(+), 536 deletions(-) create mode 100644 doc/src/sgml/ref/pg_repackdb.sgml create mode 100644 doc/src/sgml/ref/repack.sgml create mode 100644 src/bin/scripts/pg_repackdb.c create mode 100644 src/bin/scripts/t/103_repackdb.pl diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml index 817fd9f4ca7..b07fe3294cd 100644 --- a/doc/src/sgml/monitoring.sgml +++ b/doc/src/sgml/monitoring.sgml @@ -405,6 +405,14 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss = 11:34 0:00 postgres: ser </entry> </row> =20 + <row> + <entry><structname>pg_stat_progress_repack</structname><indexterm><p= rimary>pg_stat_progress_repack</primary></indexterm></entry> + <entry>One row for each backend running + <command>REPACK</command>, showing current progress. See + <xref linkend=3D"repack-progress-reporting"/>. + </entry> + </row> + <row> <entry><structname>pg_stat_progress_basebackup</structname><indexter= m><primary>pg_stat_progress_basebackup</primary></indexterm></entry> <entry>One row for each WAL sender process streaming a base backup, @@ -5609,7 +5617,8 @@ FROM pg_stat_get_backend_idset() AS backendid; certain commands during command execution. Currently, the only commands which support progress reporting are <command>ANALYZE</command>, <command>CLUSTER</command>, - <command>CREATE INDEX</command>, <command>VACUUM</command>, + <command>CREATE INDEX</command>, <command>REPACK</command>, + <command>VACUUM</command>, <command>COPY</command>, and <xref linkend=3D"protocol-replication-base-backup"/> (i.e., replica= tion command that <xref linkend=3D"app-pgbasebackup"/> issues to take @@ -6093,6 +6102,218 @@ FROM pg_stat_get_backend_idset() AS backendid; </table> </sect2> =20 + <sect2 id=3D"repack-progress-reporting"> + <title>REPACK Progress Reporting</title> + + <indexterm> + <primary>pg_stat_progress_repack</primary> + </indexterm> + + <para> + Whenever <command>REPACK</command> is running, + the <structname>pg_stat_progress_repack</structname> view will contain a + row for each backend that is currently running the command. The tables + below describe the information that will be reported and provide + information about how to interpret it. + </para> + + <table id=3D"pg-stat-progress-repack-view" xreflabel=3D"pg_stat_progress= _repack"> + <title><structname>pg_stat_progress_repack</structname> View</title> + <tgroup cols=3D"1"> + <thead> + <row> + <entry role=3D"catalog_table_entry"><para role=3D"column_definition"> + Column Type + </para> + <para> + Description + </para></entry> + </row> + </thead> + + <tbody> + <row> + <entry role=3D"catalog_table_entry"><para role=3D"column_definition"> + <structfield>pid</structfield> <type>integer</type> + </para> + <para> + Process ID of backend. + </para></entry> + </row> + + <row> + <entry role=3D"catalog_table_entry"><para role=3D"column_definition"> + <structfield>datid</structfield> <type>oid</type> + </para> + <para> + OID of the database to which this backend is connected. + </para></entry> + </row> + + <row> + <entry role=3D"catalog_table_entry"><para role=3D"column_definition"> + <structfield>datname</structfield> <type>name</type> + </para> + <para> + Name of the database to which this backend is connected. + </para></entry> + </row> + + <row> + <entry role=3D"catalog_table_entry"><para role=3D"column_definition"> + <structfield>relid</structfield> <type>oid</type> + </para> + <para> + OID of the table being repacked. + </para></entry> + </row> + + <row> + <entry role=3D"catalog_table_entry"><para role=3D"column_definition"> + <structfield>phase</structfield> <type>text</type> + </para> + <para> + Current processing phase. See <xref linkend=3D"repack-phases"/>. + </para></entry> + </row> + + <row> + <entry role=3D"catalog_table_entry"><para role=3D"column_definition"> + <structfield>repack_index_relid</structfield> <type>oid</type> + </para> + <para> + If the table is being scanned using an index, this is the OID of the + index being used; otherwise, it is zero. + </para></entry> + </row> + + <row> + <entry role=3D"catalog_table_entry"><para role=3D"column_definition"> + <structfield>heap_tuples_scanned</structfield> <type>bigint</type> + </para> + <para> + Number of heap tuples scanned. + This counter only advances when the phase is + <literal>seq scanning heap</literal>, + <literal>index scanning heap</literal> + or <literal>writing new heap</literal>. + </para></entry> + </row> + + <row> + <entry role=3D"catalog_table_entry"><para role=3D"column_definition"> + <structfield>heap_tuples_written</structfield> <type>bigint</type> + </para> + <para> + Number of heap tuples written. + This counter only advances when the phase is + <literal>seq scanning heap</literal>, + <literal>index scanning heap</literal> + or <literal>writing new heap</literal>. + </para></entry> + </row> + + <row> + <entry role=3D"catalog_table_entry"><para role=3D"column_definition"> + <structfield>heap_blks_total</structfield> <type>bigint</type> + </para> + <para> + Total number of heap blocks in the table. This number is reported + as of the beginning of <literal>seq scanning heap</literal>. + </para></entry> + </row> + + <row> + <entry role=3D"catalog_table_entry"><para role=3D"column_definition"> + <structfield>heap_blks_scanned</structfield> <type>bigint</type> + </para> + <para> + Number of heap blocks scanned. This counter only advances when the + phase is <literal>seq scanning heap</literal>. + </para></entry> + </row> + + <row> + <entry role=3D"catalog_table_entry"><para role=3D"column_definition"> + <structfield>index_rebuild_count</structfield> <type>bigint</type> + </para> + <para> + Number of indexes rebuilt. This counter only advances when the pha= se + is <literal>rebuilding index</literal>. + </para></entry> + </row> + </tbody> + </tgroup> + </table> + + <table id=3D"repack-phases"> + <title>REPACK Phases</title> + <tgroup cols=3D"2"> + <colspec colname=3D"col1" colwidth=3D"1*"/> + <colspec colname=3D"col2" colwidth=3D"2*"/> + <thead> + <row> + <entry>Phase</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + <row> + <entry><literal>initializing</literal></entry> + <entry> + The command is preparing to begin scanning the heap. This phase is + expected to be very brief. + </entry> + </row> + <row> + <entry><literal>seq scanning heap</literal></entry> + <entry> + The command is currently scanning the table using a sequential scan. + </entry> + </row> + <row> + <entry><literal>index scanning heap</literal></entry> + <entry> + <command>REPACK</command> is currently scanning the table using an = index scan. + </entry> + </row> + <row> + <entry><literal>sorting tuples</literal></entry> + <entry> + <command>REPACK</command> is currently sorting tuples. + </entry> + </row> + <row> + <entry><literal>writing new heap</literal></entry> + <entry> + <command>REPACK</command> is currently writing the new heap. + </entry> + </row> + <row> + <entry><literal>swapping relation files</literal></entry> + <entry> + The command is currently swapping newly-built files into place. + </entry> + </row> + <row> + <entry><literal>rebuilding index</literal></entry> + <entry> + The command is currently rebuilding an index. + </entry> + </row> + <row> + <entry><literal>performing final cleanup</literal></entry> + <entry> + The command is performing final cleanup. When this phase is + completed, <command>REPACK</command> will end. + </entry> + </row> + </tbody> + </tgroup> + </table> + </sect2> + <sect2 id=3D"copy-progress-reporting"> <title>COPY Progress Reporting</title> =20 diff --git a/doc/src/sgml/ref/allfiles.sgml b/doc/src/sgml/ref/allfiles.sgml index e167406c744..5df944d13ca 100644 --- a/doc/src/sgml/ref/allfiles.sgml +++ b/doc/src/sgml/ref/allfiles.sgml @@ -167,6 +167,7 @@ Complete list of usable sgml source files in this direc= tory. <!ENTITY refreshMaterializedView SYSTEM "refresh_materialized_view.sgml"> <!ENTITY reindex SYSTEM "reindex.sgml"> <!ENTITY releaseSavepoint SYSTEM "release_savepoint.sgml"> +<!ENTITY repack SYSTEM "repack.sgml"> <!ENTITY reset SYSTEM "reset.sgml"> <!ENTITY revoke SYSTEM "revoke.sgml"> <!ENTITY rollback SYSTEM "rollback.sgml"> @@ -213,6 +214,7 @@ Complete list of usable sgml source files in this direc= tory. <!ENTITY pgIsready SYSTEM "pg_isready.sgml"> <!ENTITY pgReceivewal SYSTEM "pg_receivewal.sgml"> <!ENTITY pgRecvlogical SYSTEM "pg_recvlogical.sgml"> +<!ENTITY pgRepackdb SYSTEM "pg_repackdb.sgml"> <!ENTITY pgResetwal SYSTEM "pg_resetwal.sgml"> <!ENTITY pgRestore SYSTEM "pg_restore.sgml"> <!ENTITY pgRewind SYSTEM "pg_rewind.sgml"> diff --git a/doc/src/sgml/ref/cluster.sgml b/doc/src/sgml/ref/cluster.sgml index 0b47460080b..2cda711bc9f 100644 --- a/doc/src/sgml/ref/cluster.sgml +++ b/doc/src/sgml/ref/cluster.sgml @@ -33,51 +33,13 @@ CLUSTER [ ( <replaceable class=3D"parameter">option</re= placeable> [, ...] ) ] [ <r <title>Description</title> =20 <para> - <command>CLUSTER</command> instructs <productname>PostgreSQL</productna= me> - to cluster the table specified - by <replaceable class=3D"parameter">table_name</replaceable> - based on the index specified by - <replaceable class=3D"parameter">index_name</replaceable>. The index mu= st - already have been defined on - <replaceable class=3D"parameter">table_name</replaceable>. + The <command>CLUSTER</command> command is equivalent to + <xref linkend=3D"sql-repack"/> with an <literal>USING INDEX</literal> + clause. See there for more details. </para> =20 - <para> - When a table is clustered, it is physically reordered - based on the index information. Clustering is a one-time operation: - when the table is subsequently updated, the changes are - not clustered. That is, no attempt is made to store new or - updated rows according to their index order. (If one wishes, one can - periodically recluster by issuing the command again. Also, setting - the table's <literal>fillfactor</literal> storage parameter to less than - 100% can aid in preserving cluster ordering during updates, since updat= ed - rows are kept on the same page if enough space is available there.) - </para> - - <para> - When a table is clustered, <productname>PostgreSQL</productname> - remembers which index it was clustered by. The form - <command>CLUSTER <replaceable class=3D"parameter">table_name</replaceab= le></command> - reclusters the table using the same index as before. You can also - use the <literal>CLUSTER</literal> or <literal>SET WITHOUT CLUSTER</lit= eral> - forms of <link linkend=3D"sql-altertable"><command>ALTER TABLE</command= ></link> to set the index to be used for - future cluster operations, or to clear any previous setting. - </para> - - <para> - <command>CLUSTER</command> without a - <replaceable class=3D"parameter">table_name</replaceable> reclusters al= l the - previously-clustered tables in the current database that the calling us= er - has privileges for. This form of <command>CLUSTER</command> cannot be - executed inside a transaction block. - </para> +<!-- Do we need to describe exactly which options map to what? They seem = obvious to me. --> =20 - <para> - When a table is being clustered, an <literal>ACCESS - EXCLUSIVE</literal> lock is acquired on it. This prevents any other - database operations (both reads and writes) from operating on the - table until the <command>CLUSTER</command> is finished. - </para> </refsect1> =20 <refsect1> @@ -136,63 +98,12 @@ CLUSTER [ ( <replaceable class=3D"parameter">option</r= eplaceable> [, ...] ) ] [ <r on the table. </para> =20 - <para> - In cases where you are accessing single rows randomly - within a table, the actual order of the data in the - table is unimportant. However, if you tend to access some - data more than others, and there is an index that groups - them together, you will benefit from using <command>CLUSTER</command>. - If you are requesting a range of indexed values from a table, or a - single indexed value that has multiple rows that match, - <command>CLUSTER</command> will help because once the index identifies= the - table page for the first row that matches, all other rows - that match are probably already on the same table page, - and so you save disk accesses and speed up the query. - </para> - - <para> - <command>CLUSTER</command> can re-sort the table using either an index= scan - on the specified index, or (if the index is a b-tree) a sequential - scan followed by sorting. It will attempt to choose the method that - will be faster, based on planner cost parameters and available statist= ical - information. - </para> - <para> While <command>CLUSTER</command> is running, the <xref linkend=3D"guc-search-path"/> is temporarily changed to <literal>pg_ca= talog, pg_temp</literal>. </para> =20 - <para> - When an index scan is used, a temporary copy of the table is created t= hat - contains the table data in the index order. Temporary copies of each - index on the table are created as well. Therefore, you need free spac= e on - disk at least equal to the sum of the table size and the index sizes. - </para> - - <para> - When a sequential scan and sort is used, a temporary sort file is - also created, so that the peak temporary space requirement is as much - as double the table size, plus the index sizes. This method is often - faster than the index scan method, but if the disk space requirement is - intolerable, you can disable this choice by temporarily setting <xref - linkend=3D"guc-enable-sort"/> to <literal>off</literal>. - </para> - - <para> - It is advisable to set <xref linkend=3D"guc-maintenance-work-mem"/> to - a reasonably large value (but not more than the amount of RAM you can - dedicate to the <command>CLUSTER</command> operation) before clusterin= g. - </para> - - <para> - Because the planner records statistics about the ordering of - tables, it is advisable to run <link linkend=3D"sql-analyze"><command>= ANALYZE</command></link> - on the newly clustered table. - Otherwise, the planner might make poor choices of query plans. - </para> - <para> Because <command>CLUSTER</command> remembers which indexes are cluster= ed, one can cluster the tables one wants clustered manually the first time, diff --git a/doc/src/sgml/ref/clusterdb.sgml b/doc/src/sgml/ref/clusterdb.s= gml index 0d2051bf6f1..b50c9581a98 100644 --- a/doc/src/sgml/ref/clusterdb.sgml +++ b/doc/src/sgml/ref/clusterdb.sgml @@ -64,6 +64,11 @@ PostgreSQL documentation this utility and via other methods for accessing the server. </para> =20 + <para> + <application>clusterdb</application> has been superseded by + <application>pg_repackdb</application>. + </para> + </refsect1> =20 =20 diff --git a/doc/src/sgml/ref/pg_repackdb.sgml b/doc/src/sgml/ref/pg_repack= db.sgml new file mode 100644 index 00000000000..a5ea513c6b1 --- /dev/null +++ b/doc/src/sgml/ref/pg_repackdb.sgml @@ -0,0 +1,488 @@ +<!-- +doc/src/sgml/ref/pg_repackdb.sgml +PostgreSQL documentation +--> + +<refentry id=3D"app-pgrepackdb"> + <indexterm zone=3D"app-pgrepackdb"> + <primary>pg_repackdb</primary> + </indexterm> + + <refmeta> + <refentrytitle><application>pg_repackdb</application></refentrytitle> + <manvolnum>1</manvolnum> + <refmiscinfo>Application</refmiscinfo> + </refmeta> + + <refnamediv> + <refname>pg_repackdb</refname> + <refpurpose>repack and analyze a <productname>PostgreSQL</productname> + database</refpurpose> + </refnamediv> + + <refsynopsisdiv> + <cmdsynopsis> + <command>pg_repackdb</command> + <arg rep=3D"repeat"><replaceable>connection-option</replaceable></arg> + <arg rep=3D"repeat"><replaceable>option</replaceable></arg> + + <arg choice=3D"plain" rep=3D"repeat"> + <arg choice=3D"opt"> + <group choice=3D"plain"> + <arg choice=3D"plain"><option>-t</option></arg> + <arg choice=3D"plain"><option>--table</option></arg> + </group> + <replaceable>table</replaceable> + <arg choice=3D"opt">( <replaceable class=3D"parameter">column</replac= eable> [,...] )</arg> + </arg> + </arg> + + <arg choice=3D"opt"> + <group choice=3D"plain"> + <arg choice=3D"plain"><replaceable>dbname</replaceable></arg> + <arg choice=3D"plain"><option>-a</option></arg> + <arg choice=3D"plain"><option>--all</option></arg> + </group> + </arg> + </cmdsynopsis> + + <cmdsynopsis> + <command>pg_repackdb</command> + <arg rep=3D"repeat"><replaceable>connection-option</replaceable></arg> + <arg rep=3D"repeat"><replaceable>option</replaceable></arg> + + <arg choice=3D"plain" rep=3D"repeat"> + <arg choice=3D"opt"> + <group choice=3D"plain"> + <arg choice=3D"plain"><option>-n</option></arg> + <arg choice=3D"plain"><option>--schema</option></arg> + </group> + <replaceable>schema</replaceable> + </arg> + </arg> + + <arg choice=3D"opt"> + <group choice=3D"plain"> + <arg choice=3D"plain"><replaceable>dbname</replaceable></arg> + <arg choice=3D"plain"><option>-a</option></arg> + <arg choice=3D"plain"><option>--all</option></arg> + </group> + </arg> + </cmdsynopsis> + + <cmdsynopsis> + <command>pg_repackdb</command> + <arg rep=3D"repeat"><replaceable>connection-option</replaceable></arg> + <arg rep=3D"repeat"><replaceable>option</replaceable></arg> + + <arg choice=3D"plain" rep=3D"repeat"> + <arg choice=3D"opt"> + <group choice=3D"plain"> + <arg choice=3D"plain"><option>-N</option></arg> + <arg choice=3D"plain"><option>--exclude-schema</option></arg> + </group> + <replaceable>schema</replaceable> + </arg> + </arg> + + <arg choice=3D"opt"> + <group choice=3D"plain"> + <arg choice=3D"plain"><replaceable>dbname</replaceable></arg> + <arg choice=3D"plain"><option>-a</option></arg> + <arg choice=3D"plain"><option>--all</option></arg> + </group> + </arg> + </cmdsynopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <application>pg_repackdb</application> is a utility for repacking a + <productname>PostgreSQL</productname> database. + <application>pg_repackdb</application> will also generate internal + statistics used by the <productname>PostgreSQL</productname> query + optimizer. + </para> + + <para> + <application>pg_repackdb</application> is a wrapper around the SQL + command <link linkend=3D"sql-repack"><command>REPACK</command></link>. = There + is no effective difference between repacking and analyzing databases via + this utility and via other methods for accessing the server. + </para> + </refsect1> + + <refsect1> + <title>Options</title> + + <para> + <application>pg_repackdb</application> accepts the following command-l= ine arguments: + <variablelist> + <varlistentry> + <term><option>-a</option></term> + <term><option>--all</option></term> + <listitem> + <para> + Repack all databases. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option><optional>-d</optional> <replaceable class=3D"paramete= r">dbname</replaceable></option></term> + <term><option><optional>--dbname=3D</optional><replaceable class=3D"= parameter">dbname</replaceable></option></term> + <listitem> + <para> + Specifies the name of the database to be repacked or analyzed, + when <option>-a</option>/<option>--all</option> is not used. If t= his + is not specified, the database name is read from the environment + variable <envar>PGDATABASE</envar>. If that is not set, the user = name + specified for the connection is used. + The <replaceable>dbname</replaceable> can be + a <link linkend=3D"libpq-connstring">connection string</link>. If= so, + connection string parameters will override any conflicting command + line options. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-e</option></term> + <term><option>--echo</option></term> + <listitem> + <para> + Echo the commands that <application>pg_repackdb</application> + generates and sends to the server. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--index<optional>=3D<replaceable class=3D"parameter">i= ndex_name</replaceable></optional></option></term> + <listitem> + <para> + Pass the <literal>USING INDEX</literal> clause to <literal>REPACK<= /literal>, + and optionally the index name to specify. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-j <replaceable class=3D"parameter">njobs</replaceable= ></option></term> + <term><option>--jobs=3D<replaceable class=3D"parameter">njobs</repla= ceable></option></term> + <listitem> + <para> + Execute the repack or analyze commands in parallel by running + <replaceable class=3D"parameter">njobs</replaceable> + commands simultaneously. This option may reduce the processing ti= me + but it also increases the load on the database server. + </para> + <para> + <application>pg_repackdb</application> will open + <replaceable class=3D"parameter">njobs</replaceable> connections t= o the + database, so make sure your <xref linkend=3D"guc-max-connections"/> + setting is high enough to accommodate all connections. + </para> + <para> + Note that using this mode might cause deadlock failures if certain + system catalogs are processed in parallel. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-n <replaceable class=3D"parameter">schema</replaceabl= e></option></term> + <term><option>--schema=3D<replaceable class=3D"parameter">schema</re= placeable></option></term> + <listitem> + <para> + Repack or analyze all tables in + <replaceable class=3D"parameter">schema</replaceable> only. Multi= ple + schemas can be repacked by writing multiple <option>-n</option> + switches. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-N <replaceable class=3D"parameter">schema</replaceabl= e></option></term> + <term><option>--exclude-schema=3D<replaceable class=3D"parameter">sc= hema</replaceable></option></term> + <listitem> + <para> + Do not repack or analyze any tables in + <replaceable class=3D"parameter">schema</replaceable>. Multiple s= chemas + can be excluded by writing multiple <option>-N</option> switches. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-q</option></term> + <term><option>--quiet</option></term> + <listitem> + <para> + Do not display progress messages. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-t <replaceable class=3D"parameter">table</replaceable= > [ (<replaceable class=3D"parameter">column</replaceable> [,...]) ]</optio= n></term> + <term><option>--table=3D<replaceable class=3D"parameter">table</repl= aceable> [ (<replaceable class=3D"parameter">column</replaceable> [,...]) ]= </option></term> + <listitem> + <para> + Repack or analyze <replaceable class=3D"parameter">table</replacea= ble> + only. Column names can be specified only in conjunction with + the <option>--analyze</option> option. Multiple tables can be + repacked by writing multiple + <option>-t</option> switches. + </para> + <tip> + <para> + If you specify columns, you probably have to escape the parenthes= es + from the shell. (See examples below.) + </para> + </tip> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-v</option></term> + <term><option>--verbose</option></term> + <listitem> + <para> + Print detailed information during processing. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-V</option></term> + <term><option>--version</option></term> + <listitem> + <para> + Print the <application>pg_repackdb</application> version and exit. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-z</option></term> + <term><option>--analyze</option></term> + <listitem> + <para> + Also calculate statistics for use by the optimizer. If a column n= ame + list is given, only compute statistics for those columns. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-?</option></term> + <term><option>--help</option></term> + <listitem> + <para> + Show help about <application>pg_repackdb</application> command line + arguments, and exit. + </para> + </listitem> + </varlistentry> + + </variablelist> + </para> + + <para> + <application>pg_repackdb</application> also accepts + the following command-line arguments for connection parameters: + <variablelist> + <varlistentry> + <term><option>-h <replaceable class=3D"parameter">host</replaceable>= </option></term> + <term><option>--host=3D<replaceable class=3D"parameter">host</replac= eable></option></term> + <listitem> + <para> + Specifies the host name of the machine on which the server + is running. If the value begins with a slash, it is used + as the directory for the Unix domain socket. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-p <replaceable class=3D"parameter">port</replaceable>= </option></term> + <term><option>--port=3D<replaceable class=3D"parameter">port</replac= eable></option></term> + <listitem> + <para> + Specifies the TCP port or local Unix domain socket file + extension on which the server + is listening for connections. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-U <replaceable class=3D"parameter">username</replacea= ble></option></term> + <term><option>--username=3D<replaceable class=3D"parameter">username= </replaceable></option></term> + <listitem> + <para> + User name to connect as. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-w</option></term> + <term><option>--no-password</option></term> + <listitem> + <para> + Never issue a password prompt. If the server requires + password authentication and a password is not available by + other means such as a <filename>.pgpass</filename> file, the + connection attempt will fail. This option can be useful in + batch jobs and scripts where no user is present to enter a + password. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-W</option></term> + <term><option>--password</option></term> + <listitem> + <para> + Force <application>pg_repackdb</application> to prompt for a + password before connecting to a database. + </para> + + <para> + This option is never essential, since + <application>pg_repackdb</application> will automatically prompt + for a password if the server demands password authentication. + However, <application>pg_repackdb</application> will waste a + connection attempt finding out that the server wants a password. + In some cases it is worth typing <option>-W</option> to avoid the = extra + connection attempt. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>--maintenance-db=3D<replaceable class=3D"parameter">db= name</replaceable></option></term> + <listitem> + <para> + When the <option>-a</option>/<option>--all</option> is used, conne= ct + to this database to gather the list of databases to repack. + If not specified, the <literal>postgres</literal> database will be= used, + or if that does not exist, <literal>template1</literal> will be us= ed. + This can be a <link linkend=3D"libpq-connstring">connection + string</link>. If so, connection string parameters will override = any + conflicting command line options. Also, connection string paramet= ers + other than the database name itself will be re-used when connecting + to other databases. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </refsect1> + + + <refsect1> + <title>Environment</title> + + <variablelist> + <varlistentry> + <term><envar>PGDATABASE</envar></term> + <term><envar>PGHOST</envar></term> + <term><envar>PGPORT</envar></term> + <term><envar>PGUSER</envar></term> + + <listitem> + <para> + Default connection parameters + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><envar>PG_COLOR</envar></term> + <listitem> + <para> + Specifies whether to use color in diagnostic messages. Possible valu= es + are <literal>always</literal>, <literal>auto</literal> and + <literal>never</literal>. + </para> + </listitem> + </varlistentry> + </variablelist> + + <para> + This utility, like most other <productname>PostgreSQL</productname> uti= lities, + also uses the environment variables supported by <application>libpq</ap= plication> + (see <xref linkend=3D"libpq-envars"/>). + </para> + + </refsect1> + + + <refsect1> + <title>Diagnostics</title> + + <para> + In case of difficulty, see + <xref linkend=3D"sql-repack"/> and <xref linkend=3D"app-psql"/> for + discussions of potential problems and error messages. + The database server must be running at the + targeted host. Also, any default connection settings and environment + variables used by the <application>libpq</application> front-end + library will apply. + </para> + + </refsect1> + + <refsect1> + <title>Examples</title> + + <para> + To repack the database <literal>test</literal>: +<screen> +<prompt>$ </prompt><userinput>pg_repackdb test</userinput> +</screen> + </para> + + <para> + To repack and analyze for the optimizer a database named + <literal>bigdb</literal>: +<screen> +<prompt>$ </prompt><userinput>pg_repackdb --analyze bigdb</userinput> +</screen> + </para> + + <para> + To repack a single table + <literal>foo</literal> in a database named + <literal>xyzzy</literal>, and analyze a single column + <literal>bar</literal> of the table for the optimizer: +<screen> +<prompt>$ </prompt><userinput>pg_repackdb --analyze --verbose --table=3D'f= oo(bar)' xyzzy</userinput> +</screen></para> + + <para> + To repack all tables in the <literal>foo</literal> and <literal>bar</l= iteral> schemas + in a database named <literal>xyzzy</literal>: +<screen> +<prompt>$ </prompt><userinput>pg_repackdb --schema=3D'foo' --schema=3D'bar= ' xyzzy</userinput> +</screen></para> + + + </refsect1> + + <refsect1> + <title>See Also</title> + + <simplelist type=3D"inline"> + <member><xref linkend=3D"sql-repack"/></member> + </simplelist> + </refsect1> + +</refentry> diff --git a/doc/src/sgml/ref/repack.sgml b/doc/src/sgml/ref/repack.sgml new file mode 100644 index 00000000000..61d5c2cdef1 --- /dev/null +++ b/doc/src/sgml/ref/repack.sgml @@ -0,0 +1,328 @@ +<!-- +doc/src/sgml/ref/repack.sgml +PostgreSQL documentation +--> + +<refentry id=3D"sql-repack"> + <indexterm zone=3D"sql-repack"> + <primary>REPACK</primary> + </indexterm> + + <refmeta> + <refentrytitle>REPACK</refentrytitle> + <manvolnum>7</manvolnum> + <refmiscinfo>SQL - Language Statements</refmiscinfo> + </refmeta> + + <refnamediv> + <refname>REPACK</refname> + <refpurpose>rewrite a table to reclaim disk space</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +REPACK [ ( <replaceable class=3D"parameter">option</replaceable> [, ...] )= ] [ <replaceable class=3D"parameter">table_and_columns</replaceable> [ USI= NG INDEX [ <replaceable class=3D"parameter">index_name</replaceable> ] ] ] +REPACK [ ( <replaceable class=3D"parameter">option</replaceable> [, ...] )= ] USING INDEX + +<phrase>where <replaceable class=3D"parameter">option</replaceable> can be= one of:</phrase> + + VERBOSE [ <replaceable class=3D"parameter">boolean</replaceable> ] + ANALYZE [ <replaceable class=3D"parameter">boolean</replaceable> ] + +<phrase>and <replaceable class=3D"parameter">table_and_columns</replaceabl= e> is:</phrase> + + <replaceable class=3D"parameter">table_name</replaceable> [ ( <replace= able class=3D"parameter">column_name</replaceable> [, ...] ) ] +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <command>REPACK</command> reclaims storage occupied by dead + tuples. Unlike <command>VACUUM</command>, it does so by rewriting the + entire contents of the table specified + by <replaceable class=3D"parameter">table_name</replaceable> into a new= disk + file with no extra space (except for the space guaranteed by + the <literal>fillfactor</literal> storage parameter), allowing unused s= pace + to be returned to the operating system. + </para> + + <para> + Without + a <replaceable class=3D"parameter">table_name</replaceable>, <command>R= EPACK</command> + processes every table and materialized view in the current database that + the current user has the <literal>MAINTAIN</literal> privilege on. This + form of <command>REPACK</command> cannot be executed inside a transacti= on + block. + </para> + + <para> + If a <literal>USING INDEX</literal> clause is specified, the rows are + physically reordered based on information from an index. Please see the + notes on clustering below. + </para> + + <para> + When a table is being repacked, an <literal>ACCESS EXCLUSIVE</literal> = lock + is acquired on it. This prevents any other database operations (both re= ads + and writes) from operating on the table until the <command>REPACK</comm= and> + is finished. + </para> + + <refsect2 id=3D"sql-repack-notes-on-clustering" xreflabel=3D"Notes on Cl= ustering"> + <title>Notes on Clustering</title> + + <para> + If the <literal>USING INDEX</literal> clause is specified, the rows in + the table are physically reordered following an index: if an index name + is specified in the command, then that index is used; if no index name + is specified, then the index that has been configured as the index to + cluster on. If no index has been configured in this way, an error is + thrown. The index given in the <literal>USING INDEX</literal> clause + is configured as the index to cluster on, as well as an index given + to the <command>CLUSTER</command> command. An index can be set + manually using <command>ALTER TABLE ... CLUSTER ON</command>, and reset + with <command>ALTER TABLE ... SET WITHOUT CLUSTER</command>. + </para> + + <para> + If no table name is specified in <command>REPACK USING INDEX</command>, + all tables which have a clustering index defined and which the calling + user has privileges for are processed. + </para> + + <para> + Clustering is a one-time operation: when the table is + subsequently updated, the changes are not clustered. That is, no atte= mpt + is made to store new or updated rows according to their index order. = (If + one wishes, one can periodically recluster by issuing the command agai= n. + Also, setting the table's <literal>fillfactor</literal> storage parame= ter + to less than 100% can aid in preserving cluster ordering during update= s, + since updated rows are kept on the same page if enough space is availa= ble + there.) + </para> + + <para> + In cases where you are accessing single rows randomly within a table, = the + actual order of the data in the table is unimportant. However, if you = tend + to access some data more than others, and there is an index that groups + them together, you will benefit from using clustering. If + you are requesting a range of indexed values from a table, or a single + indexed value that has multiple rows that match, + <command>REPACK</command> will help because once the index identifies = the + table page for the first row that matches, all other rows that match a= re + probably already on the same table page, and so you save disk accesses= and + speed up the query. + </para> + + <para> + <command>REPACK</command> can re-sort the table using either an index = scan + on the specified index (if the index is a b-tree), or a sequential scan + followed by sorting. It will attempt to choose the method that will be + faster, based on planner cost parameters and available statistical + information. + </para> + + <para> + Because the planner records statistics about the ordering of tables, i= t is + advisable to + run <link linkend=3D"sql-analyze"><command>ANALYZE</command></link> on= the + newly repacked table. Otherwise, the planner might make poor choices = of + query plans. + </para> + </refsect2> + + <refsect2 id=3D"sql-repack-notes-on-resources" xreflabel=3D"Notes on Res= ources"> + <title>Notes on Resources</title> + + <para> + When an index scan or a sequential scan without sort is used, a tempor= ary + copy of the table is created that contains the table data in the index + order. Temporary copies of each index on the table are created as wel= l. + Therefore, you need free space on disk at least equal to the sum of the + table size and the index sizes. + </para> + + <para> + When a sequential scan and sort is used, a temporary sort file is also + created, so that the peak temporary space requirement is as much as do= uble + the table size, plus the index sizes. This method is often faster than + the index scan method, but if the disk space requirement is intolerabl= e, + you can disable this choice by temporarily setting + <xref linkend=3D"guc-enable-sort"/> to <literal>off</literal>. + </para> + + <para> + It is advisable to set <xref linkend=3D"guc-maintenance-work-mem"/> to= a + reasonably large value (but not more than the amount of RAM you can + dedicate to the <command>REPACK</command> operation) before repacking. + </para> + </refsect2> + + </refsect1> + + <refsect1> + <title>Parameters</title> + + <variablelist> + <varlistentry> + <term><replaceable class=3D"parameter">table_name</replaceable></term> + <listitem> + <para> + The name (possibly schema-qualified) of a table. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class=3D"parameter">column_name</replaceable></term> + <listitem> + <para> + The name of a specific column to analyze. Defaults to all columns. + If a column list is specific, <literal>ANALYZE</literal> must also + be specified. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class=3D"parameter">index_name</replaceable></term> + <listitem> + <para> + The name of an index. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>VERBOSE</literal></term> + <listitem> + <para> + Prints a progress report as each table is repacked + at <literal>INFO</literal> level. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>ANALYZE</literal></term> + <term><literal>ANALYSE</literal></term> + <listitem> + <para> + Applies <xref linkend=3D"sql-analyze"/> on the table after repacking= . This is + currently only supported when a single (non-partitioned) table is sp= ecified. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class=3D"parameter">boolean</replaceable></term> + <listitem> + <para> + Specifies whether the selected option should be turned on or off. + You can write <literal>TRUE</literal>, <literal>ON</literal>, or + <literal>1</literal> to enable the option, and <literal>FALSE</liter= al>, + <literal>OFF</literal>, or <literal>0</literal> to disable it. The + <replaceable class=3D"parameter">boolean</replaceable> value can also + be omitted, in which case <literal>TRUE</literal> is assumed. + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Notes</title> + + <para> + To repack a table, one must have the <literal>MAINTAIN</literal> privi= lege + on the table. + </para> + + <para> + While <command>REPACK</command> is running, the <xref + linkend=3D"guc-search-path"/> is temporarily changed to <literal>pg_ca= talog, + pg_temp</literal>. + </para> + + <para> + Each backend running <command>REPACK</command> will report its progress + in the <structname>pg_stat_progress_repack</structname> view. See + <xref linkend=3D"repack-progress-reporting"/> for details. + </para> + + <para> + Repacking a partitioned table repacks each of its partitions. If an in= dex + is specified, each partition is repacked using the partition of that + index. <command>REPACK</command> on a partitioned table cannot be exec= uted + inside a transaction block. + </para> + + </refsect1> + + <refsect1> + <title>Examples</title> + + <para> + Repack the table <literal>employees</literal>: +<programlisting> +REPACK employees; +</programlisting> + </para> + + <para> + Repack the table <literal>employees</literal> on the basis of its + index <literal>employees_ind</literal> (Since index is used here, this = is + effectively clustering): +<programlisting> +REPACK employees USING INDEX employees_ind; +</programlisting> + </para> + + <para> + Repack the table <literal>cases</literal> on physical ordering, + running an <command>ANALYZE</command> on the given columns once + repacking is done, showing informational messages: +<programlisting> +REPACK (ANALYZE, VERBOSE) cases (district, case_nr); +</programlisting> + </para> + + <para> + Repack all tables in the database on which you have + the <literal>MAINTAIN</literal> privilege: +<programlisting> +REPACK; +</programlisting> + </para> + + <para> + Repack all tables for which a clustering index has previously been + configured on which you have the <literal>MAINTAIN</literal> privilege, + showing informational messages: +<programlisting> +REPACK (VERBOSE) USING INDEX; +</programlisting> + </para> + + </refsect1> + + <refsect1> + <title>Compatibility</title> + + <para> + There is no <command>REPACK</command> statement in the SQL standard. + </para> + </refsect1> + + <refsect1> + <title>See Also</title> + + <simplelist type=3D"inline"> + <member><xref linkend=3D"app-pgrepackdb"/></member> + <member><xref linkend=3D"repack-progress-reporting"/></member> + </simplelist> + </refsect1> + +</refentry> diff --git a/doc/src/sgml/ref/vacuum.sgml b/doc/src/sgml/ref/vacuum.sgml index 6d0fdd43cfb..ac5d083d468 100644 --- a/doc/src/sgml/ref/vacuum.sgml +++ b/doc/src/sgml/ref/vacuum.sgml @@ -25,7 +25,6 @@ VACUUM [ ( <replaceable class=3D"parameter">option</repla= ceable> [, ...] ) ] [ <re =20 <phrase>where <replaceable class=3D"parameter">option</replaceable> can be= one of:</phrase> =20 - FULL [ <replaceable class=3D"parameter">boolean</replaceable> ] FREEZE [ <replaceable class=3D"parameter">boolean</replaceable> ] VERBOSE [ <replaceable class=3D"parameter">boolean</replaceable> ] ANALYZE [ <replaceable class=3D"parameter">boolean</replaceable> ] @@ -39,6 +38,7 @@ VACUUM [ ( <replaceable class=3D"parameter">option</repla= ceable> [, ...] ) ] [ <re SKIP_DATABASE_STATS [ <replaceable class=3D"parameter">boolean</replac= eable> ] ONLY_DATABASE_STATS [ <replaceable class=3D"parameter">boolean</replac= eable> ] BUFFER_USAGE_LIMIT <replaceable class=3D"parameter">size</replaceable> + FULL [ <replaceable class=3D"parameter">boolean</replaceable> ] =20 <phrase>and <replaceable class=3D"parameter">table_and_columns</replaceabl= e> is:</phrase> =20 @@ -95,20 +95,6 @@ VACUUM [ ( <replaceable class=3D"parameter">option</repl= aceable> [, ...] ) ] [ <re <title>Parameters</title> =20 <variablelist> - <varlistentry> - <term><literal>FULL</literal></term> - <listitem> - <para> - Selects <quote>full</quote> vacuum, which can reclaim more - space, but takes much longer and exclusively locks the table. - This method also requires extra disk space, since it writes a - new copy of the table and doesn't release the old copy until - the operation is complete. Usually this should only be used when a - significant amount of space needs to be reclaimed from within the ta= ble. - </para> - </listitem> - </varlistentry> - <varlistentry> <term><literal>FREEZE</literal></term> <listitem> @@ -362,6 +348,23 @@ VACUUM [ ( <replaceable class=3D"parameter">option</re= placeable> [, ...] ) ] [ <re </listitem> </varlistentry> =20 + <varlistentry> + <term><literal>FULL</literal></term> + <listitem> + <para> + This option, which is deprecated, makes <command>VACUUM</command> + behave like <command>REPACK</command> without a + <literal>USING INDEX</literal> clause. + This method of compacting the table takes much longer than + <command>VACUUM</command> and exclusively locks the table. + This method also requires extra disk space, since it writes a + new copy of the table and doesn't release the old copy until + the operation is complete. Usually this should only be used when a + significant amount of space needs to be reclaimed from within the ta= ble. + </para> + </listitem> + </varlistentry> + <varlistentry> <term><replaceable class=3D"parameter">boolean</replaceable></term> <listitem> diff --git a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml index 2cf02c37b17..5d9a8a25a02 100644 --- a/doc/src/sgml/reference.sgml +++ b/doc/src/sgml/reference.sgml @@ -195,6 +195,7 @@ &refreshMaterializedView; &reindex; &releaseSavepoint; + &repack; &reset; &revoke; &rollback; @@ -258,6 +259,7 @@ &pgIsready; &pgReceivewal; &pgRecvlogical; + &pgRepackdb; &pgRestore; &pgVerifyBackup; &psqlRef; diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/= heap/heapam_handler.c index cbef73e5d4b..7d4b48e5a97 100644 --- a/src/backend/access/heap/heapam_handler.c +++ b/src/backend/access/heap/heapam_handler.c @@ -741,13 +741,13 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Re= lation NewHeap, if (OldIndex !=3D NULL && !use_sort) { const int ci_index[] =3D { - PROGRESS_CLUSTER_PHASE, - PROGRESS_CLUSTER_INDEX_RELID + PROGRESS_REPACK_PHASE, + PROGRESS_REPACK_INDEX_RELID }; int64 ci_val[2]; =20 /* Set phase and OIDOldIndex to columns */ - ci_val[0] =3D PROGRESS_CLUSTER_PHASE_INDEX_SCAN_HEAP; + ci_val[0] =3D PROGRESS_REPACK_PHASE_INDEX_SCAN_HEAP; ci_val[1] =3D RelationGetRelid(OldIndex); pgstat_progress_update_multi_param(2, ci_index, ci_val); =20 @@ -759,15 +759,15 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Re= lation NewHeap, else { /* In scan-and-sort mode and also VACUUM FULL, set phase */ - pgstat_progress_update_param(PROGRESS_CLUSTER_PHASE, - PROGRESS_CLUSTER_PHASE_SEQ_SCAN_HEAP); + pgstat_progress_update_param(PROGRESS_REPACK_PHASE, + PROGRESS_REPACK_PHASE_SEQ_SCAN_HEAP); =20 tableScan =3D table_beginscan(OldHeap, SnapshotAny, 0, (ScanKey) NULL); heapScan =3D (HeapScanDesc) tableScan; indexScan =3D NULL; =20 /* Set total heap blocks */ - pgstat_progress_update_param(PROGRESS_CLUSTER_TOTAL_HEAP_BLKS, + pgstat_progress_update_param(PROGRESS_REPACK_TOTAL_HEAP_BLKS, heapScan->rs_nblocks); } =20 @@ -809,7 +809,7 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Rela= tion NewHeap, * is manually updated to the correct value when the table * scan finishes. */ - pgstat_progress_update_param(PROGRESS_CLUSTER_HEAP_BLKS_SCANNED, + pgstat_progress_update_param(PROGRESS_REPACK_HEAP_BLKS_SCANNED, heapScan->rs_nblocks); break; } @@ -825,7 +825,7 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Rela= tion NewHeap, */ if (prev_cblock !=3D heapScan->rs_cblock) { - pgstat_progress_update_param(PROGRESS_CLUSTER_HEAP_BLKS_SCANNED, + pgstat_progress_update_param(PROGRESS_REPACK_HEAP_BLKS_SCANNED, (heapScan->rs_cblock + heapScan->rs_nblocks - heapScan->rs_startblock @@ -926,14 +926,14 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Re= lation NewHeap, * In scan-and-sort mode, report increase in number of tuples * scanned */ - pgstat_progress_update_param(PROGRESS_CLUSTER_HEAP_TUPLES_SCANNED, + pgstat_progress_update_param(PROGRESS_REPACK_HEAP_TUPLES_SCANNED, *num_tuples); } else { const int ct_index[] =3D { - PROGRESS_CLUSTER_HEAP_TUPLES_SCANNED, - PROGRESS_CLUSTER_HEAP_TUPLES_WRITTEN + PROGRESS_REPACK_HEAP_TUPLES_SCANNED, + PROGRESS_REPACK_HEAP_TUPLES_WRITTEN }; int64 ct_val[2]; =20 @@ -966,14 +966,14 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Re= lation NewHeap, double n_tuples =3D 0; =20 /* Report that we are now sorting tuples */ - pgstat_progress_update_param(PROGRESS_CLUSTER_PHASE, - PROGRESS_CLUSTER_PHASE_SORT_TUPLES); + pgstat_progress_update_param(PROGRESS_REPACK_PHASE, + PROGRESS_REPACK_PHASE_SORT_TUPLES); =20 tuplesort_performsort(tuplesort); =20 /* Report that we are now writing new heap */ - pgstat_progress_update_param(PROGRESS_CLUSTER_PHASE, - PROGRESS_CLUSTER_PHASE_WRITE_NEW_HEAP); + pgstat_progress_update_param(PROGRESS_REPACK_PHASE, + PROGRESS_REPACK_PHASE_WRITE_NEW_HEAP); =20 for (;;) { @@ -991,7 +991,7 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Rela= tion NewHeap, values, isnull, rwstate); /* Report n_tuples */ - pgstat_progress_update_param(PROGRESS_CLUSTER_HEAP_TUPLES_WRITTEN, + pgstat_progress_update_param(PROGRESS_REPACK_HEAP_TUPLES_WRITTEN, n_tuples); } =20 diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 43de42ce39e..5ee6389d39c 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -4077,7 +4077,7 @@ reindex_relation(const ReindexStmt *stmt, Oid relid, = int flags, Assert(!ReindexIsProcessingIndex(indexOid)); =20 /* Set index rebuild count */ - pgstat_progress_update_param(PROGRESS_CLUSTER_INDEX_REBUILD_COUNT, + pgstat_progress_update_param(PROGRESS_REPACK_INDEX_REBUILD_COUNT, i); i++; } diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/sys= tem_views.sql index 7553f31fef0..3f05ba3083a 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -1283,14 +1283,15 @@ CREATE VIEW pg_stat_progress_vacuum AS FROM pg_stat_get_progress_info('VACUUM') AS S LEFT JOIN pg_database D ON S.datid =3D D.oid; =20 -CREATE VIEW pg_stat_progress_cluster AS +CREATE VIEW pg_stat_progress_repack AS SELECT S.pid AS pid, S.datid AS datid, D.datname AS datname, S.relid AS relid, CASE S.param1 WHEN 1 THEN 'CLUSTER' - WHEN 2 THEN 'VACUUM FULL' + WHEN 2 THEN 'REPACK' + WHEN 3 THEN 'VACUUM FULL' END AS command, CASE S.param2 WHEN 0 THEN 'initializing' WHEN 1 THEN 'seq scanning heap' @@ -1301,15 +1302,35 @@ CREATE VIEW pg_stat_progress_cluster AS WHEN 6 THEN 'rebuilding index' WHEN 7 THEN 'performing final cleanup' END AS phase, - CAST(S.param3 AS oid) AS cluster_index_relid, + CAST(S.param3 AS oid) AS repack_index_relid, S.param4 AS heap_tuples_scanned, S.param5 AS heap_tuples_written, S.param6 AS heap_blks_total, S.param7 AS heap_blks_scanned, S.param8 AS index_rebuild_count - FROM pg_stat_get_progress_info('CLUSTER') AS S + FROM pg_stat_get_progress_info('REPACK') AS S LEFT JOIN pg_database D ON S.datid =3D D.oid; =20 +-- This view is as the one above, except for renaming a column and avoiding +-- 'REPACK' as a command name to report. +CREATE VIEW pg_stat_progress_cluster AS + SELECT + pid, + datid, + datname, + relid, + CASE WHEN command IN ('CLUSTER', 'VACUUM FULL') THEN command + WHEN repack_index_relid =3D 0 THEN 'VACUUM FULL' + ELSE 'CLUSTER' END AS command, + phase, + repack_index_relid AS cluster_index_relid, + heap_tuples_scanned, + heap_tuples_written, + heap_blks_total, + heap_blks_scanned, + index_rebuild_count + FROM pg_stat_progress_repack; + CREATE VIEW pg_stat_progress_create_index AS SELECT S.pid AS pid, S.datid AS datid, D.datname AS datname, diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index 60a4617a585..e19675a6d05 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -1,7 +1,8 @@ /*------------------------------------------------------------------------- * * cluster.c - * CLUSTER a table on an index. This is now also used for VACUUM FULL. + * CLUSTER a table on an index. This is now also used for VACUUM FULL a= nd + * REPACK. * * There is hardly anything left of Paul Brown's original implementation... * @@ -67,27 +68,35 @@ typedef struct Oid indexOid; } RelToCluster; =20 - -static void cluster_multiple_rels(List *rtcs, ClusterParams *params); +static bool cluster_rel_recheck(RepackCommand cmd, Relation OldHeap, + Oid indexOid, Oid userid, int options); static void rebuild_relation(Relation OldHeap, Relation index, bool verbos= e); static void copy_table_data(Relation NewHeap, Relation OldHeap, Relation O= ldIndex, bool verbose, bool *pSwapToastByContent, TransactionId *pFreezeXid, MultiXactId *pCutoffMulti); -static List *get_tables_to_cluster(MemoryContext cluster_context); -static List *get_tables_to_cluster_partitioned(MemoryContext cluster_conte= xt, - Oid indexOid); -static bool cluster_is_permitted_for_relation(Oid relid, Oid userid); +static List *get_tables_to_repack(RepackCommand cmd, bool usingindex, + MemoryContext permcxt); +static List *get_tables_to_repack_partitioned(RepackCommand cmd, + Oid relid, bool rel_is_index, + MemoryContext permcxt); +static bool cluster_is_permitted_for_relation(RepackCommand cmd, + Oid relid, Oid userid); +static Relation process_single_relation(RepackStmt *stmt, + ClusterParams *params); +static Oid determine_clustered_index(Relation rel, bool usingindex, + const char *indexname); +static const char *RepackCommandAsString(RepackCommand cmd); =20 =20 -/*------------------------------------------------------------------------= --- - * This cluster code allows for clustering multiple tables at once. Because +/* + * The repack code allows for processing multiple tables at once. Because * of this, we cannot just run everything on a single transaction, or we * would be forced to acquire exclusive locks on all the tables being * clustered, simultaneously --- very likely leading to deadlock. * - * To solve this we follow a similar strategy to VACUUM code, - * clustering each relation in a separate transaction. For this to work, - * we need to: + * To solve this we follow a similar strategy to VACUUM code, processing e= ach + * relation in a separate transaction. For this to work, we need to: + * * - provide a separate memory context so that we can pass information in * a way that survives across transactions * - start a new transaction every time a new relation is clustered @@ -98,197 +107,166 @@ static bool cluster_is_permitted_for_relation(Oid re= lid, Oid userid); * * The single-relation case does not have any such overhead. * - * We also allow a relation to be specified without index. In that case, - * the indisclustered bit will be looked up, and an ERROR will be thrown - * if there is no index with the bit set. - *------------------------------------------------------------------------= --- + * We also allow a relation to be repacked following an index, but without + * naming a specific one. In that case, the indisclustered bit will be + * looked up, and an ERROR will be thrown if no so-marked index is found. */ void -cluster(ParseState *pstate, ClusterStmt *stmt, bool isTopLevel) +ExecRepack(ParseState *pstate, RepackStmt *stmt, bool isTopLevel) { - ListCell *lc; ClusterParams params =3D {0}; - bool verbose =3D false; Relation rel =3D NULL; - Oid indexOid =3D InvalidOid; - MemoryContext cluster_context; + MemoryContext repack_context; List *rtcs; =20 /* Parse option list */ - foreach(lc, stmt->params) + foreach_node(DefElem, opt, stmt->params) { - DefElem *opt =3D (DefElem *) lfirst(lc); - if (strcmp(opt->defname, "verbose") =3D=3D 0) - verbose =3D defGetBoolean(opt); + params.options |=3D defGetBoolean(opt) ? CLUOPT_VERBOSE : 0; + else if (strcmp(opt->defname, "analyze") =3D=3D 0 || + strcmp(opt->defname, "analyse") =3D=3D 0) + params.options |=3D defGetBoolean(opt) ? CLUOPT_ANALYZE : 0; else ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("unrecognized %s option \"%s\"", - "CLUSTER", opt->defname), - parser_errposition(pstate, opt->location))); + errcode(ERRCODE_SYNTAX_ERROR), + errmsg("unrecognized %s option \"%s\"", + RepackCommandAsString(stmt->command), + opt->defname), + parser_errposition(pstate, opt->location)); } =20 - params.options =3D (verbose ? CLUOPT_VERBOSE : 0); - + /* + * If a single relation is specified, process it and we're done ... unless + * the relation is a partitioned table, in which case we fall through. + */ if (stmt->relation !=3D NULL) { - /* This is the single-relation case. */ - Oid tableOid; - - /* - * Find, lock, and check permissions on the table. We obtain - * AccessExclusiveLock right away to avoid lock-upgrade hazard in the - * single-transaction case. - */ - tableOid =3D RangeVarGetRelidExtended(stmt->relation, - AccessExclusiveLock, - 0, - RangeVarCallbackMaintainsTable, - NULL); - rel =3D table_open(tableOid, NoLock); - - /* - * Reject clustering a remote temp table ... their local buffer - * manager is not going to cope. - */ - if (RELATION_IS_OTHER_TEMP(rel)) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot cluster temporary tables of other sessions"))); - - if (stmt->indexname =3D=3D NULL) - { - ListCell *index; - - /* We need to find the index that has indisclustered set. */ - foreach(index, RelationGetIndexList(rel)) - { - indexOid =3D lfirst_oid(index); - if (get_index_isclustered(indexOid)) - break; - indexOid =3D InvalidOid; - } - - if (!OidIsValid(indexOid)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("there is no previously clustered index for table \"%s\"", - stmt->relation->relname))); - } - else - { - /* - * The index is expected to be in the same namespace as the - * relation. - */ - indexOid =3D get_relname_relid(stmt->indexname, - rel->rd_rel->relnamespace); - if (!OidIsValid(indexOid)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("index \"%s\" for table \"%s\" does not exist", - stmt->indexname, stmt->relation->relname))); - } - - /* For non-partitioned tables, do what we came here to do. */ - if (rel->rd_rel->relkind !=3D RELKIND_PARTITIONED_TABLE) - { - cluster_rel(rel, indexOid, ¶ms); - /* cluster_rel closes the relation, but keeps lock */ - - return; - } + rel =3D process_single_relation(stmt, ¶ms); + if (rel =3D=3D NULL) + return; /* all done */ } =20 + /* + * Don't allow ANALYZE in the multiple-relation case for now. Maybe we + * can add support for this later. + */ + if (params.options & CLUOPT_ANALYZE) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot %s multiple tables", "REPACK (ANALYZE)")); + /* * By here, we know we are in a multi-table situation. In order to avoid * holding locks for too long, we want to process each table in its own * transaction. This forces us to disallow running inside a user * transaction block. */ - PreventInTransactionBlock(isTopLevel, "CLUSTER"); + PreventInTransactionBlock(isTopLevel, RepackCommandAsString(stmt->command= )); =20 /* Also, we need a memory context to hold our list of relations */ - cluster_context =3D AllocSetContextCreate(PortalContext, - "Cluster", - ALLOCSET_DEFAULT_SIZES); + repack_context =3D AllocSetContextCreate(PortalContext, + "Repack", + ALLOCSET_DEFAULT_SIZES); + + params.options |=3D CLUOPT_RECHECK; =20 /* - * Either we're processing a partitioned table, or we were not given any - * table name at all. In either case, obtain a list of relations to - * process. - * - * In the former case, an index name must have been given, so we don't - * need to recheck its "indisclustered" bit, but we have to check that it - * is an index that we can cluster on. In the latter case, we set the - * option bit to have indisclustered verified. - * - * Rechecking the relation itself is necessary here in all cases. + * If we don't have a relation yet, determine a relation list. If we do, + * then it must be a partitioned table, and we want to process its + * partitions. */ - params.options |=3D CLUOPT_RECHECK; - if (rel !=3D NULL) + if (rel =3D=3D NULL) { - Assert(rel->rd_rel->relkind =3D=3D RELKIND_PARTITIONED_TABLE); - check_index_is_clusterable(rel, indexOid, AccessShareLock); - rtcs =3D get_tables_to_cluster_partitioned(cluster_context, indexOid); - - /* close relation, releasing lock on parent table */ - table_close(rel, AccessExclusiveLock); + Assert(stmt->indexname =3D=3D NULL); + rtcs =3D get_tables_to_repack(stmt->command, stmt->usingindex, + repack_context); + params.options |=3D CLUOPT_RECHECK_ISCLUSTERED; } else { - rtcs =3D get_tables_to_cluster(cluster_context); - params.options |=3D CLUOPT_RECHECK_ISCLUSTERED; - } + Oid relid; + bool rel_is_index; =20 - /* Do the job. */ - cluster_multiple_rels(rtcs, ¶ms); + Assert(rel->rd_rel->relkind =3D=3D RELKIND_PARTITIONED_TABLE); =20 - /* Start a new transaction for the cleanup work. */ - StartTransactionCommand(); + /* + * If USING INDEX was specified, resolve the index name now and pass + * it down. + */ + if (stmt->usingindex) + { + /* + * If no index name was specified when repacking a partitioned + * table, punt for now. Maybe we can improve this later. + */ + if (!stmt->indexname) + ereport(ERROR, + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("there is no previously clustered index for table \"%s\"", + RelationGetRelationName(rel))); + + relid =3D determine_clustered_index(rel, stmt->usingindex, + stmt->indexname); + if (!OidIsValid(relid)) + elog(ERROR, "unable to determine index to cluster on"); + /* XXX is this the right place for this check? */ + check_index_is_clusterable(rel, relid, AccessExclusiveLock); + rel_is_index =3D true; + } + else + { + relid =3D RelationGetRelid(rel); + rel_is_index =3D false; + } =20 - /* Clean up working storage */ - MemoryContextDelete(cluster_context); -} + rtcs =3D get_tables_to_repack_partitioned(stmt->command, + relid, rel_is_index, + repack_context); =20 -/* - * Given a list of relations to cluster, process each of them in a separate - * transaction. - * - * We expect to be in a transaction at start, but there isn't one when we - * return. - */ -static void -cluster_multiple_rels(List *rtcs, ClusterParams *params) -{ - ListCell *lc; + /* close parent relation, releasing lock on it */ + table_close(rel, AccessExclusiveLock); + rel =3D NULL; + } =20 /* Commit to get out of starting transaction */ PopActiveSnapshot(); CommitTransactionCommand(); =20 /* Cluster the tables, each in a separate transaction */ - foreach(lc, rtcs) + Assert(rel =3D=3D NULL); + foreach_ptr(RelToCluster, rtc, rtcs) { - RelToCluster *rtc =3D (RelToCluster *) lfirst(lc); - Relation rel; - /* Start a new transaction for each relation. */ StartTransactionCommand(); =20 + /* + * Open the target table, coping with the case where it has been + * dropped. + */ + rel =3D try_table_open(rtc->tableOid, AccessExclusiveLock); + if (rel =3D=3D NULL) + { + CommitTransactionCommand(); + continue; + } + /* functions in indexes may want a snapshot set */ PushActiveSnapshot(GetTransactionSnapshot()); =20 - rel =3D table_open(rtc->tableOid, AccessExclusiveLock); - /* Process this table */ - cluster_rel(rel, rtc->indexOid, params); + cluster_rel(stmt->command, rel, rtc->indexOid, ¶ms); /* cluster_rel closes the relation, but keeps lock */ =20 PopActiveSnapshot(); CommitTransactionCommand(); } + + /* Start a new transaction for the cleanup work. */ + StartTransactionCommand(); + + /* Clean up working storage */ + MemoryContextDelete(repack_context); } =20 /* @@ -304,11 +282,14 @@ cluster_multiple_rels(List *rtcs, ClusterParams *para= ms) * them incrementally while we load the table. * * If indexOid is InvalidOid, the table will be rewritten in physical order - * instead of index order. This is the new implementation of VACUUM FULL, - * and error messages should refer to the operation as VACUUM not CLUSTER. + * instead of index order. + * + * 'cmd' indicates which command is being executed, to be used for error + * messages. */ void -cluster_rel(Relation OldHeap, Oid indexOid, ClusterParams *params) +cluster_rel(RepackCommand cmd, Relation OldHeap, Oid indexOid, + ClusterParams *params) { Oid tableOid =3D RelationGetRelid(OldHeap); Oid save_userid; @@ -323,13 +304,8 @@ cluster_rel(Relation OldHeap, Oid indexOid, ClusterPar= ams *params) /* Check for user-requested abort. */ CHECK_FOR_INTERRUPTS(); =20 - pgstat_progress_start_command(PROGRESS_COMMAND_CLUSTER, tableOid); - if (OidIsValid(indexOid)) - pgstat_progress_update_param(PROGRESS_CLUSTER_COMMAND, - PROGRESS_CLUSTER_COMMAND_CLUSTER); - else - pgstat_progress_update_param(PROGRESS_CLUSTER_COMMAND, - PROGRESS_CLUSTER_COMMAND_VACUUM_FULL); + pgstat_progress_start_command(PROGRESS_COMMAND_REPACK, tableOid); + pgstat_progress_update_param(PROGRESS_REPACK_COMMAND, cmd); =20 /* * Switch to the table owner's userid, so that any index functions are run @@ -350,86 +326,38 @@ cluster_rel(Relation OldHeap, Oid indexOid, ClusterPa= rams *params) * *must* skip the one on indisclustered since it would reject an attempt * to cluster a not-previously-clustered index. */ - if (recheck) - { - /* Check that the user still has privileges for the relation */ - if (!cluster_is_permitted_for_relation(tableOid, save_userid)) - { - relation_close(OldHeap, AccessExclusiveLock); - goto out; - } - - /* - * Silently skip a temp table for a remote session. Only doing this - * check in the "recheck" case is appropriate (which currently means - * somebody is executing a database-wide CLUSTER or on a partitioned - * table), because there is another check in cluster() which will stop - * any attempt to cluster remote temp tables by name. There is - * another check in cluster_rel which is redundant, but we leave it - * for extra safety. - */ - if (RELATION_IS_OTHER_TEMP(OldHeap)) - { - relation_close(OldHeap, AccessExclusiveLock); - goto out; - } - - if (OidIsValid(indexOid)) - { - /* - * Check that the index still exists - */ - if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(indexOid))) - { - relation_close(OldHeap, AccessExclusiveLock); - goto out; - } - - /* - * Check that the index is still the one with indisclustered set, - * if needed. - */ - if ((params->options & CLUOPT_RECHECK_ISCLUSTERED) !=3D 0 && - !get_index_isclustered(indexOid)) - { - relation_close(OldHeap, AccessExclusiveLock); - goto out; - } - } - } + if (recheck && + !cluster_rel_recheck(cmd, OldHeap, indexOid, save_userid, + params->options)) + goto out; =20 /* - * We allow VACUUM FULL, but not CLUSTER, on shared catalogs. CLUSTER - * would work in most respects, but the index would only get marked as - * indisclustered in the current database, leading to unexpected behavior - * if CLUSTER were later invoked in another database. + * We allow repacking shared catalogs only when not using an index. It + * would work to use an index in most respects, but the index would only + * get marked as indisclustered in the current database, leading to + * unexpected behavior if CLUSTER were later invoked in another database. */ if (OidIsValid(indexOid) && OldHeap->rd_rel->relisshared) ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot cluster a shared catalog"))); + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot run %s on a shared catalog", + RepackCommandAsString(cmd))); =20 /* * Don't process temp tables of other backends ... their local buffer * manager is not going to cope. */ if (RELATION_IS_OTHER_TEMP(OldHeap)) - { - if (OidIsValid(indexOid)) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot cluster temporary tables of other sessions"))); - else - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot vacuum temporary tables of other sessions"))); - } + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot run %s on temporary tables of other sessions", + RepackCommandAsString(cmd))); =20 /* * Also check for active uses of the relation in the current transaction, * including open scans and pending AFTER trigger events. */ - CheckTableNotInUse(OldHeap, OidIsValid(indexOid) ? "CLUSTER" : "VACUUM"); + CheckTableNotInUse(OldHeap, RepackCommandAsString(cmd)); =20 /* Check heap and index are valid to cluster on */ if (OidIsValid(indexOid)) @@ -442,6 +370,24 @@ cluster_rel(Relation OldHeap, Oid indexOid, ClusterPar= ams *params) else index =3D NULL; =20 + /* + * When allow_system_table_mods is turned off, we disallow repacking a + * catalog on a particular index unless that's already the clustered index + * for that catalog. + * + * XXX We don't check for this in CLUSTER, because it's historically been + * allowed. + */ + if (cmd !=3D REPACK_COMMAND_CLUSTER && + !allowSystemTableMods && OidIsValid(indexOid) && + IsCatalogRelation(OldHeap) && !index->rd_index->indisclustered) + ereport(ERROR, + errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied: \"%s\" is a system catalog", + RelationGetRelationName(OldHeap)), + errdetail("System catalogs can only be clustered by the index they're = already clustered on, if any, unless \"%s\" is enabled.", + "allow_system_table_mods")); + /* * Quietly ignore the request if this is a materialized view which has not * been populated from its query. No harm is done because there is no data @@ -482,6 +428,63 @@ out: pgstat_progress_end_command(); } =20 +/* + * Check if the table (and its index) still meets the requirements of + * cluster_rel(). + */ +static bool +cluster_rel_recheck(RepackCommand cmd, Relation OldHeap, Oid indexOid, + Oid userid, int options) +{ + Oid tableOid =3D RelationGetRelid(OldHeap); + + /* Check that the user still has privileges for the relation */ + if (!cluster_is_permitted_for_relation(cmd, tableOid, userid)) + { + relation_close(OldHeap, AccessExclusiveLock); + return false; + } + + /* + * Silently skip a temp table for a remote session. Only doing this check + * in the "recheck" case is appropriate (which currently means somebody is + * executing a database-wide CLUSTER or on a partitioned table), because + * there is another check in cluster() which will stop any attempt to + * cluster remote temp tables by name. There is another check in + * cluster_rel which is redundant, but we leave it for extra safety. + */ + if (RELATION_IS_OTHER_TEMP(OldHeap)) + { + relation_close(OldHeap, AccessExclusiveLock); + return false; + } + + if (OidIsValid(indexOid)) + { + /* + * Check that the index still exists + */ + if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(indexOid))) + { + relation_close(OldHeap, AccessExclusiveLock); + return false; + } + + /* + * Check that the index is still the one with indisclustered set, if + * needed. + */ + if ((options & CLUOPT_RECHECK_ISCLUSTERED) !=3D 0 && + !get_index_isclustered(indexOid)) + { + relation_close(OldHeap, AccessExclusiveLock); + return false; + } + } + + return true; +} + /* * Verify that the specified heap and index are valid to cluster on * @@ -642,8 +645,8 @@ rebuild_relation(Relation OldHeap, Relation index, bool= verbose) Assert(CheckRelationLockedByMe(OldHeap, AccessExclusiveLock, false) && (index =3D=3D NULL || CheckRelationLockedByMe(index, AccessExclusiveL= ock, false))); =20 - if (index) - /* Mark the correct index as clustered */ + /* for CLUSTER or REPACK USING INDEX, mark the index as the one to use */ + if (index !=3D NULL) mark_index_clustered(OldHeap, RelationGetRelid(index), true); =20 /* Remember info about rel before closing OldHeap */ @@ -958,20 +961,20 @@ copy_table_data(Relation NewHeap, Relation OldHeap, R= elation OldIndex, bool verb /* Log what we're doing */ if (OldIndex !=3D NULL && !use_sort) ereport(elevel, - (errmsg("clustering \"%s.%s\" using index scan on \"%s\"", - nspname, - RelationGetRelationName(OldHeap), - RelationGetRelationName(OldIndex)))); + errmsg("repacking \"%s.%s\" using index scan on \"%s\"", + nspname, + RelationGetRelationName(OldHeap), + RelationGetRelationName(OldIndex))); else if (use_sort) ereport(elevel, - (errmsg("clustering \"%s.%s\" using sequential scan and sort", - nspname, - RelationGetRelationName(OldHeap)))); + errmsg("repacking \"%s.%s\" using sequential scan and sort", + nspname, + RelationGetRelationName(OldHeap))); else ereport(elevel, - (errmsg("vacuuming \"%s.%s\"", - nspname, - RelationGetRelationName(OldHeap)))); + errmsg("repacking \"%s.%s\" in physical order", + nspname, + RelationGetRelationName(OldHeap))); =20 /* * Hand off the actual copying to AM specific function, the generic code @@ -1458,8 +1461,8 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap, int i; =20 /* Report that we are now swapping relation files */ - pgstat_progress_update_param(PROGRESS_CLUSTER_PHASE, - PROGRESS_CLUSTER_PHASE_SWAP_REL_FILES); + pgstat_progress_update_param(PROGRESS_REPACK_PHASE, + PROGRESS_REPACK_PHASE_SWAP_REL_FILES); =20 /* Zero out possible results from swapped_relation_files */ memset(mapped_tables, 0, sizeof(mapped_tables)); @@ -1509,14 +1512,14 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap, reindex_flags |=3D REINDEX_REL_FORCE_INDEXES_PERMANENT; =20 /* Report that we are now reindexing relations */ - pgstat_progress_update_param(PROGRESS_CLUSTER_PHASE, - PROGRESS_CLUSTER_PHASE_REBUILD_INDEX); + pgstat_progress_update_param(PROGRESS_REPACK_PHASE, + PROGRESS_REPACK_PHASE_REBUILD_INDEX); =20 reindex_relation(NULL, OIDOldHeap, reindex_flags, &reindex_params); =20 /* Report that we are now doing clean up */ - pgstat_progress_update_param(PROGRESS_CLUSTER_PHASE, - PROGRESS_CLUSTER_PHASE_FINAL_CLEANUP); + pgstat_progress_update_param(PROGRESS_REPACK_PHASE, + PROGRESS_REPACK_PHASE_FINAL_CLEANUP); =20 /* * If the relation being rebuilt is pg_class, swap_relation_files() @@ -1632,106 +1635,191 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap, } } =20 - /* - * Get a list of tables that the current user has privileges on and - * have indisclustered set. Return the list in a List * of RelToCluster - * (stored in the specified memory context), each one giving the tableOid - * and the indexOid on which the table is already clustered. + * Determine which relations to process, when REPACK/CLUSTER is called + * without specifying a table name. The exact process depends on whether + * USING INDEX was given or not, and in any case we only return tables and + * materialized views that the current user has privileges to repack/clust= er. + * + * If USING INDEX was given, we scan pg_index to find those that have + * indisclustered set; if it was not given, scan pg_class and return all + * tables. + * + * Return it as a list of RelToCluster in the given memory context. */ static List * -get_tables_to_cluster(MemoryContext cluster_context) +get_tables_to_repack(RepackCommand cmd, bool usingindex, MemoryContext per= mcxt) { - Relation indRelation; + Relation catalog; TableScanDesc scan; - ScanKeyData entry; - HeapTuple indexTuple; - Form_pg_index index; - MemoryContext old_context; + HeapTuple tuple; List *rtcs =3D NIL; =20 - /* - * Get all indexes that have indisclustered set and that the current user - * has the appropriate privileges for. - */ - indRelation =3D table_open(IndexRelationId, AccessShareLock); - ScanKeyInit(&entry, - Anum_pg_index_indisclustered, - BTEqualStrategyNumber, F_BOOLEQ, - BoolGetDatum(true)); - scan =3D table_beginscan_catalog(indRelation, 1, &entry); - while ((indexTuple =3D heap_getnext(scan, ForwardScanDirection)) !=3D NUL= L) + if (usingindex) { - RelToCluster *rtc; + ScanKeyData entry; + + catalog =3D table_open(IndexRelationId, AccessShareLock); + ScanKeyInit(&entry, + Anum_pg_index_indisclustered, + BTEqualStrategyNumber, F_BOOLEQ, + BoolGetDatum(true)); + scan =3D table_beginscan_catalog(catalog, 1, &entry); + while ((tuple =3D heap_getnext(scan, ForwardScanDirection)) !=3D NULL) + { + RelToCluster *rtc; + Form_pg_index index; + MemoryContext oldcxt; =20 - index =3D (Form_pg_index) GETSTRUCT(indexTuple); + index =3D (Form_pg_index) GETSTRUCT(tuple); =20 - if (!cluster_is_permitted_for_relation(index->indrelid, GetUserId())) - continue; + /* + * Try to obtain a light lock on the index's table, to ensure it + * doesn't go away while we collect the list. If we cannot, just + * disregard it. + */ + if (!ConditionalLockRelationOid(index->indrelid, AccessShareLock)) + continue; =20 - /* Use a permanent memory context for the result list */ - old_context =3D MemoryContextSwitchTo(cluster_context); + /* Verify that the table still exists */ + if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(index->indrelid))) + { + /* Release useless lock */ + UnlockRelationOid(index->indrelid, AccessShareLock); + continue; + } =20 - rtc =3D palloc_object(RelToCluster); - rtc->tableOid =3D index->indrelid; - rtc->indexOid =3D index->indexrelid; - rtcs =3D lappend(rtcs, rtc); + if (!cluster_is_permitted_for_relation(cmd, index->indrelid, + GetUserId())) + continue; + + /* Use a permanent memory context for the result list */ + oldcxt =3D MemoryContextSwitchTo(permcxt); + rtc =3D palloc_object(RelToCluster); + rtc->tableOid =3D index->indrelid; + rtc->indexOid =3D index->indexrelid; + rtcs =3D lappend(rtcs, rtc); + MemoryContextSwitchTo(oldcxt); + } + } + else + { + catalog =3D table_open(RelationRelationId, AccessShareLock); + scan =3D table_beginscan_catalog(catalog, 0, NULL); + + while ((tuple =3D heap_getnext(scan, ForwardScanDirection)) !=3D NULL) + { + RelToCluster *rtc; + Form_pg_class class; + MemoryContext oldcxt; + + class =3D (Form_pg_class) GETSTRUCT(tuple); + + /* + * Try to obtain a light lock on the table, to ensure it doesn't + * go away while we collect the list. If we cannot, just + * disregard the table. + */ + if (!ConditionalLockRelationOid(class->oid, AccessShareLock)) + continue; =20 - MemoryContextSwitchTo(old_context); + /* Verify that the table still exists */ + if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(class->oid))) + { + /* Release useless lock */ + UnlockRelationOid(class->oid, AccessShareLock); + continue; + } + + /* Can only process plain tables and matviews */ + if (class->relkind !=3D RELKIND_RELATION && + class->relkind !=3D RELKIND_MATVIEW) + continue; + + /* noisily skip rels which the user can't process */ + if (!cluster_is_permitted_for_relation(cmd, class->oid, + GetUserId())) + continue; + + /* Use a permanent memory context for the result list */ + oldcxt =3D MemoryContextSwitchTo(permcxt); + rtc =3D palloc_object(RelToCluster); + rtc->tableOid =3D class->oid; + rtc->indexOid =3D InvalidOid; + rtcs =3D lappend(rtcs, rtc); + MemoryContextSwitchTo(oldcxt); + } } - table_endscan(scan); =20 - relation_close(indRelation, AccessShareLock); + table_endscan(scan); + relation_close(catalog, AccessShareLock); =20 return rtcs; } =20 /* - * Given an index on a partitioned table, return a list of RelToCluster for + * Given a partitioned table or its index, return a list of RelToCluster f= or * all the children leaves tables/indexes. * * Like expand_vacuum_rel, but here caller must hold AccessExclusiveLock * on the table containing the index. + * + * 'rel_is_index' tells whether 'relid' is that of an index (true) or of t= he + * owning relation. */ static List * -get_tables_to_cluster_partitioned(MemoryContext cluster_context, Oid index= Oid) +get_tables_to_repack_partitioned(RepackCommand cmd, Oid relid, + bool rel_is_index, MemoryContext permcxt) { List *inhoids; - ListCell *lc; List *rtcs =3D NIL; - MemoryContext old_context; - - /* Do not lock the children until they're processed */ - inhoids =3D find_all_inheritors(indexOid, NoLock, NULL); =20 - foreach(lc, inhoids) + /* + * Do not lock the children until they're processed. Note that we do hold + * a lock on the parent partitioned table. + */ + inhoids =3D find_all_inheritors(relid, NoLock, NULL); + foreach_oid(child_oid, inhoids) { - Oid indexrelid =3D lfirst_oid(lc); - Oid relid =3D IndexGetRelation(indexrelid, false); + Oid table_oid, + index_oid; RelToCluster *rtc; + MemoryContext oldcxt; =20 - /* consider only leaf indexes */ - if (get_rel_relkind(indexrelid) !=3D RELKIND_INDEX) - continue; + if (rel_is_index) + { + /* consider only leaf indexes */ + if (get_rel_relkind(child_oid) !=3D RELKIND_INDEX) + continue; + + table_oid =3D IndexGetRelation(child_oid, false); + index_oid =3D child_oid; + } + else + { + /* consider only leaf relations */ + if (get_rel_relkind(child_oid) !=3D RELKIND_RELATION) + continue; + + table_oid =3D child_oid; + index_oid =3D InvalidOid; + } =20 /* * It's possible that the user does not have privileges to CLUSTER the - * leaf partition despite having such privileges on the partitioned - * table. We skip any partitions which the user is not permitted to - * CLUSTER. + * leaf partition despite having them on the partitioned table. Skip + * if so. */ - if (!cluster_is_permitted_for_relation(relid, GetUserId())) + if (!cluster_is_permitted_for_relation(cmd, table_oid, GetUserId())) continue; =20 /* Use a permanent memory context for the result list */ - old_context =3D MemoryContextSwitchTo(cluster_context); - + oldcxt =3D MemoryContextSwitchTo(permcxt); rtc =3D palloc_object(RelToCluster); - rtc->tableOid =3D relid; - rtc->indexOid =3D indexrelid; + rtc->tableOid =3D table_oid; + rtc->indexOid =3D index_oid; rtcs =3D lappend(rtcs, rtc); - - MemoryContextSwitchTo(old_context); + MemoryContextSwitchTo(oldcxt); } =20 return rtcs; @@ -1742,13 +1830,167 @@ get_tables_to_cluster_partitioned(MemoryContext cl= uster_context, Oid indexOid) * function emits a WARNING. */ static bool -cluster_is_permitted_for_relation(Oid relid, Oid userid) +cluster_is_permitted_for_relation(RepackCommand cmd, Oid relid, Oid userid) { + Assert(cmd =3D=3D REPACK_COMMAND_CLUSTER || cmd =3D=3D REPACK_COMMAND_REP= ACK); + if (pg_class_aclcheck(relid, userid, ACL_MAINTAIN) =3D=3D ACLCHECK_OK) return true; =20 ereport(WARNING, - (errmsg("permission denied to cluster \"%s\", skipping it", - get_rel_name(relid)))); + errmsg("permission denied to execute %s on \"%s\", skipping it", + RepackCommandAsString(cmd), + get_rel_name(relid))); + return false; } + + +/* + * Given a RepackStmt with an indicated relation name, resolve the relation + * name, obtain lock on it, then determine what to do based on the relation + * type: if it's table and not partitioned, repack it as indicated (using = an + * existing clustered index, or following the given one), and return NULL. + * + * On the other hand, if the table is partitioned, do nothing further and + * instead return the opened and locked relcache entry, so that caller can + * process the partitions using the multiple-table handling code. In this + * case, if an index name is given, it's up to the caller to resolve it. + */ +static Relation +process_single_relation(RepackStmt *stmt, ClusterParams *params) +{ + Relation rel; + Oid tableOid; + + Assert(stmt->relation !=3D NULL); + Assert(stmt->command =3D=3D REPACK_COMMAND_CLUSTER || + stmt->command =3D=3D REPACK_COMMAND_REPACK); + + /* + * Find, lock, and check permissions on the table. We obtain + * AccessExclusiveLock right away to avoid lock-upgrade hazard in the + * single-transaction case. + */ + tableOid =3D RangeVarGetRelidExtended(stmt->relation->relation, + AccessExclusiveLock, + 0, + RangeVarCallbackMaintainsTable, + NULL); + rel =3D table_open(tableOid, NoLock); + + /* + * Reject clustering a remote temp table ... their local buffer manager is + * not going to cope. + */ + if (RELATION_IS_OTHER_TEMP(rel)) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot execute %s on temporary tables of other sessions", + RepackCommandAsString(stmt->command))); + + /* + * Make sure ANALYZE is specified if a column list is present. + */ + if ((params->options & CLUOPT_ANALYZE) =3D=3D 0 && stmt->relation->va_col= s !=3D NIL) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("ANALYZE option must be specified when a column list is provide= d")); + + /* + * For partitioned tables, let caller handle this. Otherwise, process it + * here and we're done. + */ + if (rel->rd_rel->relkind =3D=3D RELKIND_PARTITIONED_TABLE) + return rel; + else + { + Oid indexOid; + + indexOid =3D determine_clustered_index(rel, stmt->usingindex, + stmt->indexname); + if (OidIsValid(indexOid)) + check_index_is_clusterable(rel, indexOid, AccessExclusiveLock); + cluster_rel(stmt->command, rel, indexOid, params); + + /* Do an analyze, if requested */ + if (params->options & CLUOPT_ANALYZE) + { + VacuumParams vac_params =3D {0}; + + vac_params.options |=3D VACOPT_ANALYZE; + if (params->options & CLUOPT_VERBOSE) + vac_params.options |=3D VACOPT_VERBOSE; + analyze_rel(tableOid, NULL, vac_params, + stmt->relation->va_cols, true, NULL); + } + + return NULL; + } +} + +/* + * Given a relation and the usingindex/indexname options in a + * REPACK USING INDEX or CLUSTER command, return the OID of the + * index to use for clustering the table. + * + * Caller must hold lock on the relation so that the set of indexes + * doesn't change, and must call check_index_is_clusterable. + */ +static Oid +determine_clustered_index(Relation rel, bool usingindex, const char *index= name) +{ + Oid indexOid; + + if (indexname =3D=3D NULL && usingindex) + { + /* + * If USING INDEX with no name is given, find a clustered index, or + * error out if none. + */ + indexOid =3D InvalidOid; + foreach_oid(idxoid, RelationGetIndexList(rel)) + { + if (get_index_isclustered(idxoid)) + { + indexOid =3D idxoid; + break; + } + } + + if (!OidIsValid(indexOid)) + ereport(ERROR, + errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("there is no previously clustered index for table \"%s\"", + RelationGetRelationName(rel))); + } + else if (indexname !=3D NULL) + { + /* An index was specified; obtain its OID. */ + indexOid =3D get_relname_relid(indexname, rel->rd_rel->relnamespace); + if (!OidIsValid(indexOid)) + ereport(ERROR, + errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("index \"%s\" for table \"%s\" does not exist", + indexname, RelationGetRelationName(rel))); + } + else + indexOid =3D InvalidOid; + + return indexOid; +} + +static const char * +RepackCommandAsString(RepackCommand cmd) +{ + switch (cmd) + { + case REPACK_COMMAND_REPACK: + return "REPACK"; + case REPACK_COMMAND_VACUUMFULL: + return "VACUUM"; + case REPACK_COMMAND_CLUSTER: + return "CLUSTER"; + } + return "???"; /* keep compiler quiet */ +} diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 03932f45c8a..aea998260e1 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -351,7 +351,6 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, boo= l isTopLevel) } } =20 - /* * Sanity check DISABLE_PAGE_SKIPPING option. */ @@ -2289,8 +2288,9 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParam= s params, if ((params.options & VACOPT_VERBOSE) !=3D 0) cluster_params.options |=3D CLUOPT_VERBOSE; =20 - /* VACUUM FULL is now a variant of CLUSTER; see cluster.c */ - cluster_rel(rel, InvalidOid, &cluster_params); + /* VACUUM FULL is a variant of REPACK; see cluster.c */ + cluster_rel(REPACK_COMMAND_VACUUMFULL, rel, InvalidOid, + &cluster_params); /* cluster_rel closes the relation, but keeps lock */ =20 rel =3D NULL; diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 713ee5c10a2..54d37c10447 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -287,7 +287,7 @@ static Node *makeRecursiveViewSelect(char *relname, Lis= t *aliases, Node *query); AlterCompositeTypeStmt AlterUserMappingStmt AlterRoleStmt AlterRoleSetStmt AlterPolicyStmt AlterStatsStmt AlterDefaultPrivilegesStmt DefACLAction - AnalyzeStmt CallStmt ClosePortalStmt ClusterStmt CommentStmt + AnalyzeStmt CallStmt ClosePortalStmt CommentStmt ConstraintsSetStmt CopyStmt CreateAsStmt CreateCastStmt CreateDomainStmt CreateExtensionStmt CreateGroupStmt CreateOpClassStmt CreateOpFamilyStmt AlterOpFamilyStmt CreatePLangStmt @@ -304,7 +304,7 @@ static Node *makeRecursiveViewSelect(char *relname, Lis= t *aliases, Node *query); GrantStmt GrantRoleStmt ImportForeignSchemaStmt IndexStmt InsertStmt ListenStmt LoadStmt LockStmt MergeStmt NotifyStmt ExplainableStmt Prepar= ableStmt CreateFunctionStmt AlterFunctionStmt ReindexStmt RemoveAggrStmt - RemoveFuncStmt RemoveOperStmt RenameStmt ReturnStmt RevokeStmt RevokeRol= eStmt + RemoveFuncStmt RemoveOperStmt RenameStmt RepackStmt ReturnStmt RevokeStm= t RevokeRoleStmt RuleActionStmt RuleActionStmtOrEmpty RuleStmt SecLabelStmt SelectStmt TransactionStmt TransactionStmtLegacy TruncateSt= mt UnlistenStmt UpdateStmt VacuumStmt @@ -323,7 +323,7 @@ static Node *makeRecursiveViewSelect(char *relname, Lis= t *aliases, Node *query); =20 %type <str> opt_single_name %type <list> opt_qualified_name -%type <boolean> opt_concurrently +%type <boolean> opt_concurrently opt_usingindex %type <dbehavior> opt_drop_behavior %type <list> opt_utility_option_list %type <list> opt_wait_with_clause @@ -773,7 +773,7 @@ static Node *makeRecursiveViewSelect(char *relname, Lis= t *aliases, Node *query); QUOTE QUOTES =20 RANGE READ REAL REASSIGN RECURSIVE REF_P REFERENCES REFERENCING - REFRESH REINDEX RELATIVE_P RELEASE RENAME REPEATABLE REPLACE REPLICA + REFRESH REINDEX RELATIVE_P RELEASE RENAME REPACK REPEATABLE REPLACE REPLI= CA RESET RESPECT_P RESTART RESTRICT RETURN RETURNING RETURNS REVOKE RIGHT RO= LE ROLLBACK ROLLUP ROUTINE ROUTINES ROW ROWS RULE =20 @@ -1035,7 +1035,6 @@ stmt: | CallStmt | CheckPointStmt | ClosePortalStmt - | ClusterStmt | CommentStmt | ConstraintsSetStmt | CopyStmt @@ -1109,6 +1108,7 @@ stmt: | RemoveFuncStmt | RemoveOperStmt | RenameStmt + | RepackStmt | RevokeStmt | RevokeRoleStmt | RuleStmt @@ -1146,6 +1146,11 @@ opt_concurrently: | /*EMPTY*/ { $$ =3D false; } ; =20 +opt_usingindex: + USING INDEX { $$ =3D true; } + | /* EMPTY */ { $$ =3D false; } + ; + opt_drop_behavior: CASCADE { $$ =3D DROP_CASCADE; } | RESTRICT { $$ =3D DROP_RESTRICT; } @@ -12036,38 +12041,82 @@ CreateConversionStmt: /*************************************************************************= **** * * QUERY: + * REPACK [ (options) ] [ <qualified_name> [ <name_list> ] [ USING INDE= X <index_name> ] ] + * + * obsolete variants: * CLUSTER (options) [ <qualified_name> [ USING <index_name> ] ] * CLUSTER [VERBOSE] [ <qualified_name> [ USING <index_name> ] ] * CLUSTER [VERBOSE] <index_name> ON <qualified_name> (for pre-8.3) * *************************************************************************= ****/ =20 -ClusterStmt: - CLUSTER '(' utility_option_list ')' qualified_name cluster_index_specif= ication +RepackStmt: + REPACK opt_utility_option_list vacuum_relation USING INDEX name { - ClusterStmt *n =3D makeNode(ClusterStmt); + RepackStmt *n =3D makeNode(RepackStmt); =20 - n->relation =3D $5; + n->command =3D REPACK_COMMAND_REPACK; + n->relation =3D (VacuumRelation *) $3; n->indexname =3D $6; + n->usingindex =3D true; + n->params =3D $2; + $$ =3D (Node *) n; + } + | REPACK opt_utility_option_list vacuum_relation opt_usingindex + { + RepackStmt *n =3D makeNode(RepackStmt); + + n->command =3D REPACK_COMMAND_REPACK; + n->relation =3D (VacuumRelation *) $3; + n->indexname =3D NULL; + n->usingindex =3D $4; + n->params =3D $2; + $$ =3D (Node *) n; + } + | REPACK opt_utility_option_list opt_usingindex + { + RepackStmt *n =3D makeNode(RepackStmt); + + n->command =3D REPACK_COMMAND_REPACK; + n->relation =3D NULL; + n->indexname =3D NULL; + n->usingindex =3D $3; + n->params =3D $2; + $$ =3D (Node *) n; + } + | CLUSTER '(' utility_option_list ')' qualified_name cluster_index_spec= ification + { + RepackStmt *n =3D makeNode(RepackStmt); + + n->command =3D REPACK_COMMAND_CLUSTER; + n->relation =3D makeNode(VacuumRelation); + n->relation->relation =3D $5; + n->indexname =3D $6; + n->usingindex =3D true; n->params =3D $3; $$ =3D (Node *) n; } | CLUSTER opt_utility_option_list { - ClusterStmt *n =3D makeNode(ClusterStmt); + RepackStmt *n =3D makeNode(RepackStmt); =20 + n->command =3D REPACK_COMMAND_CLUSTER; n->relation =3D NULL; n->indexname =3D NULL; + n->usingindex =3D true; n->params =3D $2; $$ =3D (Node *) n; } /* unparenthesized VERBOSE kept for pre-14 compatibility */ | CLUSTER opt_verbose qualified_name cluster_index_specification { - ClusterStmt *n =3D makeNode(ClusterStmt); + RepackStmt *n =3D makeNode(RepackStmt); =20 - n->relation =3D $3; + n->command =3D REPACK_COMMAND_CLUSTER; + n->relation =3D makeNode(VacuumRelation); + n->relation->relation =3D $3; n->indexname =3D $4; + n->usingindex =3D true; if ($2) n->params =3D list_make1(makeDefElem("verbose", NULL, @2)); $$ =3D (Node *) n; @@ -12075,20 +12124,25 @@ ClusterStmt: /* unparenthesized VERBOSE kept for pre-17 compatibility */ | CLUSTER VERBOSE { - ClusterStmt *n =3D makeNode(ClusterStmt); + RepackStmt *n =3D makeNode(RepackStmt); =20 + n->command =3D REPACK_COMMAND_CLUSTER; n->relation =3D NULL; n->indexname =3D NULL; + n->usingindex =3D true; n->params =3D list_make1(makeDefElem("verbose", NULL, @2)); $$ =3D (Node *) n; } /* kept for pre-8.3 compatibility */ | CLUSTER opt_verbose name ON qualified_name { - ClusterStmt *n =3D makeNode(ClusterStmt); + RepackStmt *n =3D makeNode(RepackStmt); =20 - n->relation =3D $5; + n->command =3D REPACK_COMMAND_CLUSTER; + n->relation =3D makeNode(VacuumRelation); + n->relation->relation =3D $5; n->indexname =3D $3; + n->usingindex =3D true; if ($2) n->params =3D list_make1(makeDefElem("verbose", NULL, @2)); $$ =3D (Node *) n; @@ -18127,6 +18181,7 @@ unreserved_keyword: | RELATIVE_P | RELEASE | RENAME + | REPACK | REPEATABLE | REPLACE | REPLICA @@ -18764,6 +18819,7 @@ bare_label_keyword: | RELATIVE_P | RELEASE | RENAME + | REPACK | REPEATABLE | REPLACE | REPLICA diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 34dd6e18df5..ca737b05115 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -279,9 +279,9 @@ ClassifyUtilityCommandAsReadOnly(Node *parsetree) return COMMAND_OK_IN_RECOVERY | COMMAND_OK_IN_READ_ONLY_TXN; } =20 - case T_ClusterStmt: case T_ReindexStmt: case T_VacuumStmt: + case T_RepackStmt: { /* * These commands write WAL, so they're not strictly @@ -856,14 +856,14 @@ standard_ProcessUtility(PlannedStmt *pstmt, ExecuteCallStmt(castNode(CallStmt, parsetree), params, isAtomicContext,= dest); break; =20 - case T_ClusterStmt: - cluster(pstate, (ClusterStmt *) parsetree, isTopLevel); - break; - case T_VacuumStmt: ExecVacuum(pstate, (VacuumStmt *) parsetree, isTopLevel); break; =20 + case T_RepackStmt: + ExecRepack(pstate, (RepackStmt *) parsetree, isTopLevel); + break; + case T_ExplainStmt: ExplainQuery(pstate, (ExplainStmt *) parsetree, params, dest); break; @@ -2865,10 +2865,6 @@ CreateCommandTag(Node *parsetree) tag =3D CMDTAG_CALL; break; =20 - case T_ClusterStmt: - tag =3D CMDTAG_CLUSTER; - break; - case T_VacuumStmt: if (((VacuumStmt *) parsetree)->is_vacuumcmd) tag =3D CMDTAG_VACUUM; @@ -2876,6 +2872,13 @@ CreateCommandTag(Node *parsetree) tag =3D CMDTAG_ANALYZE; break; =20 + case T_RepackStmt: + if (((RepackStmt *) parsetree)->command =3D=3D REPACK_COMMAND_CLUSTER) + tag =3D CMDTAG_CLUSTER; + else + tag =3D CMDTAG_REPACK; + break; + case T_ExplainStmt: tag =3D CMDTAG_EXPLAIN; break; @@ -3517,7 +3520,7 @@ GetCommandLogLevel(Node *parsetree) lev =3D LOGSTMT_ALL; break; =20 - case T_ClusterStmt: + case T_RepackStmt: lev =3D LOGSTMT_DDL; break; =20 diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pg= statfuncs.c index 73ca0bb0b7f..55a69bf681d 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -287,8 +287,8 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS) cmdtype =3D PROGRESS_COMMAND_VACUUM; else if (pg_strcasecmp(cmd, "ANALYZE") =3D=3D 0) cmdtype =3D PROGRESS_COMMAND_ANALYZE; - else if (pg_strcasecmp(cmd, "CLUSTER") =3D=3D 0) - cmdtype =3D PROGRESS_COMMAND_CLUSTER; + else if (pg_strcasecmp(cmd, "REPACK") =3D=3D 0) + cmdtype =3D PROGRESS_COMMAND_REPACK; else if (pg_strcasecmp(cmd, "CREATE INDEX") =3D=3D 0) cmdtype =3D PROGRESS_COMMAND_CREATE_INDEX; else if (pg_strcasecmp(cmd, "BASEBACKUP") =3D=3D 0) diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c index 8b91bc00062..2a1bb47ff03 100644 --- a/src/bin/psql/tab-complete.in.c +++ b/src/bin/psql/tab-complete.in.c @@ -1267,7 +1267,7 @@ static const char *const sql_commands[] =3D { "DELETE FROM", "DISCARD", "DO", "DROP", "END", "EXECUTE", "EXPLAIN", "FETCH", "GRANT", "IMPORT FOREIGN SCHEMA", "INSERT INTO", "LISTEN", "LOAD= ", "LOCK", "MERGE INTO", "MOVE", "NOTIFY", "PREPARE", - "REASSIGN", "REFRESH MATERIALIZED VIEW", "REINDEX", "RELEASE", + "REASSIGN", "REFRESH MATERIALIZED VIEW", "REINDEX", "RELEASE", "REPACK", "RESET", "REVOKE", "ROLLBACK", "SAVEPOINT", "SECURITY LABEL", "SELECT", "SET", "SHOW", "START", "TABLE", "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", "VALUES", @@ -5086,6 +5086,46 @@ match_previous_words(int pattern_id, COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces); } =20 +/* REPACK */ + else if (Matches("REPACK")) + COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_clusterables, + "(", "USING INDEX"); + else if (Matches("REPACK", "(*)")) + COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_clusterables, + "USING INDEX"); + else if (Matches("REPACK", MatchAnyExcept("("))) + COMPLETE_WITH("USING INDEX"); + else if (Matches("REPACK", "(*)", MatchAnyExcept("("))) + COMPLETE_WITH("USING INDEX"); + else if (Matches("REPACK", MatchAny, "USING", "INDEX") || + Matches("REPACK", "(*)", MatchAny, "USING", "INDEX")) + { + set_completion_reference(prev3_wd); + COMPLETE_WITH_SCHEMA_QUERY(Query_for_index_of_table); + } + /* + * Complete ... [ (*) ] <sth> USING INDEX, with a list of indexes for + * <sth>. + */ + else if (TailMatches(MatchAny, "USING", "INDEX")) + { + set_completion_reference(prev3_wd); + COMPLETE_WITH_SCHEMA_QUERY(Query_for_index_of_table); + } + else if (HeadMatches("REPACK", "(*") && + !HeadMatches("REPACK", "(*)")) + { + /* + * This fires if we're in an unfinished parenthesized option list. + * get_previous_words treats a completed parenthesized option list as + * one word, so the above test is correct. + */ + if (ends_with(prev_wd, '(') || ends_with(prev_wd, ',')) + COMPLETE_WITH("ANALYZE", "VERBOSE"); + else if (TailMatches("ANALYZE", "VERBOSE")) + COMPLETE_WITH("ON", "OFF"); + } + /* SECURITY LABEL */ else if (Matches("SECURITY")) COMPLETE_WITH("LABEL"); diff --git a/src/bin/scripts/Makefile b/src/bin/scripts/Makefile index e6cd9ef4af5..f964a5803ca 100644 --- a/src/bin/scripts/Makefile +++ b/src/bin/scripts/Makefile @@ -23,6 +23,7 @@ PROGRAMS =3D \ dropdb \ dropuser \ pg_isready \ + pg_repackdb \ reindexdb \ vacuumdb =20 @@ -39,6 +40,7 @@ clusterdb: clusterdb.o common.o $(WIN32RES) | submake-lib= pq submake-libpgport su vacuumdb: vacuumdb.o vacuuming.o common.o $(WIN32RES) | submake-libpq subm= ake-libpgport submake-libpgfeutils reindexdb: reindexdb.o common.o $(WIN32RES) | submake-libpq submake-libpgp= ort submake-libpgfeutils pg_isready: pg_isready.o common.o $(WIN32RES) | submake-libpq submake-libp= gport submake-libpgfeutils +pg_repackdb: pg_repackdb.o vacuuming.o common.o $(WIN32RES) | submake-libp= q submake-libpgport submake-libpgfeutils =20 install: all installdirs $(INSTALL_PROGRAM) createdb$(X) '$(DESTDIR)$(bindir)'/createdb$(X) @@ -49,6 +51,7 @@ install: all installdirs $(INSTALL_PROGRAM) vacuumdb$(X) '$(DESTDIR)$(bindir)'/vacuumdb$(X) $(INSTALL_PROGRAM) reindexdb$(X) '$(DESTDIR)$(bindir)'/reindexdb$(X) $(INSTALL_PROGRAM) pg_isready$(X) '$(DESTDIR)$(bindir)'/pg_isready$(X) + $(INSTALL_PROGRAM) pg_repackdb$(X) '$(DESTDIR)$(bindir)'/pg_repackdb$(X) =20 installdirs: $(MKDIR_P) '$(DESTDIR)$(bindir)' diff --git a/src/bin/scripts/meson.build b/src/bin/scripts/meson.build index c083ec38099..1e88bacebba 100644 --- a/src/bin/scripts/meson.build +++ b/src/bin/scripts/meson.build @@ -42,6 +42,7 @@ vacuuming_common =3D static_library('libvacuuming_common', =20 binaries =3D [ 'vacuumdb', + 'pg_repackdb', ] foreach binary : binaries binary_sources =3D files('@[email protected]'.format(binary)) @@ -80,6 +81,7 @@ tests +=3D { 't/100_vacuumdb.pl', 't/101_vacuumdb_all.pl', 't/102_vacuumdb_stages.pl', + 't/103_repackdb.pl', 't/200_connstr.pl', ], }, diff --git a/src/bin/scripts/pg_repackdb.c b/src/bin/scripts/pg_repackdb.c new file mode 100644 index 00000000000..2765d1e97b8 --- /dev/null +++ b/src/bin/scripts/pg_repackdb.c @@ -0,0 +1,240 @@ +/*------------------------------------------------------------------------- + * + * pg_repackdb + * An utility to run REPACK + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * FIXME: this is missing a way to specify the index to use to repack one + * table, or whether to pass a WITH INDEX clause when multiple tables are + * used. Something like --index[=3Dindexname]. Adding that bleeds into + * vacuuming.c as well. + * + * src/bin/scripts/pg_repackdb.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres_fe.h" + +#include <limits.h> + +#include "common.h" +#include "common/logging.h" +#include "fe_utils/option_utils.h" +#include "vacuuming.h" + +static void help(const char *progname); +static void check_objfilter(bits32 objfilter); + +int +main(int argc, char *argv[]) +{ + static struct option long_options[] =3D { + {"host", required_argument, NULL, 'h'}, + {"port", required_argument, NULL, 'p'}, + {"username", required_argument, NULL, 'U'}, + {"no-password", no_argument, NULL, 'w'}, + {"password", no_argument, NULL, 'W'}, + {"echo", no_argument, NULL, 'e'}, + {"quiet", no_argument, NULL, 'q'}, + {"dbname", required_argument, NULL, 'd'}, + {"analyze", no_argument, NULL, 'z'}, + {"all", no_argument, NULL, 'a'}, + /* XXX this could be 'i', but optional_arg is messy */ + {"index", optional_argument, NULL, 1}, + {"table", required_argument, NULL, 't'}, + {"verbose", no_argument, NULL, 'v'}, + {"jobs", required_argument, NULL, 'j'}, + {"schema", required_argument, NULL, 'n'}, + {"exclude-schema", required_argument, NULL, 'N'}, + {"maintenance-db", required_argument, NULL, 2}, + {NULL, 0, NULL, 0} + }; + + const char *progname; + int optindex; + int c; + const char *dbname =3D NULL; + const char *maintenance_db =3D NULL; + ConnParams cparams; + vacuumingOptions vacopts; + SimpleStringList objects =3D {NULL, NULL}; + int concurrentCons =3D 1; + int tbl_count =3D 0; + int ret; + + /* initialize options */ + memset(&vacopts, 0, sizeof(vacopts)); + vacopts.mode =3D MODE_REPACK; + + /* the same for connection parameters */ + memset(&cparams, 0, sizeof(cparams)); + cparams.prompt_password =3D TRI_DEFAULT; + + pg_logging_init(argv[0]); + progname =3D get_progname(argv[0]); + set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts")); + + handle_help_version_opts(argc, argv, progname, help); + + while ((c =3D getopt_long(argc, argv, "ad:eh:j:n:N:p:qt:U:vwWz", + long_options, &optindex)) !=3D -1) + { + switch (c) + { + case 'a': + vacopts.objfilter |=3D OBJFILTER_ALL_DBS; + break; + case 'd': + vacopts.objfilter |=3D OBJFILTER_DATABASE; + dbname =3D pg_strdup(optarg); + break; + case 'e': + vacopts.echo =3D true; + break; + case 'h': + cparams.pghost =3D pg_strdup(optarg); + break; + case 'j': + if (!option_parse_int(optarg, "-j/--jobs", 1, INT_MAX, + &concurrentCons)) + exit(1); + break; + case 'n': + vacopts.objfilter |=3D OBJFILTER_SCHEMA; + simple_string_list_append(&objects, optarg); + break; + case 'N': + vacopts.objfilter |=3D OBJFILTER_SCHEMA_EXCLUDE; + simple_string_list_append(&objects, optarg); + break; + case 'p': + cparams.pgport =3D pg_strdup(optarg); + break; + case 'q': + vacopts.quiet =3D true; + break; + case 't': + vacopts.objfilter |=3D OBJFILTER_TABLE; + simple_string_list_append(&objects, optarg); + tbl_count++; + break; + case 'U': + cparams.pguser =3D pg_strdup(optarg); + break; + case 'v': + vacopts.verbose =3D true; + break; + case 'w': + cparams.prompt_password =3D TRI_NO; + break; + case 'W': + cparams.prompt_password =3D TRI_YES; + break; + case 'z': + vacopts.and_analyze =3D true; + break; + case 1: + vacopts.using_index =3D true; + if (optarg) + vacopts.indexname =3D pg_strdup(optarg); + else + vacopts.indexname =3D NULL; + break; + case 2: + maintenance_db =3D pg_strdup(optarg); + break; + default: + /* getopt_long already emitted a complaint */ + pg_log_error_hint("Try \"%s --help\" for more information.", progname); + exit(1); + } + } + + /* + * Non-option argument specifies database name as long as it wasn't + * already specified with -d / --dbname + */ + if (optind < argc && dbname =3D=3D NULL) + { + vacopts.objfilter |=3D OBJFILTER_DATABASE; + dbname =3D argv[optind]; + optind++; + } + + if (optind < argc) + { + pg_log_error("too many command-line arguments (first is \"%s\")", + argv[optind]); + pg_log_error_hint("Try \"%s --help\" for more information.", progname); + exit(1); + } + + /* + * Validate the combination of filters specified in the command-line + * options. + */ + check_objfilter(vacopts.objfilter); + + ret =3D vacuuming_main(&cparams, dbname, maintenance_db, &vacopts, + &objects, tbl_count, concurrentCons, + progname); + exit(ret); +} + +/* + * Verify that the filters used at command line are compatible. + */ +void +check_objfilter(bits32 objfilter) +{ + if ((objfilter & OBJFILTER_ALL_DBS) && + (objfilter & OBJFILTER_DATABASE)) + pg_fatal("cannot repack all databases and a specific one at the same tim= e"); + + if ((objfilter & OBJFILTER_TABLE) && + (objfilter & OBJFILTER_SCHEMA)) + pg_fatal("cannot repack all tables in schema(s) and specific table(s) at= the same time"); + + if ((objfilter & OBJFILTER_TABLE) && + (objfilter & OBJFILTER_SCHEMA_EXCLUDE)) + pg_fatal("cannot repack specific table(s) and exclude schema(s) at the s= ame time"); + + if ((objfilter & OBJFILTER_SCHEMA) && + (objfilter & OBJFILTER_SCHEMA_EXCLUDE)) + pg_fatal("cannot repack all tables in schema(s) and exclude schema(s) at= the same time"); +} + +static void +help(const char *progname) +{ + printf(_("%s repacks a PostgreSQL database.\n\n"), progname); + printf(_("Usage:\n")); + printf(_(" %s [OPTION]... [DBNAME]\n"), progname); + printf(_("\nOptions:\n")); + printf(_(" -a, --all repack all databases\n")); + printf(_(" -d, --dbname=3DDBNAME database to repack\n")); + printf(_(" -e, --echo show the commands being sent = to the server\n")); + printf(_(" --index[=3DINDEX] repack following an index\n= ")); + printf(_(" -j, --jobs=3DNUM use this many concurrent co= nnections to repack\n")); + printf(_(" -n, --schema=3DSCHEMA repack tables in the specif= ied schema(s) only\n")); + printf(_(" -N, --exclude-schema=3DSCHEMA do not repack tables in the= specified schema(s)\n")); + printf(_(" -q, --quiet don't write any messages\n")); + printf(_(" -t, --table=3D'TABLE[(COLUMNS)]' repack specific table(s) on= ly\n")); + printf(_(" -v, --verbose write a lot of output\n")); + printf(_(" -V, --version output version information, t= hen exit\n")); + printf(_(" -z, --analyze update optimizer statistics\n= ")); + printf(_(" -?, --help show this help, then exit\n")= ); + printf(_("\nConnection options:\n")); + printf(_(" -h, --host=3DHOSTNAME database server host or socket di= rectory\n")); + printf(_(" -p, --port=3DPORT database server port\n")); + printf(_(" -U, --username=3DUSERNAME user name to connect as\n")); + printf(_(" -w, --no-password never prompt for password\n")); + printf(_(" -W, --password force password prompt\n")); + printf(_(" --maintenance-db=3DDBNAME alternate maintenance database\n"= )); + printf(_("\nRead the description of the SQL command REPACK for details.\n= ")); + printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT); + printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL); +} diff --git a/src/bin/scripts/t/103_repackdb.pl b/src/bin/scripts/t/103_repa= ckdb.pl new file mode 100644 index 00000000000..44113367a61 --- /dev/null +++ b/src/bin/scripts/t/103_repackdb.pl @@ -0,0 +1,47 @@ +# Copyright (c) 2021-2026, PostgreSQL Global Development Group + +use strict; +use warnings FATAL =3D> 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +program_help_ok('pg_repackdb'); +program_version_ok('pg_repackdb'); +program_options_handling_ok('pg_repackdb'); + +my $node =3D PostgreSQL::Test::Cluster->new('main'); +$node->init; +$node->start; + +$node->issues_sql_like( + [ 'pg_repackdb', 'postgres', '-t', 'pg_class'], + qr/statement: REPACK.*pg_class;/, + 'pg_repackdb processes a single table'); + +$node->safe_psql('postgres', 'CREATE USER testusr; + GRANT CREATE ON SCHEMA public TO testusr'); +$node->safe_psql('postgres', + 'CREATE TABLE cluster_1 (a int primary key); + ALTER TABLE cluster_1 CLUSTER ON cluster_1_pkey; + CREATE TABLE cluster_2 (a int unique); + ALTER TABLE cluster_2 CLUSTER ON cluster_2_a_key;', + extra_params =3D> ['-U' =3D> 'testusr']); + +$node->issues_sql_like( + [ 'pg_repackdb', 'postgres', '-U', 'testusr' ], + qr/statement: REPACK.*;/, + 'SQL REPACK run'); + +$node->issues_sql_like( + [ 'pg_repackdb', 'postgres', '--index'], + qr/statement: REPACK.*cluster_1 USING INDEX.*statement: REPACK.*cluster_2= USING INDEX/ms, + 'pg_repackdb --index chooses multiple tables'); + +$node->issues_sql_like( + [ 'pg_repackdb', 'postgres', '--analyze', '-t', 'cluster_1'], + qr/statement: REPACK \(ANALYZE\) public.cluster_1/, + 'pg_repackdb --analyze works'); + +done_testing(); diff --git a/src/bin/scripts/vacuuming.c b/src/bin/scripts/vacuuming.c index faac9089a01..0fa7be3c0c3 100644 --- a/src/bin/scripts/vacuuming.c +++ b/src/bin/scripts/vacuuming.c @@ -1,6 +1,6 @@ /*------------------------------------------------------------------------- * vacuuming.c - * Helper routines for vacuumdb + * Helper routines for vacuumdb and pg_repackdb * * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California @@ -194,6 +194,14 @@ vacuum_one_database(ConnParams *cparams, =20 conn =3D connectDatabase(cparams, progname, vacopts->echo, false, true); =20 + if (vacopts->mode =3D=3D MODE_REPACK && PQserverVersion(conn) < 190000) + { + /* XXX arguably, here we should use VACUUM FULL instead of failing */ + PQfinish(conn); + pg_fatal("cannot use the \"%s\" command on server versions older than Po= stgreSQL %s", + "REPACK", "19"); + } + if (vacopts->disable_page_skipping && PQserverVersion(conn) < 90600) { PQfinish(conn); @@ -286,9 +294,18 @@ vacuum_one_database(ConnParams *cparams, if (vacopts->mode =3D=3D MODE_ANALYZE_IN_STAGES) printf(_("%s: processing database \"%s\": %s\n"), progname, PQdb(conn), _(stage_messages[stage])); - else + else if (vacopts->mode =3D=3D MODE_ANALYZE) + printf(_("%s: analyzing database \"%s\"\n"), + progname, PQdb(conn)); + else if (vacopts->mode =3D=3D MODE_VACUUM) printf(_("%s: vacuuming database \"%s\"\n"), progname, PQdb(conn)); + else + { + Assert(vacopts->mode =3D=3D MODE_REPACK); + printf(_("%s: repacking database \"%s\"\n"), + progname, PQdb(conn)); + } fflush(stdout); } =20 @@ -640,6 +657,35 @@ retrieve_objects(PGconn *conn, vacuumingOptions *vacop= ts, " AND listed_objects.object_oid IS NOT NULL\n"); } =20 + /* + * In REPACK mode, if the 'using_index' option was given but no index + * name, filter only tables that have an index with indisclustered set. + * (If an index name is given, we trust the user to pass a reasonable list + * of tables.) + * + * XXX it may be worth printing an error if an index name is given with no + * list of tables. + */ + if (vacopts->mode =3D=3D MODE_REPACK && + vacopts->using_index && !vacopts->indexname) + { + appendPQExpBufferStr(&catalog_query, + " AND EXISTS (SELECT 1 FROM pg_catalog.pg_index\n" + " WHERE indrelid =3D c.oid AND indisclustered)\n"); + } + + /* + * In REPACK mode, only consider the tables that the current user has + * MAINTAIN privileges on. XXX maybe we should do this in all cases, not + * just REPACK. The vacuumdb output is too noisy for no reason. + */ + if (vacopts->mode =3D=3D MODE_REPACK) + { + appendPQExpBufferStr(&catalog_query, + " AND pg_catalog.has_table_privilege(current_user, " + "c.oid, 'MAINTAIN')\n"); + } + /* * If no tables were listed, filter for the relevant relation types. If * tables were given via --table, don't bother filtering by relation type. @@ -878,8 +924,10 @@ prepare_vacuum_command(PGconn *conn, PQExpBuffer sql, if (vacopts->verbose) appendPQExpBufferStr(sql, " VERBOSE"); } + + appendPQExpBuffer(sql, " %s", table); } - else + else if (vacopts->mode =3D=3D MODE_VACUUM) { appendPQExpBufferStr(sql, "VACUUM"); =20 @@ -993,9 +1041,39 @@ prepare_vacuum_command(PGconn *conn, PQExpBuffer sql, if (vacopts->and_analyze) appendPQExpBufferStr(sql, " ANALYZE"); } + + appendPQExpBuffer(sql, " %s", table); } + else if (vacopts->mode =3D=3D MODE_REPACK) + { + appendPQExpBufferStr(sql, "REPACK"); =20 - appendPQExpBuffer(sql, " %s;", table); + if (vacopts->verbose) + { + appendPQExpBuffer(sql, "%sVERBOSE", sep); + sep =3D comma; + } + if (vacopts->and_analyze) + { + appendPQExpBuffer(sql, "%sANALYZE", sep); + sep =3D comma; + } + + if (sep !=3D paren) + appendPQExpBufferChar(sql, ')'); + + appendPQExpBuffer(sql, " %s", table); + + if (vacopts->using_index) + { + appendPQExpBuffer(sql, " USING INDEX"); + if (vacopts->indexname) + appendPQExpBuffer(sql, " %s", fmtIdEnc(vacopts->indexname, + PQclientEncoding(conn))); + } + } + + appendPQExpBufferChar(sql, ';'); } =20 /* @@ -1024,13 +1102,21 @@ run_vacuum_command(ParallelSlot *free_slot, vacuumi= ngOptions *vacopts, { if (table) { - pg_log_error("vacuuming of table \"%s\" in database \"%s\" failed: %s", - table, PQdb(conn), PQerrorMessage(conn)); + if (vacopts->mode =3D=3D MODE_VACUUM) + pg_log_error("vacuuming of table \"%s\" in database \"%s\" failed: %s", + table, PQdb(conn), PQerrorMessage(conn)); + else + pg_log_error("repacking of table \"%s\" in database \"%s\" failed: %s", + table, PQdb(conn), PQerrorMessage(conn)); } else { - pg_log_error("vacuuming of database \"%s\" failed: %s", - PQdb(conn), PQerrorMessage(conn)); + if (vacopts->mode =3D=3D MODE_VACUUM) + pg_log_error("vacuuming of database \"%s\" failed: %s", + PQdb(conn), PQerrorMessage(conn)); + else + pg_log_error("repacking of database \"%s\" failed: %s", + PQdb(conn), PQerrorMessage(conn)); } } } diff --git a/src/bin/scripts/vacuuming.h b/src/bin/scripts/vacuuming.h index be4a75ef2f4..6e8abe00a4f 100644 --- a/src/bin/scripts/vacuuming.h +++ b/src/bin/scripts/vacuuming.h @@ -20,6 +20,7 @@ typedef enum { MODE_VACUUM, + MODE_REPACK, MODE_ANALYZE, MODE_ANALYZE_IN_STAGES } RunMode; @@ -37,6 +38,8 @@ typedef struct vacuumingOptions bool and_analyze; bool full; bool freeze; + bool using_index; + char *indexname; bool disable_page_skipping; bool skip_locked; int min_xid_age; diff --git a/src/include/commands/cluster.h b/src/include/commands/cluster.h index 8ea81622f9d..28741988478 100644 --- a/src/include/commands/cluster.h +++ b/src/include/commands/cluster.h @@ -24,6 +24,7 @@ #define CLUOPT_RECHECK 0x02 /* recheck relation state */ #define CLUOPT_RECHECK_ISCLUSTERED 0x04 /* recheck relation state for * indisclustered */ +#define CLUOPT_ANALYZE 0x08 /* do an ANALYZE */ =20 /* options for CLUSTER */ typedef struct ClusterParams @@ -31,8 +32,11 @@ typedef struct ClusterParams bits32 options; /* bitmask of CLUOPT_* */ } ClusterParams; =20 -extern void cluster(ParseState *pstate, ClusterStmt *stmt, bool isTopLevel= ); -extern void cluster_rel(Relation OldHeap, Oid indexOid, ClusterParams *par= ams); + +extern void ExecRepack(ParseState *pstate, RepackStmt *stmt, bool isTopLev= el); + +extern void cluster_rel(RepackCommand command, Relation OldHeap, Oid index= Oid, + ClusterParams *params); extern void check_index_is_clusterable(Relation OldHeap, Oid indexOid, LOCKMODE lockmode); extern void mark_index_clustered(Relation rel, Oid indexOid, bool is_inter= nal); diff --git a/src/include/commands/progress.h b/src/include/commands/progres= s.h index 359221dc296..f00e39b937d 100644 --- a/src/include/commands/progress.h +++ b/src/include/commands/progress.h @@ -73,28 +73,34 @@ #define PROGRESS_ANALYZE_STARTED_BY_MANUAL 1 #define PROGRESS_ANALYZE_STARTED_BY_AUTOVACUUM 2 =20 -/* Progress parameters for cluster */ -#define PROGRESS_CLUSTER_COMMAND 0 -#define PROGRESS_CLUSTER_PHASE 1 -#define PROGRESS_CLUSTER_INDEX_RELID 2 -#define PROGRESS_CLUSTER_HEAP_TUPLES_SCANNED 3 -#define PROGRESS_CLUSTER_HEAP_TUPLES_WRITTEN 4 -#define PROGRESS_CLUSTER_TOTAL_HEAP_BLKS 5 -#define PROGRESS_CLUSTER_HEAP_BLKS_SCANNED 6 -#define PROGRESS_CLUSTER_INDEX_REBUILD_COUNT 7 - -/* Phases of cluster (as advertised via PROGRESS_CLUSTER_PHASE) */ -#define PROGRESS_CLUSTER_PHASE_SEQ_SCAN_HEAP 1 -#define PROGRESS_CLUSTER_PHASE_INDEX_SCAN_HEAP 2 -#define PROGRESS_CLUSTER_PHASE_SORT_TUPLES 3 -#define PROGRESS_CLUSTER_PHASE_WRITE_NEW_HEAP 4 -#define PROGRESS_CLUSTER_PHASE_SWAP_REL_FILES 5 -#define PROGRESS_CLUSTER_PHASE_REBUILD_INDEX 6 -#define PROGRESS_CLUSTER_PHASE_FINAL_CLEANUP 7 - -/* Commands of PROGRESS_CLUSTER */ -#define PROGRESS_CLUSTER_COMMAND_CLUSTER 1 -#define PROGRESS_CLUSTER_COMMAND_VACUUM_FULL 2 +/* + * Progress parameters for REPACK. + * + * Values for PROGRESS_REPACK_COMMAND are defined as in RepackCommand. + * + * Note: Since REPACK shares code with CLUSTER, these values are also + * used by CLUSTER. (CLUSTER is now deprecated, so it makes little sense to + * introduce a separate set of constants.) + */ +#define PROGRESS_REPACK_COMMAND 0 +#define PROGRESS_REPACK_PHASE 1 +#define PROGRESS_REPACK_INDEX_RELID 2 +#define PROGRESS_REPACK_HEAP_TUPLES_SCANNED 3 +#define PROGRESS_REPACK_HEAP_TUPLES_WRITTEN 4 +#define PROGRESS_REPACK_TOTAL_HEAP_BLKS 5 +#define PROGRESS_REPACK_HEAP_BLKS_SCANNED 6 +#define PROGRESS_REPACK_INDEX_REBUILD_COUNT 7 + +/* + * Phases of repack (as advertised via PROGRESS_REPACK_PHASE). + */ +#define PROGRESS_REPACK_PHASE_SEQ_SCAN_HEAP 1 +#define PROGRESS_REPACK_PHASE_INDEX_SCAN_HEAP 2 +#define PROGRESS_REPACK_PHASE_SORT_TUPLES 3 +#define PROGRESS_REPACK_PHASE_WRITE_NEW_HEAP 4 +#define PROGRESS_REPACK_PHASE_SWAP_REL_FILES 5 +#define PROGRESS_REPACK_PHASE_REBUILD_INDEX 6 +#define PROGRESS_REPACK_PHASE_FINAL_CLEANUP 7 =20 /* Progress parameters for CREATE INDEX */ /* 3, 4 and 5 reserved for "waitfor" metrics */ diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 646d6ced763..c15ba5e6f29 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -3980,18 +3980,6 @@ typedef struct AlterSystemStmt VariableSetStmt *setstmt; /* SET subcommand */ } AlterSystemStmt; =20 -/* ---------------------- - * Cluster Statement (support pbrown's cluster index implementation) - * ---------------------- - */ -typedef struct ClusterStmt -{ - NodeTag type; - RangeVar *relation; /* relation being indexed, or NULL if all */ - char *indexname; /* original index defined */ - List *params; /* list of DefElem nodes */ -} ClusterStmt; - /* ---------------------- * Vacuum and Analyze Statements * @@ -4004,7 +3992,7 @@ typedef struct VacuumStmt NodeTag type; List *options; /* list of DefElem nodes */ List *rels; /* list of VacuumRelation, or NIL for all */ - bool is_vacuumcmd; /* true for VACUUM, false for ANALYZE */ + bool is_vacuumcmd; /* true for VACUUM, false otherwise */ } VacuumStmt; =20 /* @@ -4022,6 +4010,27 @@ typedef struct VacuumRelation List *va_cols; /* list of column names, or NIL for all */ } VacuumRelation; =20 +/* ---------------------- + * Repack Statement + * ---------------------- + */ +typedef enum RepackCommand +{ + REPACK_COMMAND_CLUSTER =3D 1, + REPACK_COMMAND_REPACK, + REPACK_COMMAND_VACUUMFULL, +} RepackCommand; + +typedef struct RepackStmt +{ + NodeTag type; + RepackCommand command; /* type of command being run */ + VacuumRelation *relation; /* relation being repacked */ + char *indexname; /* order tuples by this index */ + bool usingindex; /* whether USING INDEX is specified */ + List *params; /* list of DefElem nodes */ +} RepackStmt; + /* ---------------------- * Explain Statement * diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h index f7753c5c8a8..6f74a8c05c7 100644 --- a/src/include/parser/kwlist.h +++ b/src/include/parser/kwlist.h @@ -377,6 +377,7 @@ PG_KEYWORD("reindex", REINDEX, UNRESERVED_KEYWORD, BARE= _LABEL) PG_KEYWORD("relative", RELATIVE_P, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("release", RELEASE, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("rename", RENAME, UNRESERVED_KEYWORD, BARE_LABEL) +PG_KEYWORD("repack", REPACK, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("repeatable", REPEATABLE, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("replace", REPLACE, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("replica", REPLICA, UNRESERVED_KEYWORD, BARE_LABEL) diff --git a/src/include/tcop/cmdtaglist.h b/src/include/tcop/cmdtaglist.h index 1290c9bab68..652dc61b834 100644 --- a/src/include/tcop/cmdtaglist.h +++ b/src/include/tcop/cmdtaglist.h @@ -196,6 +196,7 @@ PG_CMDTAG(CMDTAG_REASSIGN_OWNED, "REASSIGN OWNED", fals= e, false, false) PG_CMDTAG(CMDTAG_REFRESH_MATERIALIZED_VIEW, "REFRESH MATERIALIZED VIEW", t= rue, false, false) PG_CMDTAG(CMDTAG_REINDEX, "REINDEX", true, false, false) PG_CMDTAG(CMDTAG_RELEASE, "RELEASE", false, false, false) +PG_CMDTAG(CMDTAG_REPACK, "REPACK", false, false, false) PG_CMDTAG(CMDTAG_RESET, "RESET", false, false, false) PG_CMDTAG(CMDTAG_REVOKE, "REVOKE", true, false, false) PG_CMDTAG(CMDTAG_REVOKE_ROLE, "REVOKE ROLE", false, false, false) diff --git a/src/include/utils/backend_progress.h b/src/include/utils/backe= nd_progress.h index 19f63b41431..6300dbd15d5 100644 --- a/src/include/utils/backend_progress.h +++ b/src/include/utils/backend_progress.h @@ -24,10 +24,10 @@ typedef enum ProgressCommandType PROGRESS_COMMAND_INVALID, PROGRESS_COMMAND_VACUUM, PROGRESS_COMMAND_ANALYZE, - PROGRESS_COMMAND_CLUSTER, PROGRESS_COMMAND_CREATE_INDEX, PROGRESS_COMMAND_BASEBACKUP, PROGRESS_COMMAND_COPY, + PROGRESS_COMMAND_REPACK, } ProgressCommandType; =20 #define PGSTAT_NUM_PROGRESS_PARAM 20 diff --git a/src/test/regress/expected/cluster.out b/src/test/regress/expec= ted/cluster.out index 4d40a6809ab..277854418fa 100644 --- a/src/test/regress/expected/cluster.out +++ b/src/test/regress/expected/cluster.out @@ -495,6 +495,43 @@ ALTER TABLE clstrpart SET WITHOUT CLUSTER; ERROR: cannot mark index clustered in partitioned table ALTER TABLE clstrpart CLUSTER ON clstrpart_idx; ERROR: cannot mark index clustered in partitioned table +-- Check that REPACK sets new relfilenodes: it should process exactly the = same +-- tables as CLUSTER did. +DROP TABLE old_cluster_info; +DROP TABLE new_cluster_info; +CREATE TEMP TABLE old_cluster_info AS SELECT relname, level, relfilenode, = relkind FROM pg_partition_tree('clstrpart'::regclass) AS tree JOIN pg_class= c ON c.oid=3Dtree.relid ; +REPACK clstrpart USING INDEX clstrpart_idx; +CREATE TEMP TABLE new_cluster_info AS SELECT relname, level, relfilenode, = relkind FROM pg_partition_tree('clstrpart'::regclass) AS tree JOIN pg_class= c ON c.oid=3Dtree.relid ; +SELECT relname, old.level, old.relkind, old.relfilenode =3D new.relfilenod= e FROM old_cluster_info AS old JOIN new_cluster_info AS new USING (relname)= ORDER BY relname COLLATE "C"; + relname | level | relkind | ?column?=20 +-------------+-------+---------+---------- + clstrpart | 0 | p | t + clstrpart1 | 1 | p | t + clstrpart11 | 2 | r | f + clstrpart12 | 2 | p | t + clstrpart2 | 1 | r | f + clstrpart3 | 1 | p | t + clstrpart33 | 2 | r | f +(7 rows) + +-- And finally the same for REPACK w/o index. +DROP TABLE old_cluster_info; +DROP TABLE new_cluster_info; +CREATE TEMP TABLE old_cluster_info AS SELECT relname, level, relfilenode, = relkind FROM pg_partition_tree('clstrpart'::regclass) AS tree JOIN pg_class= c ON c.oid=3Dtree.relid ; +REPACK clstrpart; +CREATE TEMP TABLE new_cluster_info AS SELECT relname, level, relfilenode, = relkind FROM pg_partition_tree('clstrpart'::regclass) AS tree JOIN pg_class= c ON c.oid=3Dtree.relid ; +SELECT relname, old.level, old.relkind, old.relfilenode =3D new.relfilenod= e FROM old_cluster_info AS old JOIN new_cluster_info AS new USING (relname)= ORDER BY relname COLLATE "C"; + relname | level | relkind | ?column?=20 +-------------+-------+---------+---------- + clstrpart | 0 | p | t + clstrpart1 | 1 | p | t + clstrpart11 | 2 | r | f + clstrpart12 | 2 | p | t + clstrpart2 | 1 | r | f + clstrpart3 | 1 | p | t + clstrpart33 | 2 | r | f +(7 rows) + DROP TABLE clstrpart; -- Ownership of partitions is checked CREATE TABLE ptnowner(i int unique) PARTITION BY LIST (i); @@ -513,7 +550,7 @@ CREATE TEMP TABLE ptnowner_oldnodes AS JOIN pg_class AS c ON c.oid=3Dtree.relid; SET SESSION AUTHORIZATION regress_ptnowner; CLUSTER ptnowner USING ptnowner_i_idx; -WARNING: permission denied to cluster "ptnowner2", skipping it +WARNING: permission denied to execute CLUSTER on "ptnowner2", skipping it RESET SESSION AUTHORIZATION; SELECT a.relname, a.relfilenode=3Db.relfilenode FROM pg_class a JOIN ptnowner_oldnodes b USING (oid) ORDER BY a.relname COLLATE "C"; @@ -665,6 +702,101 @@ SELECT * FROM clstr_expression WHERE -a =3D -3 ORDER = BY -a, b; (4 rows) =20 COMMIT; +---------------------------------------------------------------------- +-- +-- REPACK +-- +---------------------------------------------------------------------- +-- REPACK handles individual tables identically to CLUSTER, but it's worth +-- checking if it handles table hierarchies identically as well. +REPACK clstr_tst USING INDEX clstr_tst_c; +-- Verify that inheritance link still works +INSERT INTO clstr_tst_inh VALUES (0, 100, 'in child table 2'); +SELECT a,b,c,substring(d for 30), length(d) from clstr_tst; + a | b | c | substring | length=20 +----+-----+------------------+--------------------------------+-------- + 10 | 14 | catorce | |=20=20=20= =20=20=20=20 + 18 | 5 | cinco | |=20=20=20= =20=20=20=20 + 9 | 4 | cuatro | |=20=20=20= =20=20=20=20 + 26 | 19 | diecinueve | |=20=20=20= =20=20=20=20 + 12 | 18 | dieciocho | |=20=20=20= =20=20=20=20 + 30 | 16 | dieciseis | |=20=20=20= =20=20=20=20 + 24 | 17 | diecisiete | |=20=20=20= =20=20=20=20 + 2 | 10 | diez | |=20=20=20= =20=20=20=20 + 23 | 12 | doce | |=20=20=20= =20=20=20=20 + 11 | 2 | dos | |=20=20=20= =20=20=20=20 + 25 | 9 | nueve | |=20=20=20= =20=20=20=20 + 31 | 8 | ocho | |=20=20=20= =20=20=20=20 + 1 | 11 | once | |=20=20=20= =20=20=20=20 + 28 | 15 | quince | |=20=20=20= =20=20=20=20 + 32 | 6 | seis | xyzzyxyzzyxyzzyxyzzyxyzzyxyzzy | 500000 + 29 | 7 | siete | |=20=20=20= =20=20=20=20 + 15 | 13 | trece | |=20=20=20= =20=20=20=20 + 22 | 30 | treinta | |=20=20=20= =20=20=20=20 + 17 | 32 | treinta y dos | |=20=20=20= =20=20=20=20 + 3 | 31 | treinta y uno | |=20=20=20= =20=20=20=20 + 5 | 3 | tres | |=20=20=20= =20=20=20=20 + 20 | 1 | uno | |=20=20=20= =20=20=20=20 + 6 | 20 | veinte | |=20=20=20= =20=20=20=20 + 14 | 25 | veinticinco | |=20=20=20= =20=20=20=20 + 21 | 24 | veinticuatro | |=20=20=20= =20=20=20=20 + 4 | 22 | veintidos | |=20=20=20= =20=20=20=20 + 19 | 29 | veintinueve | |=20=20=20= =20=20=20=20 + 16 | 28 | veintiocho | |=20=20=20= =20=20=20=20 + 27 | 26 | veintiseis | |=20=20=20= =20=20=20=20 + 13 | 27 | veintisiete | |=20=20=20= =20=20=20=20 + 7 | 23 | veintitres | |=20=20=20= =20=20=20=20 + 8 | 21 | veintiuno | |=20=20=20= =20=20=20=20 + 0 | 100 | in child table | |=20=20=20= =20=20=20=20 + 0 | 100 | in child table 2 | |=20=20=20= =20=20=20=20 +(34 rows) + +-- Verify that foreign key link still works +INSERT INTO clstr_tst (b, c) VALUES (1111, 'this should fail'); +ERROR: insert or update on table "clstr_tst" violates foreign key constra= int "clstr_tst_con" +DETAIL: Key (b)=3D(1111) is not present in table "clstr_tst_s". +SELECT conname FROM pg_constraint WHERE conrelid =3D 'clstr_tst'::regclass +ORDER BY 1; + conname=20=20=20=20=20=20=20=20 +---------------------- + clstr_tst_a_not_null + clstr_tst_con + clstr_tst_pkey +(3 rows) + +-- Verify partial analyze works +REPACK (ANALYZE) clstr_tst (a); +REPACK (ANALYZE) clstr_tst; +REPACK (VERBOSE) clstr_tst (a); +ERROR: ANALYZE option must be specified when a column list is provided +-- REPACK w/o argument performs no ordering, so we can only check which ta= bles +-- have the relfilenode changed. +RESET SESSION AUTHORIZATION; +CREATE TEMP TABLE relnodes_old AS +(SELECT relname, relfilenode +FROM pg_class +WHERE relname IN ('clstr_1', 'clstr_2', 'clstr_3')); +SET SESSION AUTHORIZATION regress_clstr_user; +SET client_min_messages =3D ERROR; -- order of "skipping" warnings may va= ry +REPACK; +RESET client_min_messages; +RESET SESSION AUTHORIZATION; +CREATE TEMP TABLE relnodes_new AS +(SELECT relname, relfilenode +FROM pg_class +WHERE relname IN ('clstr_1', 'clstr_2', 'clstr_3')); +-- Do the actual comparison. Unlike CLUSTER, clstr_3 should have been +-- processed because there is nothing like clustering index here. +SELECT o.relname FROM relnodes_old o +JOIN relnodes_new n ON o.relname =3D n.relname +WHERE o.relfilenode <> n.relfilenode +ORDER BY o.relname; + relname=20 +--------- + clstr_1 + clstr_3 +(2 rows) + -- clean up DROP TABLE clustertest; DROP TABLE clstr_1; diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expecte= d/rules.out index f4ee2bd7459..48461550636 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -2002,34 +2002,23 @@ pg_stat_progress_basebackup| SELECT pid, ELSE NULL::text END AS backup_type FROM pg_stat_get_progress_info('BASEBACKUP'::text) s(pid, datid, relid,= param1, param2, param3, param4, param5, param6, param7, param8, param9, pa= ram10, param11, param12, param13, param14, param15, param16, param17, param= 18, param19, param20); -pg_stat_progress_cluster| SELECT s.pid, - s.datid, - d.datname, - s.relid, - CASE s.param1 - WHEN 1 THEN 'CLUSTER'::text - WHEN 2 THEN 'VACUUM FULL'::text - ELSE NULL::text +pg_stat_progress_cluster| SELECT pid, + datid, + datname, + relid, + CASE + WHEN (command =3D ANY (ARRAY['CLUSTER'::text, 'VACUUM FULL'::t= ext])) THEN command + WHEN (repack_index_relid =3D (0)::oid) THEN 'VACUUM FULL'::text + ELSE 'CLUSTER'::text END AS command, - CASE s.param2 - WHEN 0 THEN 'initializing'::text - WHEN 1 THEN 'seq scanning heap'::text - WHEN 2 THEN 'index scanning heap'::text - WHEN 3 THEN 'sorting tuples'::text - WHEN 4 THEN 'writing new heap'::text - WHEN 5 THEN 'swapping relation files'::text - WHEN 6 THEN 'rebuilding index'::text - WHEN 7 THEN 'performing final cleanup'::text - ELSE NULL::text - END AS phase, - (s.param3)::oid AS cluster_index_relid, - s.param4 AS heap_tuples_scanned, - s.param5 AS heap_tuples_written, - s.param6 AS heap_blks_total, - s.param7 AS heap_blks_scanned, - s.param8 AS index_rebuild_count - FROM (pg_stat_get_progress_info('CLUSTER'::text) s(pid, datid, relid, p= aram1, param2, param3, param4, param5, param6, param7, param8, param9, para= m10, param11, param12, param13, param14, param15, param16, param17, param18= , param19, param20) - LEFT JOIN pg_database d ON ((s.datid =3D d.oid))); + phase, + repack_index_relid AS cluster_index_relid, + heap_tuples_scanned, + heap_tuples_written, + heap_blks_total, + heap_blks_scanned, + index_rebuild_count + FROM pg_stat_progress_repack; pg_stat_progress_copy| SELECT s.pid, s.datid, d.datname, @@ -2089,6 +2078,35 @@ pg_stat_progress_create_index| SELECT s.pid, s.param15 AS partitions_done FROM (pg_stat_get_progress_info('CREATE INDEX'::text) s(pid, datid, rel= id, param1, param2, param3, param4, param5, param6, param7, param8, param9,= param10, param11, param12, param13, param14, param15, param16, param17, pa= ram18, param19, param20) LEFT JOIN pg_database d ON ((s.datid =3D d.oid))); +pg_stat_progress_repack| SELECT s.pid, + s.datid, + d.datname, + s.relid, + CASE s.param1 + WHEN 1 THEN 'CLUSTER'::text + WHEN 2 THEN 'REPACK'::text + WHEN 3 THEN 'VACUUM FULL'::text + ELSE NULL::text + END AS command, + CASE s.param2 + WHEN 0 THEN 'initializing'::text + WHEN 1 THEN 'seq scanning heap'::text + WHEN 2 THEN 'index scanning heap'::text + WHEN 3 THEN 'sorting tuples'::text + WHEN 4 THEN 'writing new heap'::text + WHEN 5 THEN 'swapping relation files'::text + WHEN 6 THEN 'rebuilding index'::text + WHEN 7 THEN 'performing final cleanup'::text + ELSE NULL::text + END AS phase, + (s.param3)::oid AS repack_index_relid, + s.param4 AS heap_tuples_scanned, + s.param5 AS heap_tuples_written, + s.param6 AS heap_blks_total, + s.param7 AS heap_blks_scanned, + s.param8 AS index_rebuild_count + FROM (pg_stat_get_progress_info('REPACK'::text) s(pid, datid, relid, pa= ram1, param2, param3, param4, param5, param6, param7, param8, param9, param= 10, param11, param12, param13, param14, param15, param16, param17, param18,= param19, param20) + LEFT JOIN pg_database d ON ((s.datid =3D d.oid))); pg_stat_progress_vacuum| SELECT s.pid, s.datid, d.datname, diff --git a/src/test/regress/sql/cluster.sql b/src/test/regress/sql/cluste= r.sql index b7115f86104..c976823a3cb 100644 --- a/src/test/regress/sql/cluster.sql +++ b/src/test/regress/sql/cluster.sql @@ -76,7 +76,6 @@ INSERT INTO clstr_tst (b, c) VALUES (1111, 'this should f= ail'); SELECT conname FROM pg_constraint WHERE conrelid =3D 'clstr_tst'::regclass ORDER BY 1; =20 - SELECT relname, relkind, EXISTS(SELECT 1 FROM pg_class WHERE oid =3D c.reltoastrelid) AS hastoa= st FROM pg_class c WHERE relname LIKE 'clstr_tst%' ORDER BY relname; @@ -229,6 +228,24 @@ SELECT relname, old.level, old.relkind, old.relfilenod= e =3D new.relfilenode FROM o CLUSTER clstrpart; ALTER TABLE clstrpart SET WITHOUT CLUSTER; ALTER TABLE clstrpart CLUSTER ON clstrpart_idx; + +-- Check that REPACK sets new relfilenodes: it should process exactly the = same +-- tables as CLUSTER did. +DROP TABLE old_cluster_info; +DROP TABLE new_cluster_info; +CREATE TEMP TABLE old_cluster_info AS SELECT relname, level, relfilenode, = relkind FROM pg_partition_tree('clstrpart'::regclass) AS tree JOIN pg_class= c ON c.oid=3Dtree.relid ; +REPACK clstrpart USING INDEX clstrpart_idx; +CREATE TEMP TABLE new_cluster_info AS SELECT relname, level, relfilenode, = relkind FROM pg_partition_tree('clstrpart'::regclass) AS tree JOIN pg_class= c ON c.oid=3Dtree.relid ; +SELECT relname, old.level, old.relkind, old.relfilenode =3D new.relfilenod= e FROM old_cluster_info AS old JOIN new_cluster_info AS new USING (relname)= ORDER BY relname COLLATE "C"; + +-- And finally the same for REPACK w/o index. +DROP TABLE old_cluster_info; +DROP TABLE new_cluster_info; +CREATE TEMP TABLE old_cluster_info AS SELECT relname, level, relfilenode, = relkind FROM pg_partition_tree('clstrpart'::regclass) AS tree JOIN pg_class= c ON c.oid=3Dtree.relid ; +REPACK clstrpart; +CREATE TEMP TABLE new_cluster_info AS SELECT relname, level, relfilenode, = relkind FROM pg_partition_tree('clstrpart'::regclass) AS tree JOIN pg_class= c ON c.oid=3Dtree.relid ; +SELECT relname, old.level, old.relkind, old.relfilenode =3D new.relfilenod= e FROM old_cluster_info AS old JOIN new_cluster_info AS new USING (relname)= ORDER BY relname COLLATE "C"; + DROP TABLE clstrpart; =20 -- Ownership of partitions is checked @@ -313,6 +330,57 @@ EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHE= RE -a =3D -3 ORDER BY -a, b; SELECT * FROM clstr_expression WHERE -a =3D -3 ORDER BY -a, b; COMMIT; =20 +---------------------------------------------------------------------- +-- +-- REPACK +-- +---------------------------------------------------------------------- + +-- REPACK handles individual tables identically to CLUSTER, but it's worth +-- checking if it handles table hierarchies identically as well. +REPACK clstr_tst USING INDEX clstr_tst_c; + +-- Verify that inheritance link still works +INSERT INTO clstr_tst_inh VALUES (0, 100, 'in child table 2'); +SELECT a,b,c,substring(d for 30), length(d) from clstr_tst; + +-- Verify that foreign key link still works +INSERT INTO clstr_tst (b, c) VALUES (1111, 'this should fail'); + +SELECT conname FROM pg_constraint WHERE conrelid =3D 'clstr_tst'::regclass +ORDER BY 1; + +-- Verify partial analyze works +REPACK (ANALYZE) clstr_tst (a); +REPACK (ANALYZE) clstr_tst; +REPACK (VERBOSE) clstr_tst (a); + +-- REPACK w/o argument performs no ordering, so we can only check which ta= bles +-- have the relfilenode changed. +RESET SESSION AUTHORIZATION; +CREATE TEMP TABLE relnodes_old AS +(SELECT relname, relfilenode +FROM pg_class +WHERE relname IN ('clstr_1', 'clstr_2', 'clstr_3')); + +SET SESSION AUTHORIZATION regress_clstr_user; +SET client_min_messages =3D ERROR; -- order of "skipping" warnings may va= ry +REPACK; +RESET client_min_messages; + +RESET SESSION AUTHORIZATION; +CREATE TEMP TABLE relnodes_new AS +(SELECT relname, relfilenode +FROM pg_class +WHERE relname IN ('clstr_1', 'clstr_2', 'clstr_3')); + +-- Do the actual comparison. Unlike CLUSTER, clstr_3 should have been +-- processed because there is nothing like clustering index here. +SELECT o.relname FROM relnodes_old o +JOIN relnodes_new n ON o.relname =3D n.relname +WHERE o.relfilenode <> n.relfilenode +ORDER BY o.relname; + -- clean up DROP TABLE clustertest; DROP TABLE clstr_1; diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs= .list index 1c8610fd46c..da0df6e89d6 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -2576,6 +2576,8 @@ ReorderBufferTupleCidKey ReorderBufferUpdateProgressTxnCB ReorderTuple RepOriginId +RepackCommand +RepackStmt ReparameterizeForeignPathByChild_function ReplaceVarsFromTargetList_context ReplaceVarsNoMatchOption --=20 2.47.3 --=-=-= Content-Type: text/x-diff Content-Disposition: attachment; filename=v31-0002-Refactor-index_concurrently_create_copy-for-use-with.patch ^ permalink raw reply [nested|flat] 280+ messages in thread
end of thread, other threads:[~2026-01-22 08:23 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 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 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/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 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 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/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 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/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 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/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 2/8] 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 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/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/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 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/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 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/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/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/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/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/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/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/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 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/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/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/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 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/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/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/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 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/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/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 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/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 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/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 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 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/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 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 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/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/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/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/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/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/7] 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 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/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/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/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/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/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 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/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 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 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 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 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 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/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 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/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/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/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]> 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]> 2026-01-22 08:23 [PATCH 1/6] Add REPACK command Antonin Houska <[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