mirror of
https://github.com/postgres/postgres.git
synced 2025-07-02 09:02:37 +03:00
Since createplan.c no longer cares whether index operators are lossy, it has
no particular need to do get_op_opfamily_properties() while building an indexscan plan. Postpone that lookup until executor start. This simplifies createplan.c a lot more than it complicates nodeIndexscan.c, and makes things more uniform since we already had to do it that way for RowCompare expressions. Should be a bit faster too, at least for plans that aren't re-used many times, since we avoid palloc'ing and perhaps copying the intermediate list data structure.
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/executor/nodeIndexscan.c,v 1.127 2008/04/13 19:18:14 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/executor/nodeIndexscan.c,v 1.128 2008/04/13 20:51:20 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -576,8 +576,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
|
||||
ExecIndexBuildScanKeys((PlanState *) indexstate,
|
||||
indexstate->iss_RelationDesc,
|
||||
node->indexqual,
|
||||
node->indexstrategy,
|
||||
node->indexsubtype,
|
||||
&indexstate->iss_ScanKeys,
|
||||
&indexstate->iss_NumScanKeys,
|
||||
&indexstate->iss_RuntimeKeys,
|
||||
@ -655,12 +653,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
|
||||
* planstate: executor state node we are working for
|
||||
* index: the index we are building scan keys for
|
||||
* quals: indexquals expressions
|
||||
* strategies: associated operator strategy numbers
|
||||
* subtypes: associated operator subtype OIDs
|
||||
*
|
||||
* (Any elements of the strategies and subtypes lists that correspond to
|
||||
* RowCompareExpr quals are not used here; instead we look up the info
|
||||
* afresh.)
|
||||
*
|
||||
* Output params are:
|
||||
*
|
||||
@ -675,15 +667,12 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
|
||||
* ScalarArrayOpExpr quals are not supported.
|
||||
*/
|
||||
void
|
||||
ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
|
||||
List *quals, List *strategies, List *subtypes,
|
||||
ExecIndexBuildScanKeys(PlanState *planstate, Relation index, List *quals,
|
||||
ScanKey *scanKeys, int *numScanKeys,
|
||||
IndexRuntimeKeyInfo **runtimeKeys, int *numRuntimeKeys,
|
||||
IndexArrayKeyInfo **arrayKeys, int *numArrayKeys)
|
||||
{
|
||||
ListCell *qual_cell;
|
||||
ListCell *strategy_cell;
|
||||
ListCell *subtype_cell;
|
||||
ScanKey scan_keys;
|
||||
IndexRuntimeKeyInfo *runtime_keys;
|
||||
IndexArrayKeyInfo *array_keys;
|
||||
@ -725,40 +714,31 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
|
||||
extra_scan_keys = n_scan_keys;
|
||||
|
||||
/*
|
||||
* for each opclause in the given qual, convert each qual's opclause into
|
||||
* for each opclause in the given qual, convert the opclause into
|
||||
* a single scan key
|
||||
*/
|
||||
qual_cell = list_head(quals);
|
||||
strategy_cell = list_head(strategies);
|
||||
subtype_cell = list_head(subtypes);
|
||||
|
||||
for (j = 0; j < n_scan_keys; j++)
|
||||
j = 0;
|
||||
foreach(qual_cell, quals)
|
||||
{
|
||||
ScanKey this_scan_key = &scan_keys[j];
|
||||
Expr *clause; /* one clause of index qual */
|
||||
Expr *clause = (Expr *) lfirst(qual_cell);
|
||||
ScanKey this_scan_key = &scan_keys[j++];
|
||||
Oid opno; /* operator's OID */
|
||||
RegProcedure opfuncid; /* operator proc id used in scan */
|
||||
StrategyNumber strategy; /* op's strategy number */
|
||||
Oid subtype; /* op's strategy subtype */
|
||||
Oid opfamily; /* opfamily of index column */
|
||||
int op_strategy; /* operator's strategy number */
|
||||
Oid op_lefttype; /* operator's declared input types */
|
||||
Oid op_righttype;
|
||||
Expr *leftop; /* expr on lhs of operator */
|
||||
Expr *rightop; /* expr on rhs ... */
|
||||
AttrNumber varattno; /* att number used in scan */
|
||||
|
||||
/*
|
||||
* extract clause information from the qualification
|
||||
*/
|
||||
clause = (Expr *) lfirst(qual_cell);
|
||||
qual_cell = lnext(qual_cell);
|
||||
strategy = lfirst_int(strategy_cell);
|
||||
strategy_cell = lnext(strategy_cell);
|
||||
subtype = lfirst_oid(subtype_cell);
|
||||
subtype_cell = lnext(subtype_cell);
|
||||
|
||||
if (IsA(clause, OpExpr))
|
||||
{
|
||||
/* indexkey op const or indexkey op expression */
|
||||
int flags = 0;
|
||||
Datum scanvalue;
|
||||
|
||||
opno = ((OpExpr *) clause)->opno;
|
||||
opfuncid = ((OpExpr *) clause)->opfuncid;
|
||||
|
||||
/*
|
||||
@ -776,6 +756,19 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
|
||||
elog(ERROR, "indexqual doesn't have key on left side");
|
||||
|
||||
varattno = ((Var *) leftop)->varattno;
|
||||
if (varattno < 1 || varattno > index->rd_index->indnatts)
|
||||
elog(ERROR, "bogus index qualification");
|
||||
|
||||
/*
|
||||
* We have to look up the operator's strategy number. This
|
||||
* provides a cross-check that the operator does match the index.
|
||||
*/
|
||||
opfamily = index->rd_opfamily[varattno - 1];
|
||||
|
||||
get_op_opfamily_properties(opno, opfamily,
|
||||
&op_strategy,
|
||||
&op_lefttype,
|
||||
&op_righttype);
|
||||
|
||||
/*
|
||||
* rightop is the constant or variable comparison value
|
||||
@ -810,8 +803,8 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
|
||||
ScanKeyEntryInitialize(this_scan_key,
|
||||
flags,
|
||||
varattno, /* attribute number to scan */
|
||||
strategy, /* op's strategy */
|
||||
subtype, /* strategy subtype */
|
||||
op_strategy, /* op's strategy */
|
||||
op_righttype, /* strategy subtype */
|
||||
opfuncid, /* reg proc to use */
|
||||
scanvalue); /* constant */
|
||||
}
|
||||
@ -830,12 +823,6 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
|
||||
ScanKey this_sub_key = &scan_keys[extra_scan_keys];
|
||||
int flags = SK_ROW_MEMBER;
|
||||
Datum scanvalue;
|
||||
Oid opno;
|
||||
Oid opfamily;
|
||||
int op_strategy;
|
||||
Oid op_lefttype;
|
||||
Oid op_righttype;
|
||||
bool op_recheck;
|
||||
|
||||
/*
|
||||
* leftop should be the index key Var, possibly relabeled
|
||||
@ -897,8 +884,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
|
||||
get_op_opfamily_properties(opno, opfamily,
|
||||
&op_strategy,
|
||||
&op_lefttype,
|
||||
&op_righttype,
|
||||
&op_recheck);
|
||||
&op_righttype);
|
||||
|
||||
if (op_strategy != rc->rctype)
|
||||
elog(ERROR, "RowCompare index qualification contains wrong operator");
|
||||
@ -941,6 +927,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
|
||||
ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
|
||||
|
||||
Assert(saop->useOr);
|
||||
opno = saop->opno;
|
||||
opfuncid = saop->opfuncid;
|
||||
|
||||
/*
|
||||
@ -958,6 +945,19 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
|
||||
elog(ERROR, "indexqual doesn't have key on left side");
|
||||
|
||||
varattno = ((Var *) leftop)->varattno;
|
||||
if (varattno < 1 || varattno > index->rd_index->indnatts)
|
||||
elog(ERROR, "bogus index qualification");
|
||||
|
||||
/*
|
||||
* We have to look up the operator's strategy number. This
|
||||
* provides a cross-check that the operator does match the index.
|
||||
*/
|
||||
opfamily = index->rd_opfamily[varattno - 1];
|
||||
|
||||
get_op_opfamily_properties(opno, opfamily,
|
||||
&op_strategy,
|
||||
&op_lefttype,
|
||||
&op_righttype);
|
||||
|
||||
/*
|
||||
* rightop is the constant or variable array value
|
||||
@ -981,8 +981,8 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
|
||||
ScanKeyEntryInitialize(this_scan_key,
|
||||
0, /* flags */
|
||||
varattno, /* attribute number to scan */
|
||||
strategy, /* op's strategy */
|
||||
subtype, /* strategy subtype */
|
||||
op_strategy, /* op's strategy */
|
||||
op_righttype, /* strategy subtype */
|
||||
opfuncid, /* reg proc to use */
|
||||
(Datum) 0); /* constant */
|
||||
}
|
||||
@ -1013,8 +1013,8 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
|
||||
ScanKeyEntryInitialize(this_scan_key,
|
||||
SK_ISNULL | SK_SEARCHNULL,
|
||||
varattno, /* attribute number to scan */
|
||||
strategy, /* op's strategy */
|
||||
subtype, /* strategy subtype */
|
||||
InvalidStrategy, /* no strategy */
|
||||
InvalidOid, /* no strategy subtype */
|
||||
InvalidOid, /* no reg proc for this */
|
||||
(Datum) 0); /* constant */
|
||||
}
|
||||
|
Reference in New Issue
Block a user