diff options
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execQual.c | 2 | ||||
-rw-r--r-- | src/backend/executor/execUtils.c | 4 | ||||
-rw-r--r-- | src/backend/executor/nodeBitmapIndexscan.c | 24 | ||||
-rw-r--r-- | src/backend/executor/nodeIndexscan.c | 160 | ||||
-rw-r--r-- | src/backend/executor/nodeMergejoin.c | 2 |
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); |