62 int *numSkipArrayKeys_out);
65 Datum *elems,
int nelems);
69 bool reverse,
Datum *elems,
int nelems);
72 Oid origelemtype,
Oid nextelemtype,
73 Datum *elems_orig,
int *nelems_orig,
74 Datum *elems_next,
int nelems_next);
187 int new_numberOfKeys;
188 int numberOfEqualCols;
194 int *keyDataMap = NULL;
210 if (numberOfKeys < 1)
228 inkeys = arrayKeyData;
232 numberOfKeys *
sizeof(
int));
246 if (inkeys[0].sk_attno < 1)
247 elog(
ERROR,
"btree index keys must be ordered by attribute");
250 if (numberOfKeys == 1)
258 if (inkeys[0].sk_attno == 1)
280 new_numberOfKeys = 0;
281 numberOfEqualCols = 0;
290 memset(xform, 0,
sizeof(xform));
297 for (
int i = 0;;
i++)
302 if (
i < numberOfKeys)
317 if (
i == numberOfKeys || inkey->
sk_attno != attno)
319 int priorNumberOfEqualCols = numberOfEqualCols;
322 if (i < numberOfKeys && inkey->sk_attno < attno)
323 elog(
ERROR,
"btree index keys must be ordered by attribute");
388 xform[
j].inkey = NULL;
389 xform[
j].inkeyi = -1;
449 keyDataMap[new_numberOfKeys - 1] = xform[
j].inkeyi;
450 if (priorNumberOfEqualCols == attno - 1)
458 if (
i == numberOfKeys)
463 memset(xform, 0,
sizeof(xform));
476 keyDataMap[new_numberOfKeys - 1] =
i;
477 if (numberOfEqualCols == attno - 1)
500 if (xform[
j].inkey == NULL)
503 xform[
j].inkey = inkey;
505 xform[
j].arrayidx = arrayidx;
532 array = &so->
arrayKeys[xform[
j].arrayidx - 1];
552 array, orderproc, &test_result))
563 xform[
j].inkey = inkey;
565 xform[
j].arrayidx = arrayidx;
604 keyDataMap[new_numberOfKeys - 1] = xform[
j].inkeyi;
605 if (numberOfEqualCols == attno - 1)
607 xform[
j].inkey = inkey;
609 xform[
j].arrayidx = arrayidx;
778 elog(
ERROR,
"unrecognized StrategyNumber: %d",
905 *result = (leftnull < rightnull);
908 *result = (leftnull <= rightnull);
911 *result = (leftnull == rightnull);
914 *result = (leftnull >= rightnull);
917 *result = (leftnull > rightnull);
920 elog(
ERROR,
"unrecognized StrategyNumber: %d", (
int) strat);
947 if (leftarray && rightarray)
962 orderproc, array, result);
965 orderproc, array, result);
984 lefttype = opcintype;
987 righttype = opcintype;
996 if (lefttype == opcintype && righttype == optype)
1123 Oid arraysk_elemtype;
1146 orderprocp = &crosstypeproc;
1153 arraysk, &cmpresult);
1161 if (cmpresult >= cmpexact)
1164 new_nelems = matchelem;
1183 if (cmpresult >= cmpexact)
1186 new_nelems = array->
num_elems - matchelem;
1188 sizeof(
Datum) * new_nelems);
1191 elog(
ERROR,
"unrecognized StrategyNumber: %d",
1197 Assert(new_nelems <= array->num_elems);
1200 *qual_ok = new_nelems > 0;
1297 elog(
ERROR,
"unrecognized StrategyNumber: %d",
1394 new_sk_argument = array->
sksup->
decrement(rel, orig_sk_argument, &uflow);
1446 new_sk_argument = array->
sksup->
increment(rel, orig_sk_argument, &oflow);
1537 if (numArrayKeys == 0)
1545 numArrayKeyData = scan->
numberOfKeys + numSkipArrayKeys;
1553 "BTree array context",
1564 so->
skipScan = (numSkipArrayKeys > 0);
1571 numArrayKeyData = 0;
1572 for (
int input_ikey = 0; input_ikey < scan->
numberOfKeys; input_ikey++)
1590 cur = &arrayKeyData[numArrayKeyData];
1593 while (numSkipArrayKeys && attno_skip <= inkey->sk_attno)
1595 Oid opfamily = rel->rd_opfamily[attno_skip - 1];
1596 Oid opcintype = rel->rd_opcintype[attno_skip - 1];
1597 Oid collation = rel->rd_indcollation[attno_skip - 1];
1598 Oid eq_op = skip_eq_ops[attno_skip - 1];
1615 Assert(input_ikey < scan->numberOfKeys - 1);
1628 elog(
ERROR,
"missing oprcode for skipping equals operator %u", eq_op);
1645 reverse = (indoption[attno_skip - 1] & INDOPTION_DESC) != 0;
1664 cur = &arrayKeyData[numArrayKeyData];
1701 &elmlen, &elmbyval, &elmalign);
1704 elmlen, elmbyval, elmalign,
1705 &elem_values, &elem_nulls, &num_elems);
1712 for (
int j = 0;
j < num_elems;
j++)
1715 elem_values[num_nonnulls++] = elem_values[
j];
1721 if (num_nonnulls == 0)
1733 elemtype =
cur->sk_subtype;
1735 elemtype = rel->rd_opcintype[
cur->sk_attno - 1];
1742 switch (
cur->sk_strategy)
1749 elem_values, num_nonnulls);
1760 elem_values, num_nonnulls);
1764 elog(
ERROR,
"unrecognized StrategyNumber: %d",
1765 (
int)
cur->sk_strategy);
1778 &so->
orderProcs[numArrayKeyData], &sortprocp);
1786 reverse = (indoption[
cur->sk_attno - 1] & INDOPTION_DESC) != 0;
1788 elem_values, num_nonnulls);
1790 if (origarrayatt ==
cur->sk_attno)
1805 origelemtype, elemtype,
1807 elem_values, num_elems))
1842 origarrayatt =
cur->sk_attno;
1843 origarraykey = numArrayKeys;
1844 origelemtype = elemtype;
1864 *new_numberOfKeys = numArrayKeyData;
1868 return arrayKeyData;
1910 for (
int output_ikey = 0; output_ikey < so->
numberOfKeys; output_ikey++)
1921 input_ikey = keyDataMap[output_ikey];
1923 Assert(last_equal_output_ikey < output_ikey);
1924 Assert(last_equal_output_ikey < input_ikey);
1925 last_equal_output_ikey = output_ikey;
1948 elemtype = rel->rd_opcintype[outkey->
sk_attno - 1];
1992 outkey->
sk_flags &= ~SK_SEARCHARRAY;
2001 memmove(array, array + 1,
2042 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2043 errmsg_internal(
"number of array scan keys left by preprocessing (%d) exceeds the maximum allowed by parallel btree index scans (%d)",
2083 int *numSkipArrayKeys_out)
2088 bool attno_has_equal =
false,
2089 attno_has_rowcompare =
false;
2090 int numSAOPArrayKeys,
2092 prev_numSkipArrayKeys;
2097 numSAOPArrayKeys = 0;
2098 *numSkipArrayKeys_out = prev_numSkipArrayKeys = numSkipArrayKeys = 0;
2107#ifdef DEBUG_DISABLE_SKIP_SCAN
2109 return numSAOPArrayKeys;
2112 for (
int i = 0;;
i++)
2120 while (attno_skip < attno_inkey)
2126 skip_eq_ops_out[attno_skip - 1] =
2129 if (!
OidIsValid(skip_eq_ops_out[attno_skip - 1]))
2135 *numSkipArrayKeys_out = prev_numSkipArrayKeys;
2136 return numSAOPArrayKeys + prev_numSkipArrayKeys;
2144 prev_numSkipArrayKeys = numSkipArrayKeys;
2177 if (attno_has_rowcompare)
2184 if (attno_inkey < inkey->sk_attno)
2190 if (attno_has_equal)
2193 skip_eq_ops_out[attno_skip - 1] =
InvalidOid;
2201 skip_eq_ops_out[attno_skip - 1] =
2205 if (!
OidIsValid(skip_eq_ops_out[attno_skip - 1]))
2221 attno_has_equal =
false;
2231 attno_has_equal =
true;
2233 attno_has_rowcompare =
true;
2236 *numSkipArrayKeys_out = numSkipArrayKeys;
2237 return numSAOPArrayKeys + numSkipArrayKeys;
2250 Datum *elems,
int nelems)
2274 elog(
ERROR,
"missing operator %d(%u,%u) in opfamily %u",
2275 strat, elemtype, elemtype,
2279 elog(
ERROR,
"missing oprcode for operator %u", cmp_op);
2285 for (
i = 1;
i < nelems;
i++)
2336 if (elemtype == opcintype)
2341 *sortprocp = orderproc;
2360 elog(
ERROR,
"missing support function %d(%u,%u) for attribute %d of index \"%s\"",
2382 elog(
ERROR,
"missing support function %d(%u,%u) for attribute %d of index \"%s\"",
2402 Datum *elems,
int nelems)
2446 bool reverse,
Oid origelemtype,
Oid nextelemtype,
2447 Datum *elems_orig,
int *nelems_orig,
2448 Datum *elems_next,
int nelems_next)
2453 int nelems_orig_start = *nelems_orig,
2454 nelems_orig_merged = 0;
2461 if (origelemtype != nextelemtype)
2478 mergeproc = &crosstypeproc;
2482 cxt.sortproc = mergeproc;
2484 cxt.reverse = reverse;
2486 for (
int i = 0,
j = 0;
i < nelems_orig_start &&
j < nelems_next;)
2488 Datum *oelem = elems_orig +
i,
2489 *nelem = elems_next +
j;
2494 elems_orig[nelems_orig_merged++] = *oelem;
2504 *nelems_orig = nelems_orig_merged;
#define DatumGetArrayTypeP(X)
void deconstruct_array(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)
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)
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 Datum _bt_find_extreme_element(IndexScanDesc scan, ScanKey skey, Oid elemtype, StrategyNumber strat, Datum *elems, int nelems)
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_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 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)
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)