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);
208 int new_numberOfKeys;
209 int numberOfEqualCols;
213 redundant_key_kept =
false;
216 int *keyDataMap = NULL;
232 if (numberOfKeys < 1)
250 inkeys = arrayKeyData;
254 numberOfKeys *
sizeof(
int));
268 if (inkeys[0].sk_attno < 1)
269 elog(
ERROR,
"btree index keys must be ordered by attribute");
272 if (numberOfKeys == 1)
280 if (inkeys[0].sk_attno == 1)
302 new_numberOfKeys = 0;
303 numberOfEqualCols = 0;
312 memset(xform, 0,
sizeof(xform));
319 for (
int i = 0;;
i++)
324 if (
i < numberOfKeys)
339 if (
i == numberOfKeys || inkey->
sk_attno != attno)
341 int priorNumberOfEqualCols = numberOfEqualCols;
344 if (i < numberOfKeys && inkey->sk_attno < attno)
345 elog(
ERROR,
"btree index keys must be ordered by attribute");
410 xform[
j].inkey = NULL;
411 xform[
j].inkeyi = -1;
414 redundant_key_kept =
true;
436 redundant_key_kept =
true;
455 redundant_key_kept =
true;
476 keyDataMap[new_numberOfKeys - 1] = xform[
j].inkeyi;
477 if (priorNumberOfEqualCols == attno - 1)
485 if (
i == numberOfKeys)
490 memset(xform, 0,
sizeof(xform));
508 if (xform[
j].inkey == NULL)
511 xform[
j].inkey = inkey;
513 xform[
j].arrayidx = arrayidx;
540 array = &so->
arrayKeys[xform[
j].arrayidx - 1];
560 array, orderproc, &test_result))
571 xform[
j].inkey = inkey;
573 xform[
j].arrayidx = arrayidx;
611 keyDataMap[new_numberOfKeys - 1] = xform[
j].inkeyi;
612 if (numberOfEqualCols == attno - 1)
614 xform[
j].inkey = inkey;
616 xform[
j].arrayidx = arrayidx;
617 redundant_key_kept =
true;
798 elog(
ERROR,
"unrecognized StrategyNumber: %d",
937 *result = (leftnull < rightnull);
940 *result = (leftnull <= rightnull);
943 *result = (leftnull == rightnull);
946 *result = (leftnull >= rightnull);
949 *result = (leftnull > rightnull);
952 elog(
ERROR,
"unrecognized StrategyNumber: %d", (
int) strat);
989 if (leftarray && rightarray)
1004 orderproc, array, result);
1005 else if (rightarray)
1007 orderproc, array, result);
1026 lefttype = opcintype;
1029 righttype = opcintype;
1038 if (lefttype == opcintype && righttype == optype)
1165 Oid arraysk_elemtype;
1188 orderprocp = &crosstypeproc;
1195 arraysk, &cmpresult);
1203 if (cmpresult >= cmpexact)
1206 new_nelems = matchelem;
1225 if (cmpresult >= cmpexact)
1228 new_nelems = array->
num_elems - matchelem;
1230 sizeof(
Datum) * new_nelems);
1233 elog(
ERROR,
"unrecognized StrategyNumber: %d",
1239 Assert(new_nelems <= array->num_elems);
1242 *qual_ok = new_nelems > 0;
1339 elog(
ERROR,
"unrecognized StrategyNumber: %d",
1437 new_sk_argument = array->
sksup->
decrement(rel, orig_sk_argument, &uflow);
1495 new_sk_argument = array->
sksup->
increment(rel, orig_sk_argument, &oflow);
1555 *unmarkOrderProcs = NULL;
1577 haveReqEquals =
false;
1578 haveReqForward =
false;
1579 haveReqBackward =
false;
1590 haveReqEquals =
false;
1591 haveReqForward =
false;
1592 haveReqBackward =
false;
1603 unmarkikey[
i] =
true;
1616 haveReqEquals =
true;
1617 for (
int j = firsti;
j <
i;
j++)
1622 unmarkikey[
j] =
true;
1632 haveReqForward =
true;
1637 haveReqBackward =
true;
1645 unmarkikey[
i] =
true;
1687 memcpy(keepKeys + nkept, origkey,
sizeof(
ScanKeyData));
1691 keyDataMap[
i] = nkept;
1692 memcpy(keepOrderProcs + nkept, &so->
orderProcs[
i],
1704 unmark = unmarkKeys + nunmarked;
1710 memcpy(&unmarkOrderProcs[nunmarked], &so->
orderProcs[
i],
1749 Assert(nunmarked == nunmark);
1765 memcpy(so->
orderProcs + nkept, unmarkOrderProcs,
1769 for (
int arridx = 0; arridx < so->
numArrayKeys; arridx++)
1784 pfree(unmarkOrderProcs);
1785 pfree(keepOrderProcs);
1866 so->
skipScan = (numSkipArrayKeys > 0);
1869 if (numArrayKeys == 0)
1877 numArrayKeyData = scan->
numberOfKeys + numSkipArrayKeys;
1885 "BTree array context",
1902 numArrayKeyData = 0;
1903 for (
int input_ikey = 0; input_ikey < scan->
numberOfKeys; input_ikey++)
1921 cur = &arrayKeyData[numArrayKeyData];
1924 while (numSkipArrayKeys && attno_skip <= inkey->sk_attno)
1926 Oid opfamily = rel->rd_opfamily[attno_skip - 1];
1927 Oid opcintype = rel->rd_opcintype[attno_skip - 1];
1928 Oid collation = rel->rd_indcollation[attno_skip - 1];
1929 Oid eq_op = skip_eq_ops[attno_skip - 1];
1946 Assert(input_ikey < scan->numberOfKeys - 1);
1959 elog(
ERROR,
"missing oprcode for skipping equals operator %u", eq_op);
1976 reverse = (indoption[attno_skip - 1] & INDOPTION_DESC) != 0;
1995 cur = &arrayKeyData[numArrayKeyData];
2032 &elmlen, &elmbyval, &elmalign);
2035 elmlen, elmbyval, elmalign,
2036 &elem_values, &elem_nulls, &num_elems);
2043 for (
int j = 0;
j < num_elems;
j++)
2046 elem_values[num_nonnulls++] = elem_values[
j];
2052 if (num_nonnulls == 0)
2064 elemtype =
cur->sk_subtype;
2066 elemtype = rel->rd_opcintype[
cur->sk_attno - 1];
2073 switch (
cur->sk_strategy)
2080 elem_values, num_nonnulls);
2091 elem_values, num_nonnulls);
2095 elog(
ERROR,
"unrecognized StrategyNumber: %d",
2096 (
int)
cur->sk_strategy);
2109 &so->
orderProcs[numArrayKeyData], &sortprocp);
2117 reverse = (indoption[
cur->sk_attno - 1] & INDOPTION_DESC) != 0;
2119 elem_values, num_nonnulls);
2121 if (origarrayatt ==
cur->sk_attno)
2136 origelemtype, elemtype,
2138 elem_values, num_elems))
2173 origarrayatt =
cur->sk_attno;
2174 origarraykey = numArrayKeys;
2175 origelemtype = elemtype;
2195 *new_numberOfKeys = numArrayKeyData;
2199 return arrayKeyData;
2241 for (
int output_ikey = 0; output_ikey < so->
numberOfKeys; output_ikey++)
2252 input_ikey = keyDataMap[output_ikey];
2254 Assert(last_equal_output_ikey < output_ikey);
2255 Assert(last_equal_output_ikey < input_ikey);
2256 last_equal_output_ikey = output_ikey;
2279 elemtype = rel->rd_opcintype[outkey->
sk_attno - 1];
2323 outkey->
sk_flags &= ~SK_SEARCHARRAY;
2332 memmove(array, array + 1,
2373 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2374 errmsg_internal(
"number of array scan keys left by preprocessing (%d) exceeds the maximum allowed by parallel btree index scans (%d)",
2414 int *numSkipArrayKeys_out)
2419 bool attno_has_equal =
false,
2420 attno_has_rowcompare =
false;
2421 int numSAOPArrayKeys,
2423 prev_numSkipArrayKeys;
2428 numSAOPArrayKeys = 0;
2429 *numSkipArrayKeys_out = prev_numSkipArrayKeys = numSkipArrayKeys = 0;
2438#ifdef DEBUG_DISABLE_SKIP_SCAN
2440 return numSAOPArrayKeys;
2443 for (
int i = 0;;
i++)
2451 while (attno_skip < attno_inkey)
2457 skip_eq_ops_out[attno_skip - 1] =
2460 if (!
OidIsValid(skip_eq_ops_out[attno_skip - 1]))
2466 *numSkipArrayKeys_out = prev_numSkipArrayKeys;
2467 return numSAOPArrayKeys + prev_numSkipArrayKeys;
2475 prev_numSkipArrayKeys = numSkipArrayKeys;
2508 if (attno_has_rowcompare)
2515 if (attno_inkey < inkey->sk_attno)
2521 if (attno_has_equal)
2524 skip_eq_ops_out[attno_skip - 1] =
InvalidOid;
2532 skip_eq_ops_out[attno_skip - 1] =
2536 if (!
OidIsValid(skip_eq_ops_out[attno_skip - 1]))
2552 attno_has_equal =
false;
2562 attno_has_equal =
true;
2564 attno_has_rowcompare =
true;
2567 *numSkipArrayKeys_out = numSkipArrayKeys;
2568 return numSAOPArrayKeys + numSkipArrayKeys;
2581 const Datum *elems,
int nelems)
2605 elog(
ERROR,
"missing operator %d(%u,%u) in opfamily %u",
2606 strat, elemtype, elemtype,
2610 elog(
ERROR,
"missing oprcode for operator %u", cmp_op);
2616 for (
i = 1;
i < nelems;
i++)
2667 if (elemtype == opcintype)
2672 *sortprocp = orderproc;
2691 elog(
ERROR,
"missing support function %d(%u,%u) for attribute %d of index \"%s\"",
2713 elog(
ERROR,
"missing support function %d(%u,%u) for attribute %d of index \"%s\"",
2733 Datum *elems,
int nelems)
2777 bool reverse,
Oid origelemtype,
Oid nextelemtype,
2778 Datum *elems_orig,
int *nelems_orig,
2779 Datum *elems_next,
int nelems_next)
2784 int nelems_orig_start = *nelems_orig,
2785 nelems_orig_merged = 0;
2792 if (origelemtype != nextelemtype)
2809 mergeproc = &crosstypeproc;
2813 cxt.sortproc = mergeproc;
2815 cxt.reverse = reverse;
2817 for (
int i = 0,
j = 0;
i < nelems_orig_start &&
j < nelems_next;)
2819 Datum *oelem = elems_orig +
i,
2820 *nelem = elems_next +
j;
2825 elems_orig[nelems_orig_merged++] = *oelem;
2835 *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)