aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/execQual.c2
-rw-r--r--src/backend/executor/execUtils.c4
-rw-r--r--src/backend/executor/nodeBitmapIndexscan.c24
-rw-r--r--src/backend/executor/nodeIndexscan.c160
-rw-r--r--src/backend/executor/nodeMergejoin.c2
5 files changed, 138 insertions, 54 deletions
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 27ea91c0140..6bac6d06236 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -4694,7 +4694,7 @@ ExecInitExpr(Expr *node, PlanState *parent)
Oid righttype;
Oid proc;
- get_op_opfamily_properties(opno, opfamily,
+ get_op_opfamily_properties(opno, opfamily, false,
&strategy,
&lefttype,
&righttype);
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 57806ca8f0f..6ad0f1e52ad 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -1211,8 +1211,8 @@ check_exclusion_constraint(Relation heap, Relation index, IndexInfo *indexInfo,
retry:
conflict = false;
found_self = false;
- index_scan = index_beginscan(heap, index, &DirtySnapshot,
- index_natts, scankeys);
+ index_scan = index_beginscan(heap, index, &DirtySnapshot, index_natts, 0);
+ index_rescan(index_scan, scankeys, index_natts, NULL, 0);
while ((tup = index_getnext(index_scan,
ForwardScanDirection)) != NULL)
diff --git a/src/backend/executor/nodeBitmapIndexscan.c b/src/backend/executor/nodeBitmapIndexscan.c
index 97ce0dde294..573e294882c 100644
--- a/src/backend/executor/nodeBitmapIndexscan.c
+++ b/src/backend/executor/nodeBitmapIndexscan.c
@@ -95,7 +95,9 @@ MultiExecBitmapIndexScan(BitmapIndexScanState *node)
doscan = ExecIndexAdvanceArrayKeys(node->biss_ArrayKeys,
node->biss_NumArrayKeys);
if (doscan) /* reset index scan */
- index_rescan(node->biss_ScanDesc, node->biss_ScanKeys);
+ index_rescan(node->biss_ScanDesc,
+ node->biss_ScanKeys, node->biss_NumScanKeys,
+ NULL, 0);
}
/* must provide our own instrumentation support */
@@ -147,7 +149,9 @@ ExecReScanBitmapIndexScan(BitmapIndexScanState *node)
/* reset index scan */
if (node->biss_RuntimeKeysReady)
- index_rescan(node->biss_ScanDesc, node->biss_ScanKeys);
+ index_rescan(node->biss_ScanDesc,
+ node->biss_ScanKeys, node->biss_NumScanKeys,
+ NULL, 0);
}
/* ----------------------------------------------------------------
@@ -256,6 +260,8 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
* Initialize index-specific scan state
*/
indexstate->biss_RuntimeKeysReady = false;
+ indexstate->biss_RuntimeKeys = NULL;
+ indexstate->biss_NumRuntimeKeys = 0;
/*
* build the index scan keys from the index qualification
@@ -264,6 +270,7 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
indexstate->biss_RelationDesc,
node->scan.scanrelid,
node->indexqual,
+ false,
&indexstate->biss_ScanKeys,
&indexstate->biss_NumScanKeys,
&indexstate->biss_RuntimeKeys,
@@ -297,8 +304,17 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
indexstate->biss_ScanDesc =
index_beginscan_bitmap(indexstate->biss_RelationDesc,
estate->es_snapshot,
- indexstate->biss_NumScanKeys,
- indexstate->biss_ScanKeys);
+ indexstate->biss_NumScanKeys);
+
+ /*
+ * If no run-time keys to calculate, go ahead and pass the scankeys to
+ * the index AM.
+ */
+ if (indexstate->biss_NumRuntimeKeys == 0 &&
+ indexstate->biss_NumArrayKeys == 0)
+ index_rescan(indexstate->biss_ScanDesc,
+ indexstate->biss_ScanKeys, indexstate->biss_NumScanKeys,
+ NULL, 0);
/*
* all done.
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index ee5fc72c209..3aed2960d3f 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -181,7 +181,9 @@ ExecReScanIndexScan(IndexScanState *node)
node->iss_RuntimeKeysReady = true;
/* reset index scan */
- index_rescan(node->iss_ScanDesc, node->iss_ScanKeys);
+ index_rescan(node->iss_ScanDesc,
+ node->iss_ScanKeys, node->iss_NumScanKeys,
+ node->iss_OrderByKeys, node->iss_NumOrderByKeys);
ExecScanReScan(&node->ss);
}
@@ -480,10 +482,11 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
* initialize child expressions
*
* Note: we don't initialize all of the indexqual expression, only the
- * sub-parts corresponding to runtime keys (see below). The indexqualorig
- * expression is always initialized even though it will only be used in
- * some uncommon cases --- would be nice to improve that. (Problem is
- * that any SubPlans present in the expression must be found now...)
+ * sub-parts corresponding to runtime keys (see below). Likewise for
+ * indexorderby, if any. But the indexqualorig expression is always
+ * initialized even though it will only be used in some uncommon cases ---
+ * would be nice to improve that. (Problem is that any SubPlans present
+ * in the expression must be found now...)
*/
indexstate->ss.ps.targetlist = (List *)
ExecInitExpr((Expr *) node->scan.plan.targetlist,
@@ -543,6 +546,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
* Initialize index-specific scan state
*/
indexstate->iss_RuntimeKeysReady = false;
+ indexstate->iss_RuntimeKeys = NULL;
+ indexstate->iss_NumRuntimeKeys = 0;
/*
* build the index scan keys from the index qualification
@@ -551,6 +556,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
indexstate->iss_RelationDesc,
node->scan.scanrelid,
node->indexqual,
+ false,
&indexstate->iss_ScanKeys,
&indexstate->iss_NumScanKeys,
&indexstate->iss_RuntimeKeys,
@@ -559,6 +565,21 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
NULL);
/*
+ * any ORDER BY exprs have to be turned into scankeys in the same way
+ */
+ ExecIndexBuildScanKeys((PlanState *) indexstate,
+ indexstate->iss_RelationDesc,
+ node->scan.scanrelid,
+ node->indexorderby,
+ true,
+ &indexstate->iss_OrderByKeys,
+ &indexstate->iss_NumOrderByKeys,
+ &indexstate->iss_RuntimeKeys,
+ &indexstate->iss_NumRuntimeKeys,
+ NULL, /* no ArrayKeys */
+ NULL);
+
+ /*
* If we have runtime keys, we need an ExprContext to evaluate them. The
* node's standard context won't do because we want to reset that context
* for every tuple. So, build another context just like the other one...
@@ -584,7 +605,16 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
indexstate->iss_RelationDesc,
estate->es_snapshot,
indexstate->iss_NumScanKeys,
- indexstate->iss_ScanKeys);
+ indexstate->iss_NumOrderByKeys);
+
+ /*
+ * If no run-time keys to calculate, go ahead and pass the scankeys to
+ * the index AM.
+ */
+ if (indexstate->iss_NumRuntimeKeys == 0)
+ index_rescan(indexstate->iss_ScanDesc,
+ indexstate->iss_ScanKeys, indexstate->iss_NumScanKeys,
+ indexstate->iss_OrderByKeys, indexstate->iss_NumOrderByKeys);
/*
* all done.
@@ -624,12 +654,20 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
* 5. NullTest ("indexkey IS NULL/IS NOT NULL"). We just fill in the
* ScanKey properly.
*
+ * This code is also used to prepare ORDER BY expressions for amcanorderbyop
+ * indexes. The behavior is exactly the same, except that we have to look up
+ * the operator differently. Note that only cases 1 and 2 are currently
+ * possible for ORDER BY.
+ *
* Input params are:
*
* planstate: executor state node we are working for
* index: the index we are building scan keys for
* scanrelid: varno of the index's relation within current query
- * quals: indexquals expressions
+ * quals: indexquals (or indexorderbys) expressions
+ * isorderby: true if processing ORDER BY exprs, false if processing quals
+ * *runtimeKeys: ptr to pre-existing IndexRuntimeKeyInfos, or NULL if none
+ * *numRuntimeKeys: number of pre-existing runtime keys
*
* Output params are:
*
@@ -645,7 +683,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
*/
void
ExecIndexBuildScanKeys(PlanState *planstate, Relation index, Index scanrelid,
- List *quals, ScanKey *scanKeys, int *numScanKeys,
+ List *quals, bool isorderby,
+ ScanKey *scanKeys, int *numScanKeys,
IndexRuntimeKeyInfo **runtimeKeys, int *numRuntimeKeys,
IndexArrayKeyInfo **arrayKeys, int *numArrayKeys)
{
@@ -654,43 +693,31 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index, Index scanrelid,
IndexRuntimeKeyInfo *runtime_keys;
IndexArrayKeyInfo *array_keys;
int n_scan_keys;
- int extra_scan_keys;
int n_runtime_keys;
+ int max_runtime_keys;
int n_array_keys;
int j;
+ /* Allocate array for ScanKey structs: one per qual */
+ n_scan_keys = list_length(quals);
+ scan_keys = (ScanKey) palloc(n_scan_keys * sizeof(ScanKeyData));
+
/*
- * If there are any RowCompareExpr quals, we need extra ScanKey entries
- * for them, and possibly extra runtime-key entries. Count up what's
- * needed. (The subsidiary ScanKey arrays for the RowCompareExprs could
- * be allocated as separate chunks, but we have to count anyway to make
- * runtime_keys large enough, so might as well just do one palloc.)
+ * runtime_keys array is dynamically resized as needed. We handle it
+ * this way so that the same runtime keys array can be shared between
+ * indexquals and indexorderbys, which will be processed in separate
+ * calls of this function. Caller must be sure to pass in NULL/0 for
+ * first call.
*/
- n_scan_keys = list_length(quals);
- extra_scan_keys = 0;
- foreach(qual_cell, quals)
- {
- if (IsA(lfirst(qual_cell), RowCompareExpr))
- extra_scan_keys +=
- list_length(((RowCompareExpr *) lfirst(qual_cell))->opnos);
- }
- scan_keys = (ScanKey)
- palloc((n_scan_keys + extra_scan_keys) * sizeof(ScanKeyData));
- /* Allocate these arrays as large as they could possibly need to be */
- runtime_keys = (IndexRuntimeKeyInfo *)
- palloc((n_scan_keys + extra_scan_keys) * sizeof(IndexRuntimeKeyInfo));
+ runtime_keys = *runtimeKeys;
+ n_runtime_keys = max_runtime_keys = *numRuntimeKeys;
+
+ /* Allocate array_keys as large as it could possibly need to be */
array_keys = (IndexArrayKeyInfo *)
palloc0(n_scan_keys * sizeof(IndexArrayKeyInfo));
- n_runtime_keys = 0;
n_array_keys = 0;
/*
- * Below here, extra_scan_keys is index of first cell to use for next
- * RowCompareExpr
- */
- extra_scan_keys = n_scan_keys;
-
- /*
* for each opclause in the given qual, convert the opclause into a single
* scan key
*/
@@ -742,11 +769,14 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index, Index scanrelid,
*/
opfamily = index->rd_opfamily[varattno - 1];
- get_op_opfamily_properties(opno, opfamily,
+ get_op_opfamily_properties(opno, opfamily, isorderby,
&op_strategy,
&op_lefttype,
&op_righttype);
+ if (isorderby)
+ flags |= SK_ORDER_BY;
+
/*
* rightop is the constant or variable comparison value
*/
@@ -767,6 +797,21 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index, Index scanrelid,
else
{
/* Need to treat this one as a runtime key */
+ if (n_runtime_keys >= max_runtime_keys)
+ {
+ if (max_runtime_keys == 0)
+ {
+ max_runtime_keys = 8;
+ runtime_keys = (IndexRuntimeKeyInfo *)
+ palloc(max_runtime_keys * sizeof(IndexRuntimeKeyInfo));
+ }
+ else
+ {
+ max_runtime_keys *= 2;
+ runtime_keys = (IndexRuntimeKeyInfo *)
+ repalloc(runtime_keys, max_runtime_keys * sizeof(IndexRuntimeKeyInfo));
+ }
+ }
runtime_keys[n_runtime_keys].scan_key = this_scan_key;
runtime_keys[n_runtime_keys].key_expr =
ExecInitExpr(rightop, planstate);
@@ -794,12 +839,19 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index, Index scanrelid,
ListCell *largs_cell = list_head(rc->largs);
ListCell *rargs_cell = list_head(rc->rargs);
ListCell *opnos_cell = list_head(rc->opnos);
- ScanKey first_sub_key = &scan_keys[extra_scan_keys];
+ ScanKey first_sub_key;
+ int n_sub_key;
+
+ Assert(!isorderby);
+
+ first_sub_key = (ScanKey)
+ palloc(list_length(rc->opnos) * sizeof(ScanKeyData));
+ n_sub_key = 0;
/* Scan RowCompare columns and generate subsidiary ScanKey items */
while (opnos_cell != NULL)
{
- ScanKey this_sub_key = &scan_keys[extra_scan_keys];
+ ScanKey this_sub_key = &first_sub_key[n_sub_key];
int flags = SK_ROW_MEMBER;
Datum scanvalue;
@@ -832,7 +884,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index, Index scanrelid,
elog(ERROR, "bogus RowCompare index qualification");
opfamily = index->rd_opfamily[varattno - 1];
- get_op_opfamily_properties(opno, opfamily,
+ get_op_opfamily_properties(opno, opfamily, isorderby,
&op_strategy,
&op_lefttype,
&op_righttype);
@@ -866,6 +918,21 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index, Index scanrelid,
else
{
/* Need to treat this one as a runtime key */
+ if (n_runtime_keys >= max_runtime_keys)
+ {
+ if (max_runtime_keys == 0)
+ {
+ max_runtime_keys = 8;
+ runtime_keys = (IndexRuntimeKeyInfo *)
+ palloc(max_runtime_keys * sizeof(IndexRuntimeKeyInfo));
+ }
+ else
+ {
+ max_runtime_keys *= 2;
+ runtime_keys = (IndexRuntimeKeyInfo *)
+ repalloc(runtime_keys, max_runtime_keys * sizeof(IndexRuntimeKeyInfo));
+ }
+ }
runtime_keys[n_runtime_keys].scan_key = this_sub_key;
runtime_keys[n_runtime_keys].key_expr =
ExecInitExpr(rightop, planstate);
@@ -885,11 +952,11 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index, Index scanrelid,
op_righttype, /* strategy subtype */
opfuncid, /* reg proc to use */
scanvalue); /* constant */
- extra_scan_keys++;
+ n_sub_key++;
}
/* Mark the last subsidiary scankey correctly */
- scan_keys[extra_scan_keys - 1].sk_flags |= SK_ROW_END;
+ first_sub_key[n_sub_key - 1].sk_flags |= SK_ROW_END;
/*
* We don't use ScanKeyEntryInitialize for the header because it
@@ -907,6 +974,8 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index, Index scanrelid,
/* indexkey op ANY (array-expression) */
ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
+ Assert(!isorderby);
+
Assert(saop->useOr);
opno = saop->opno;
opfuncid = saop->opfuncid;
@@ -935,7 +1004,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index, Index scanrelid,
*/
opfamily = index->rd_opfamily[varattno - 1];
- get_op_opfamily_properties(opno, opfamily,
+ get_op_opfamily_properties(opno, opfamily, isorderby,
&op_strategy,
&op_lefttype,
&op_righttype);
@@ -973,6 +1042,8 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index, Index scanrelid,
NullTest *ntest = (NullTest *) clause;
int flags;
+ Assert(!isorderby);
+
/*
* argument should be the index key Var, possibly relabeled
*/
@@ -1020,12 +1091,9 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index, Index scanrelid,
(int) nodeTag(clause));
}
+ Assert(n_runtime_keys <= max_runtime_keys);
+
/* Get rid of any unused arrays */
- if (n_runtime_keys == 0)
- {
- pfree(runtime_keys);
- runtime_keys = NULL;
- }
if (n_array_keys == 0)
{
pfree(array_keys);
diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c
index e8ce5bc02b3..98d1615514b 100644
--- a/src/backend/executor/nodeMergejoin.c
+++ b/src/backend/executor/nodeMergejoin.c
@@ -201,7 +201,7 @@ MJExamineQuals(List *mergeclauses,
clause->rexpr = ExecInitExpr((Expr *) lsecond(qual->args), parent);
/* Extract the operator's declared left/right datatypes */
- get_op_opfamily_properties(qual->opno, opfamily,
+ get_op_opfamily_properties(qual->opno, opfamily, false,
&op_strategy,
&op_lefttype,
&op_righttype);