67 int *numSkipArrayKeys_out);
70 const Datum *elems,
int nelems);
74 bool reverse,
Datum *elems,
int nelems);
77 Oid origelemtype,
Oid nextelemtype,
78 Datum *elems_orig,
int *nelems_orig,
79 Datum *elems_next,
int nelems_next);
199 int new_numberOfKeys;
200 int numberOfEqualCols;
204 redundant_key_kept =
false;
207 int *keyDataMap = NULL;
223 if (numberOfKeys < 1)
241 inkeys = arrayKeyData;
245 numberOfKeys *
sizeof(
int));
259 if (inkeys[0].sk_attno < 1)
260 elog(
ERROR,
"btree index keys must be ordered by attribute");
263 if (numberOfKeys == 1)
271 if (inkeys[0].sk_attno == 1)
293 new_numberOfKeys = 0;
294 numberOfEqualCols = 0;
303 memset(xform, 0,
sizeof(xform));
310 for (
int i = 0;;
i++)
315 if (
i < numberOfKeys)
330 if (
i == numberOfKeys || inkey->
sk_attno != attno)
332 int priorNumberOfEqualCols = numberOfEqualCols;
335 if (i < numberOfKeys && inkey->sk_attno < attno)
336 elog(
ERROR,
"btree index keys must be ordered by attribute");
401 xform[
j].inkey = NULL;
402 xform[
j].inkeyi = -1;
405 redundant_key_kept =
true;
427 redundant_key_kept =
true;
446 redundant_key_kept =
true;
467 keyDataMap[new_numberOfKeys - 1] = xform[
j].inkeyi;
468 if (priorNumberOfEqualCols == attno - 1)
476 if (
i == numberOfKeys)
481 memset(xform, 0,
sizeof(xform));
499 if (xform[
j].inkey == NULL)
502 xform[
j].inkey = inkey;
504 xform[
j].arrayidx = arrayidx;
531 array = &so->
arrayKeys[xform[
j].arrayidx - 1];
551 array, orderproc, &test_result))
562 xform[
j].inkey = inkey;
564 xform[
j].arrayidx = arrayidx;
602 keyDataMap[new_numberOfKeys - 1] = xform[
j].inkeyi;
603 if (numberOfEqualCols == attno - 1)
605 xform[
j].inkey = inkey;
607 xform[
j].arrayidx = arrayidx;
608 redundant_key_kept =
true;
789 elog(
ERROR,
"unrecognized StrategyNumber: %d",
928 *result = (leftnull < rightnull);
931 *result = (leftnull <= rightnull);
934 *result = (leftnull == rightnull);
937 *result = (leftnull >= rightnull);
940 *result = (leftnull > rightnull);
943 elog(
ERROR,
"unrecognized StrategyNumber: %d", (
int) strat);
980 if (leftarray && rightarray)
995 orderproc, array, result);
998 orderproc, array, result);
1017 lefttype = opcintype;
1020 righttype = opcintype;
1029 if (lefttype == opcintype && righttype == optype)
1156 Oid arraysk_elemtype;
1179 orderprocp = &crosstypeproc;
1186 arraysk, &cmpresult);
1194 if (cmpresult >= cmpexact)
1197 new_nelems = matchelem;
1216 if (cmpresult >= cmpexact)
1219 new_nelems = array->
num_elems - matchelem;
1221 sizeof(
Datum) * new_nelems);
1224 elog(
ERROR,
"unrecognized StrategyNumber: %d",
1230 Assert(new_nelems <= array->num_elems);
1233 *qual_ok = new_nelems > 0;
1330 elog(
ERROR,
"unrecognized StrategyNumber: %d",
1428 new_sk_argument = array->
sksup->
decrement(rel, orig_sk_argument, &uflow);
1486 new_sk_argument = array->
sksup->
increment(rel, orig_sk_argument, &oflow);
1546 *unmarkOrderProcs = NULL;
1568 haveReqEquals =
false;
1569 haveReqForward =
false;
1570 haveReqBackward =
false;
1581 haveReqEquals =
false;
1582 haveReqForward =
false;
1583 haveReqBackward =
false;
1594 unmarkikey[
i] =
true;
1607 haveReqEquals =
true;
1608 for (
int j = firsti;
j <
i;
j++)
1613 unmarkikey[
j] =
true;
1623 haveReqForward =
true;
1628 haveReqBackward =
true;
1636 unmarkikey[
i] =
true;
1678 memcpy(keepKeys + nkept, origkey,
sizeof(
ScanKeyData));
1682 keyDataMap[
i] = nkept;
1683 memcpy(keepOrderProcs + nkept, &so->
orderProcs[
i],
1695 unmark = unmarkKeys + nunmarked;
1701 memcpy(&unmarkOrderProcs[nunmarked], &so->
orderProcs[
i],
1740 Assert(nunmarked == nunmark);
1756 memcpy(so->
orderProcs + nkept, unmarkOrderProcs,
1760 for (
int arridx = 0; arridx < so->
numArrayKeys; arridx++)
1775 pfree(unmarkOrderProcs);
1776 pfree(keepOrderProcs);
1857 so->
skipScan = (numSkipArrayKeys > 0);
1860 if (numArrayKeys == 0)
1868 numArrayKeyData = scan->
numberOfKeys + numSkipArrayKeys;
1876 "BTree array context",
1893 numArrayKeyData = 0;
1894 for (
int input_ikey = 0; input_ikey < scan->
numberOfKeys; input_ikey++)
1912 cur = &arrayKeyData[numArrayKeyData];
1915 while (numSkipArrayKeys && attno_skip <= inkey->sk_attno)
1917 Oid opfamily = rel->rd_opfamily[attno_skip - 1];
1918 Oid opcintype = rel->rd_opcintype[attno_skip - 1];
1919 Oid collation = rel->rd_indcollation[attno_skip - 1];
1920 Oid eq_op = skip_eq_ops[attno_skip - 1];
1937 Assert(input_ikey < scan->numberOfKeys - 1);
1950 elog(
ERROR,
"missing oprcode for skipping equals operator %u", eq_op);
1967 reverse = (indoption[attno_skip - 1] & INDOPTION_DESC) != 0;
1986 cur = &arrayKeyData[numArrayKeyData];
2023 &elmlen, &elmbyval, &elmalign);
2026 elmlen, elmbyval, elmalign,
2027 &elem_values, &elem_nulls, &num_elems);
2034 for (
int j = 0;
j < num_elems;
j++)
2037 elem_values[num_nonnulls++] = elem_values[
j];
2043 if (num_nonnulls == 0)
2055 elemtype =
cur->sk_subtype;
2057 elemtype = rel->rd_opcintype[
cur->sk_attno - 1];
2064 switch (
cur->sk_strategy)
2071 elem_values, num_nonnulls);
2082 elem_values, num_nonnulls);
2086 elog(
ERROR,
"unrecognized StrategyNumber: %d",
2087 (
int)
cur->sk_strategy);
2100 &so->
orderProcs[numArrayKeyData], &sortprocp);
2108 reverse = (indoption[
cur->sk_attno - 1] & INDOPTION_DESC) != 0;
2110 elem_values, num_nonnulls);
2112 if (origarrayatt ==
cur->sk_attno)
2127 origelemtype, elemtype,
2129 elem_values, num_elems))
2164 origarrayatt =
cur->sk_attno;
2165 origarraykey = numArrayKeys;
2166 origelemtype = elemtype;
2186 *new_numberOfKeys = numArrayKeyData;
2190 return arrayKeyData;
2232 for (
int output_ikey = 0; output_ikey < so->
numberOfKeys; output_ikey++)
2243 input_ikey = keyDataMap[output_ikey];
2245 Assert(last_equal_output_ikey < output_ikey);
2246 Assert(last_equal_output_ikey < input_ikey);
2247 last_equal_output_ikey = output_ikey;
2270 elemtype = rel->rd_opcintype[outkey->
sk_attno - 1];
2314 outkey->
sk_flags &= ~SK_SEARCHARRAY;
2323 memmove(array, array + 1,
2364 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2365 errmsg_internal(
"number of array scan keys left by preprocessing (%d) exceeds the maximum allowed by parallel btree index scans (%d)",
2405 int *numSkipArrayKeys_out)
2410 bool attno_has_equal =
false,
2411 attno_has_rowcompare =
false;
2412 int numSAOPArrayKeys,
2414 prev_numSkipArrayKeys;
2419 numSAOPArrayKeys = 0;
2420 *numSkipArrayKeys_out = prev_numSkipArrayKeys = numSkipArrayKeys = 0;
2429#ifdef DEBUG_DISABLE_SKIP_SCAN
2431 return numSAOPArrayKeys;
2434 for (
int i = 0;;
i++)
2442 while (attno_skip < attno_inkey)
2448 skip_eq_ops_out[attno_skip - 1] =
2451 if (!
OidIsValid(skip_eq_ops_out[attno_skip - 1]))
2457 *numSkipArrayKeys_out = prev_numSkipArrayKeys;
2458 return numSAOPArrayKeys + prev_numSkipArrayKeys;
2466 prev_numSkipArrayKeys = numSkipArrayKeys;
2499 if (attno_has_rowcompare)
2506 if (attno_inkey < inkey->sk_attno)
2512 if (attno_has_equal)
2515 skip_eq_ops_out[attno_skip - 1] =
InvalidOid;
2523 skip_eq_ops_out[attno_skip - 1] =
2527 if (!
OidIsValid(skip_eq_ops_out[attno_skip - 1]))
2543 attno_has_equal =
false;
2553 attno_has_equal =
true;
2555 attno_has_rowcompare =
true;
2558 *numSkipArrayKeys_out = numSkipArrayKeys;
2559 return numSAOPArrayKeys + numSkipArrayKeys;
2572 const Datum *elems,
int nelems)
2596 elog(
ERROR,
"missing operator %d(%u,%u) in opfamily %u",
2597 strat, elemtype, elemtype,
2601 elog(
ERROR,
"missing oprcode for operator %u", cmp_op);
2607 for (
i = 1;
i < nelems;
i++)
2658 if (elemtype == opcintype)
2663 *sortprocp = orderproc;
2682 elog(
ERROR,
"missing support function %d(%u,%u) for attribute %d of index \"%s\"",
2704 elog(
ERROR,
"missing support function %d(%u,%u) for attribute %d of index \"%s\"",
2724 Datum *elems,
int nelems)
2768 bool reverse,
Oid origelemtype,
Oid nextelemtype,
2769 Datum *elems_orig,
int *nelems_orig,
2770 Datum *elems_next,
int nelems_next)
2775 int nelems_orig_start = *nelems_orig,
2776 nelems_orig_merged = 0;
2783 if (origelemtype != nextelemtype)
2800 mergeproc = &crosstypeproc;
2804 cxt.sortproc = mergeproc;
2806 cxt.reverse = reverse;
2808 for (
int i = 0,
j = 0;
i < nelems_orig_start &&
j < nelems_next;)
2810 Datum *oelem = elems_orig +
i,
2811 *nelem = elems_next +
j;
2816 elems_orig[nelems_orig_merged++] = *oelem;
2826 *nelems_orig = nelems_orig_merged;
#define DatumGetArrayTypeP(X)
void deconstruct_array(const ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
#define InvalidAttrNumber
#define RegProcedureIsValid(p)
#define INVERT_COMPARE_RESULT(var)
#define PG_USED_FOR_ASSERTS_ONLY
#define OidIsValid(objectId)
int errmsg_internal(const char *fmt,...)
int errcode(int sqlerrcode)
#define ereport(elevel,...)
Datum OidFunctionCall2Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2)
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
void fmgr_info(Oid functionId, FmgrInfo *finfo)
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
static int compare(const void *arg1, const void *arg2)
Assert(PointerIsAligned(start, uint64))
FmgrInfo * index_getprocinfo(Relation irel, AttrNumber attnum, uint16 procnum)
static int pg_cmp_s32(int32 a, int32 b)
if(TABLE==NULL||TABLE_index==NULL)
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
RegProcedure get_opcode(Oid opno)
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
void * MemoryContextAlloc(MemoryContext context, Size size)
void MemoryContextReset(MemoryContext context)
void * repalloc(void *pointer, Size size)
void pfree(void *pointer)
void * palloc0(Size size)
MemoryContext CurrentMemoryContext
#define AllocSetContextCreate
#define ALLOCSET_SMALL_SIZES
static bool _bt_merge_arrays(IndexScanDesc scan, ScanKey skey, FmgrInfo *sortproc, bool reverse, Oid origelemtype, Oid nextelemtype, Datum *elems_orig, int *nelems_orig, Datum *elems_next, int nelems_next)
static void _bt_skiparray_strat_increment(IndexScanDesc scan, ScanKey arraysk, BTArrayKeyInfo *array)
static int _bt_num_array_keys(IndexScanDesc scan, Oid *skip_eq_ops_out, int *numSkipArrayKeys_out)
static bool _bt_saoparray_shrink(IndexScanDesc scan, ScanKey arraysk, ScanKey skey, FmgrInfo *orderproc, BTArrayKeyInfo *array, bool *qual_ok)
struct BTScanKeyPreproc BTScanKeyPreproc
static void _bt_skiparray_strat_adjust(IndexScanDesc scan, ScanKey arraysk, BTArrayKeyInfo *array)
struct BTSortArrayContext BTSortArrayContext
static int _bt_reorder_array_cmp(const void *a, const void *b)
static bool _bt_skiparray_shrink(IndexScanDesc scan, ScanKey skey, BTArrayKeyInfo *array, bool *qual_ok)
static bool _bt_fix_scankey_strategy(ScanKey skey, int16 *indoption)
static void _bt_unmark_keys(IndexScanDesc scan, int *keyDataMap)
static void _bt_mark_scankey_required(ScanKey skey)
static ScanKey _bt_preprocess_array_keys(IndexScanDesc scan, int *new_numberOfKeys)
static int _bt_compare_array_elements(const void *a, const void *b, void *arg)
static void _bt_preprocess_array_keys_final(IndexScanDesc scan, int *keyDataMap)
static void _bt_setup_array_cmp(IndexScanDesc scan, ScanKey skey, Oid elemtype, FmgrInfo *orderproc, FmgrInfo **sortprocp)
static int _bt_sort_array_elements(ScanKey skey, FmgrInfo *sortproc, bool reverse, Datum *elems, int nelems)
static Datum _bt_find_extreme_element(IndexScanDesc scan, ScanKey skey, Oid elemtype, StrategyNumber strat, const Datum *elems, int nelems)
static bool _bt_compare_scankey_args(IndexScanDesc scan, ScanKey op, ScanKey leftarg, ScanKey rightarg, BTArrayKeyInfo *array, FmgrInfo *orderproc, bool *result)
static void _bt_skiparray_strat_decrement(IndexScanDesc scan, ScanKey arraysk, BTArrayKeyInfo *array)
static bool _bt_compare_array_scankey_args(IndexScanDesc scan, ScanKey arraysk, ScanKey skey, FmgrInfo *orderproc, BTArrayKeyInfo *array, bool *qual_ok)
void _bt_preprocess_keys(IndexScanDesc scan)
#define SK_BT_INDOPTION_SHIFT
#define SK_BT_NULLS_FIRST
#define BTCommuteStrategyNumber(strat)
BTScanOpaqueData * BTScanOpaque
int _bt_binsrch_array_skey(FmgrInfo *orderproc, bool cur_elem_trig, ScanDirection dir, Datum tupdatum, bool tupnull, BTArrayKeyInfo *array, ScanKey cur, int32 *set_elem_result)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
void qsort_arg(void *base, size_t nel, size_t elsize, qsort_arg_comparator cmp, void *arg)
#define qsort(a, b, c, d)
static bool DatumGetBool(Datum X)
static Pointer DatumGetPointer(Datum X)
static int32 DatumGetInt32(Datum X)
static size_t qunique_arg(void *array, size_t elements, size_t width, int(*compare)(const void *, const void *, void *), void *arg)
#define RelationGetDescr(relation)
#define RelationGetRelationName(relation)
#define IndexRelationGetNumberOfKeyAttributes(relation)
void ScanKeyEntryInitialize(ScanKey entry, int flags, AttrNumber attributeNumber, StrategyNumber strategy, Oid subtype, Oid collation, RegProcedure procedure, Datum argument)
@ NoMovementScanDirection
SkipSupport PrepareSkipSupportFromOpclass(Oid opfamily, Oid opcintype, bool reverse)
#define BTGreaterStrategyNumber
#define BTMaxStrategyNumber
#define BTLessStrategyNumber
#define BTEqualStrategyNumber
#define BTLessEqualStrategyNumber
#define BTGreaterEqualStrategyNumber
BTArrayKeyInfo * arrayKeys
MemoryContext arrayContext
struct ScanKeyData * keyData
struct ParallelIndexScanDescData * parallel_scan
StrategyNumber sk_strategy
SkipSupportIncDec decrement
SkipSupportIncDec increment
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)