mirror of
https://github.com/postgres/postgres.git
synced 2025-07-02 09:02:37 +03:00
Simplify the planner's new representation of indexable clauses a little.
In commit1a8d5afb0
, I thought it'd be a good idea to define IndexClause.indexquals as NIL in the most common case where the given clause (IndexClause.rinfo) is usable exactly as-is. It'd be more consistent to define the indexquals in that case as being a one-element list containing IndexClause.rinfo, but I thought saving the palloc overhead for making such a list would be worthwhile. In hindsight, that was a great example of "premature optimization is the root of all evil": it's complicated everyplace that needs to deal with the indexquals, requiring duplicative code to handle both the simple case and the not-simple case. I'd initially found that tolerable but it's getting less so as I mop up some areas that I'd not touched in1a8d5afb0
. In any case, two more pallocs during a planner run are surely at the noise level (a conclusion confirmed by a bit of microbenchmarking). So let's change this decision before it becomes set in stone, and insist that IndexClause.indexquals always be a valid list of the actual index quals for the clause. Discussion: https://postgr.es/m/24586.1550106354@sss.pgh.pa.us
This commit is contained in:
@ -197,8 +197,6 @@ static bool get_actual_variable_range(PlannerInfo *root,
|
||||
Oid sortop,
|
||||
Datum *min, Datum *max);
|
||||
static RelOptInfo *find_join_input_rel(PlannerInfo *root, Relids relids);
|
||||
static IndexQualInfo *deconstruct_indexqual(RestrictInfo *rinfo,
|
||||
IndexOptInfo *index, int indexcol);
|
||||
static List *add_predicate_to_quals(IndexOptInfo *index, List *indexQuals);
|
||||
|
||||
|
||||
@ -5263,16 +5261,13 @@ get_index_quals(List *indexclauses)
|
||||
foreach(lc, indexclauses)
|
||||
{
|
||||
IndexClause *iclause = lfirst_node(IndexClause, lc);
|
||||
ListCell *lc2;
|
||||
|
||||
if (iclause->indexquals == NIL)
|
||||
foreach(lc2, iclause->indexquals)
|
||||
{
|
||||
/* rinfo->clause is directly usable as an indexqual */
|
||||
result = lappend(result, iclause->rinfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* report the derived indexquals */
|
||||
result = list_concat(result, list_copy(iclause->indexquals));
|
||||
RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc2);
|
||||
|
||||
result = lappend(result, rinfo);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@ -5282,85 +5277,60 @@ List *
|
||||
deconstruct_indexquals(IndexPath *path)
|
||||
{
|
||||
List *result = NIL;
|
||||
IndexOptInfo *index = path->indexinfo;
|
||||
ListCell *lc;
|
||||
|
||||
foreach(lc, path->indexclauses)
|
||||
{
|
||||
IndexClause *iclause = lfirst_node(IndexClause, lc);
|
||||
int indexcol = iclause->indexcol;
|
||||
IndexQualInfo *qinfo;
|
||||
ListCell *lc2;
|
||||
|
||||
if (iclause->indexquals == NIL)
|
||||
foreach(lc2, iclause->indexquals)
|
||||
{
|
||||
/* rinfo->clause is directly usable as an indexqual */
|
||||
qinfo = deconstruct_indexqual(iclause->rinfo, index, indexcol);
|
||||
result = lappend(result, qinfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Process the derived indexquals */
|
||||
ListCell *lc2;
|
||||
RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc2);
|
||||
Expr *clause = rinfo->clause;
|
||||
IndexQualInfo *qinfo;
|
||||
|
||||
foreach(lc2, iclause->indexquals)
|
||||
qinfo = (IndexQualInfo *) palloc(sizeof(IndexQualInfo));
|
||||
qinfo->rinfo = rinfo;
|
||||
qinfo->indexcol = indexcol;
|
||||
|
||||
if (IsA(clause, OpExpr))
|
||||
{
|
||||
RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc2);
|
||||
|
||||
qinfo = deconstruct_indexqual(rinfo, index, indexcol);
|
||||
result = lappend(result, qinfo);
|
||||
qinfo->clause_op = ((OpExpr *) clause)->opno;
|
||||
qinfo->other_operand = get_rightop(clause);
|
||||
}
|
||||
else if (IsA(clause, RowCompareExpr))
|
||||
{
|
||||
RowCompareExpr *rc = (RowCompareExpr *) clause;
|
||||
|
||||
qinfo->clause_op = linitial_oid(rc->opnos);
|
||||
qinfo->other_operand = (Node *) rc->rargs;
|
||||
}
|
||||
else if (IsA(clause, ScalarArrayOpExpr))
|
||||
{
|
||||
ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
|
||||
|
||||
qinfo->clause_op = saop->opno;
|
||||
qinfo->other_operand = (Node *) lsecond(saop->args);
|
||||
}
|
||||
else if (IsA(clause, NullTest))
|
||||
{
|
||||
qinfo->clause_op = InvalidOid;
|
||||
qinfo->other_operand = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
elog(ERROR, "unsupported indexqual type: %d",
|
||||
(int) nodeTag(clause));
|
||||
}
|
||||
|
||||
result = lappend(result, qinfo);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static IndexQualInfo *
|
||||
deconstruct_indexqual(RestrictInfo *rinfo, IndexOptInfo *index, int indexcol)
|
||||
{
|
||||
{
|
||||
Expr *clause;
|
||||
IndexQualInfo *qinfo;
|
||||
|
||||
clause = rinfo->clause;
|
||||
|
||||
qinfo = (IndexQualInfo *) palloc(sizeof(IndexQualInfo));
|
||||
qinfo->rinfo = rinfo;
|
||||
qinfo->indexcol = indexcol;
|
||||
|
||||
if (IsA(clause, OpExpr))
|
||||
{
|
||||
qinfo->clause_op = ((OpExpr *) clause)->opno;
|
||||
qinfo->other_operand = get_rightop(clause);
|
||||
}
|
||||
else if (IsA(clause, RowCompareExpr))
|
||||
{
|
||||
RowCompareExpr *rc = (RowCompareExpr *) clause;
|
||||
|
||||
qinfo->clause_op = linitial_oid(rc->opnos);
|
||||
qinfo->other_operand = (Node *) rc->rargs;
|
||||
}
|
||||
else if (IsA(clause, ScalarArrayOpExpr))
|
||||
{
|
||||
ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
|
||||
|
||||
qinfo->clause_op = saop->opno;
|
||||
qinfo->other_operand = (Node *) lsecond(saop->args);
|
||||
}
|
||||
else if (IsA(clause, NullTest))
|
||||
{
|
||||
qinfo->clause_op = InvalidOid;
|
||||
qinfo->other_operand = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
elog(ERROR, "unsupported indexqual type: %d",
|
||||
(int) nodeTag(clause));
|
||||
}
|
||||
|
||||
return qinfo;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple function to compute the total eval cost of the "other operands"
|
||||
* in an IndexQualInfo list. Since we know these will be evaluated just
|
||||
|
Reference in New Issue
Block a user