Commit 8fd3fdd8 authored by Tom Lane's avatar Tom Lane

Simplify the planner's new representation of indexable clauses a little.

In commit 1a8d5afb, 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 in
1a8d5afb.  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
parent 86eea786
...@@ -2435,7 +2435,7 @@ match_clause_to_indexcol(PlannerInfo *root, ...@@ -2435,7 +2435,7 @@ match_clause_to_indexcol(PlannerInfo *root,
{ {
iclause = makeNode(IndexClause); iclause = makeNode(IndexClause);
iclause->rinfo = rinfo; iclause->rinfo = rinfo;
iclause->indexquals = NIL; iclause->indexquals = list_make1(rinfo);
iclause->lossy = false; iclause->lossy = false;
iclause->indexcol = indexcol; iclause->indexcol = indexcol;
iclause->indexcols = NIL; iclause->indexcols = NIL;
...@@ -2599,7 +2599,7 @@ match_opclause_to_indexcol(PlannerInfo *root, ...@@ -2599,7 +2599,7 @@ match_opclause_to_indexcol(PlannerInfo *root,
{ {
iclause = makeNode(IndexClause); iclause = makeNode(IndexClause);
iclause->rinfo = rinfo; iclause->rinfo = rinfo;
iclause->indexquals = NIL; iclause->indexquals = list_make1(rinfo);
iclause->lossy = false; iclause->lossy = false;
iclause->indexcol = indexcol; iclause->indexcol = indexcol;
iclause->indexcols = NIL; iclause->indexcols = NIL;
...@@ -2819,7 +2819,7 @@ match_saopclause_to_indexcol(RestrictInfo *rinfo, ...@@ -2819,7 +2819,7 @@ match_saopclause_to_indexcol(RestrictInfo *rinfo,
IndexClause *iclause = makeNode(IndexClause); IndexClause *iclause = makeNode(IndexClause);
iclause->rinfo = rinfo; iclause->rinfo = rinfo;
iclause->indexquals = NIL; iclause->indexquals = list_make1(rinfo);
iclause->lossy = false; iclause->lossy = false;
iclause->indexcol = indexcol; iclause->indexcol = indexcol;
iclause->indexcols = NIL; iclause->indexcols = NIL;
...@@ -3078,7 +3078,7 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo, ...@@ -3078,7 +3078,7 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo,
* usable as index quals. * usable as index quals.
*/ */
if (var_on_left && !iclause->lossy) if (var_on_left && !iclause->lossy)
iclause->indexquals = NIL; iclause->indexquals = list_make1(rinfo);
else else
{ {
/* /*
......
...@@ -3075,11 +3075,8 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual, ...@@ -3075,11 +3075,8 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
Assert(!rinfo->pseudoconstant); Assert(!rinfo->pseudoconstant);
subquals = lappend(subquals, rinfo->clause); subquals = lappend(subquals, rinfo->clause);
if (iclause->indexquals) subindexquals = list_concat(subindexquals,
subindexquals = list_concat(subindexquals, get_actual_clauses(iclause->indexquals));
get_actual_clauses(iclause->indexquals));
else
subindexquals = lappend(subindexquals, rinfo->clause);
if (rinfo->parent_ec) if (rinfo->parent_ec)
subindexECs = lappend(subindexECs, rinfo->parent_ec); subindexECs = lappend(subindexECs, rinfo->parent_ec);
} }
...@@ -4491,33 +4488,18 @@ fix_indexqual_references(PlannerInfo *root, IndexPath *index_path, ...@@ -4491,33 +4488,18 @@ fix_indexqual_references(PlannerInfo *root, IndexPath *index_path,
{ {
IndexClause *iclause = lfirst_node(IndexClause, lc); IndexClause *iclause = lfirst_node(IndexClause, lc);
int indexcol = iclause->indexcol; int indexcol = iclause->indexcol;
ListCell *lc2;
if (iclause->indexquals == NIL) foreach(lc2, iclause->indexquals)
{ {
/* rinfo->clause is directly usable as an indexqual */ RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc2);
Node *clause = (Node *) iclause->rinfo->clause; Node *clause = (Node *) rinfo->clause;
stripped_indexquals = lappend(stripped_indexquals, clause); stripped_indexquals = lappend(stripped_indexquals, clause);
clause = fix_indexqual_clause(root, index, indexcol, clause = fix_indexqual_clause(root, index, indexcol,
clause, iclause->indexcols); clause, iclause->indexcols);
fixed_indexquals = lappend(fixed_indexquals, clause); fixed_indexquals = lappend(fixed_indexquals, clause);
} }
else
{
/* Process the derived indexquals */
ListCell *lc2;
foreach(lc2, iclause->indexquals)
{
RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc2);
Node *clause = (Node *) rinfo->clause;
stripped_indexquals = lappend(stripped_indexquals, clause);
clause = fix_indexqual_clause(root, index, indexcol,
clause, iclause->indexcols);
fixed_indexquals = lappend(fixed_indexquals, clause);
}
}
} }
*stripped_indexquals_p = stripped_indexquals; *stripped_indexquals_p = stripped_indexquals;
......
...@@ -197,8 +197,6 @@ static bool get_actual_variable_range(PlannerInfo *root, ...@@ -197,8 +197,6 @@ static bool get_actual_variable_range(PlannerInfo *root,
Oid sortop, Oid sortop,
Datum *min, Datum *max); Datum *min, Datum *max);
static RelOptInfo *find_join_input_rel(PlannerInfo *root, Relids relids); 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); static List *add_predicate_to_quals(IndexOptInfo *index, List *indexQuals);
...@@ -5263,16 +5261,13 @@ get_index_quals(List *indexclauses) ...@@ -5263,16 +5261,13 @@ get_index_quals(List *indexclauses)
foreach(lc, indexclauses) foreach(lc, indexclauses)
{ {
IndexClause *iclause = lfirst_node(IndexClause, lc); IndexClause *iclause = lfirst_node(IndexClause, lc);
ListCell *lc2;
if (iclause->indexquals == NIL) foreach(lc2, iclause->indexquals)
{ {
/* rinfo->clause is directly usable as an indexqual */ RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc2);
result = lappend(result, iclause->rinfo);
} result = lappend(result, rinfo);
else
{
/* report the derived indexquals */
result = list_concat(result, list_copy(iclause->indexquals));
} }
} }
return result; return result;
...@@ -5282,83 +5277,58 @@ List * ...@@ -5282,83 +5277,58 @@ List *
deconstruct_indexquals(IndexPath *path) deconstruct_indexquals(IndexPath *path)
{ {
List *result = NIL; List *result = NIL;
IndexOptInfo *index = path->indexinfo;
ListCell *lc; ListCell *lc;
foreach(lc, path->indexclauses) foreach(lc, path->indexclauses)
{ {
IndexClause *iclause = lfirst_node(IndexClause, lc); IndexClause *iclause = lfirst_node(IndexClause, lc);
int indexcol = iclause->indexcol; 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 */ RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc2);
ListCell *lc2; Expr *clause = rinfo->clause;
IndexQualInfo *qinfo;
foreach(lc2, iclause->indexquals) qinfo = (IndexQualInfo *) palloc(sizeof(IndexQualInfo));
{ qinfo->rinfo = rinfo;
RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc2); qinfo->indexcol = indexcol;
qinfo = deconstruct_indexqual(rinfo, index, indexcol); if (IsA(clause, OpExpr))
result = lappend(result, qinfo); {
qinfo->clause_op = ((OpExpr *) clause)->opno;
qinfo->other_operand = get_rightop(clause);
} }
} else if (IsA(clause, RowCompareExpr))
} {
return result; RowCompareExpr *rc = (RowCompareExpr *) clause;
}
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 = linitial_oid(rc->opnos);
{ qinfo->other_operand = (Node *) rc->rargs;
qinfo->clause_op = ((OpExpr *) clause)->opno; }
qinfo->other_operand = get_rightop(clause); else if (IsA(clause, ScalarArrayOpExpr))
} {
else if (IsA(clause, RowCompareExpr)) ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
{
RowCompareExpr *rc = (RowCompareExpr *) clause;
qinfo->clause_op = linitial_oid(rc->opnos); qinfo->clause_op = saop->opno;
qinfo->other_operand = (Node *) rc->rargs; qinfo->other_operand = (Node *) lsecond(saop->args);
} }
else if (IsA(clause, ScalarArrayOpExpr)) else if (IsA(clause, NullTest))
{ {
ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause; qinfo->clause_op = InvalidOid;
qinfo->other_operand = NULL;
}
else
{
elog(ERROR, "unsupported indexqual type: %d",
(int) nodeTag(clause));
}
qinfo->clause_op = saop->opno; result = lappend(result, qinfo);
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;
} }
return result;
} }
/* /*
......
...@@ -1185,26 +1185,20 @@ typedef struct IndexPath ...@@ -1185,26 +1185,20 @@ typedef struct IndexPath
* conditions is done by a planner support function attached to the * conditions is done by a planner support function attached to the
* indexclause's top-level function or operator. * indexclause's top-level function or operator.
* *
* If indexquals is NIL, it means that rinfo->clause is directly usable as * indexquals is a list of RestrictInfos for the directly-usable index
* an indexqual. Otherwise indexquals contains one or more directly-usable * conditions associated with this IndexClause. In the simplest case
* indexqual conditions extracted from the given clause. The 'lossy' flag * it's a one-element list whose member is iclause->rinfo. Otherwise,
* indicates whether the indexquals are semantically equivalent to the * it contains one or more directly-usable indexqual conditions extracted
* original clause, or form a weaker condition. * from the given clause. The 'lossy' flag indicates whether the
* * indexquals are semantically equivalent to the original clause, or
* Currently, entries in indexquals are RestrictInfos, but they could perhaps * represent a weaker condition.
* be bare clauses instead; the only advantage of making them RestrictInfos
* is the possibility of caching cost and selectivity information across
* multiple uses, and it's not clear that that's really worth the price of
* constructing RestrictInfos for them. Note however that the extended-stats
* machinery won't do anything with non-RestrictInfo clauses, so that would
* have to be fixed.
* *
* Normally, indexcol is the index of the single index column the clause * Normally, indexcol is the index of the single index column the clause
* works on, and indexcols is NIL. But if the clause is a RowCompareExpr, * works on, and indexcols is NIL. But if the clause is a RowCompareExpr,
* indexcol is the index of the leading column, and indexcols is a list of * indexcol is the index of the leading column, and indexcols is a list of
* all the affected columns. (Note that indexcols matches up with the * all the affected columns. (Note that indexcols matches up with the
* columns of the actual indexable RowCompareExpr, which might be in * columns of the actual indexable RowCompareExpr in indexquals, which
* indexquals rather than rinfo.) * might be different from the original in rinfo.)
* *
* An IndexPath's IndexClause list is required to be ordered by index * An IndexPath's IndexClause list is required to be ordered by index
* column, i.e. the indexcol values must form a nondecreasing sequence. * column, i.e. the indexcol values must form a nondecreasing sequence.
...@@ -1214,7 +1208,7 @@ typedef struct IndexClause ...@@ -1214,7 +1208,7 @@ typedef struct IndexClause
{ {
NodeTag type; NodeTag type;
struct RestrictInfo *rinfo; /* original restriction or join clause */ struct RestrictInfo *rinfo; /* original restriction or join clause */
List *indexquals; /* indexqual(s) derived from it, or NIL */ List *indexquals; /* indexqual(s) derived from it */
bool lossy; /* are indexquals a lossy version of clause? */ bool lossy; /* are indexquals a lossy version of clause? */
AttrNumber indexcol; /* index column the clause uses (zero-based) */ AttrNumber indexcol; /* index column the clause uses (zero-based) */
List *indexcols; /* multiple index columns, if RowCompare */ List *indexcols; /* multiple index columns, if RowCompare */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment