Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fa559a8

Browse files
committed
Adjust indexscan planning logic to keep RestrictInfo nodes associated
with index qual clauses in the Path representation. This saves a little work during createplan and (probably more importantly) allows reuse of cached selectivity estimates during indexscan planning. Also fix latent bug: wrong plan would have been generated for a 'special operator' used in a nestloop-inner-indexscan join qual, because the special operator would not have gotten into the list of quals to recheck. This bug is only latent because at present the special-operator code could never trigger on a join qual, but sooner or later someone will want to do it.
1 parent 5d472f6 commit fa559a8

File tree

11 files changed

+400
-188
lines changed

11 files changed

+400
-188
lines changed

src/backend/nodes/outfuncs.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.227 2004/01/05 18:04:38 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.228 2004/01/05 23:39:53 tgl Exp $
1212
*
1313
* NOTES
1414
* Every node type that can appear in stored rules' parsetrees *must*
@@ -968,8 +968,9 @@ _outIndexPath(StringInfo str, IndexPath *node)
968968
_outPathInfo(str, (Path *) node);
969969

970970
WRITE_NODE_FIELD(indexinfo);
971-
WRITE_NODE_FIELD(indexqual);
972-
WRITE_NODE_FIELD(indexjoinclauses);
971+
WRITE_NODE_FIELD(indexclauses);
972+
WRITE_NODE_FIELD(indexquals);
973+
WRITE_BOOL_FIELD(isjoininner);
973974
WRITE_ENUM_FIELD(indexscandir, ScanDirection);
974975
WRITE_FLOAT_FIELD(rows, "%.0f");
975976
}

src/backend/optimizer/path/costsize.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
* Portions Copyright (c) 1994, Regents of the University of California
5050
*
5151
* IDENTIFICATION
52-
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.120 2004/01/05 05:07:35 tgl Exp $
52+
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.121 2004/01/05 23:39:54 tgl Exp $
5353
*
5454
*-------------------------------------------------------------------------
5555
*/
@@ -238,6 +238,9 @@ cost_nonsequential_access(double relpages)
238238
* Any additional quals evaluated as qpquals may reduce the number of returned
239239
* tuples, but they won't reduce the number of tuples we have to fetch from
240240
* the table, so they don't reduce the scan cost.
241+
*
242+
* NOTE: as of 7.5, indexQuals is a list of RestrictInfo nodes, where formerly
243+
* it was a list of bare clause expressions.
241244
*/
242245
void
243246
cost_index(Path *path, Query *root,

src/backend/optimizer/path/indxpath.c

Lines changed: 77 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.154 2004/01/05 05:07:35 tgl Exp $
12+
* $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.155 2004/01/05 23:39:54 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -76,7 +76,7 @@ static bool match_index_to_operand(Node *operand, int indexcol,
7676
RelOptInfo *rel, IndexOptInfo *index);
7777
static bool match_special_index_operator(Expr *clause, Oid opclass,
7878
bool indexkey_on_left);
79-
static List *expand_indexqual_condition(Expr *clause, Oid opclass);
79+
static List *expand_indexqual_condition(RestrictInfo *rinfo, Oid opclass);
8080
static List *prefix_quals(Node *leftop, Oid opclass,
8181
Const *prefix, Pattern_Prefix_Status pstatus);
8282
static List *network_prefix_quals(Node *leftop, Oid expr_op, Oid opclass,
@@ -1418,8 +1418,7 @@ make_innerjoin_index_path(Query *root,
14181418
{
14191419
IndexPath *pathnode = makeNode(IndexPath);
14201420
List *indexquals,
1421-
*allclauses,
1422-
*l;
1421+
*allclauses;
14231422

14241423
/* XXX perhaps this code should be merged with create_index_path? */
14251424

@@ -1433,28 +1432,21 @@ make_innerjoin_index_path(Query *root,
14331432
*/
14341433
pathnode->path.pathkeys = NIL;
14351434

1436-
/* Convert RestrictInfo nodes to indexquals the executor can handle */
1435+
/* Convert clauses to indexquals the executor can handle */
14371436
indexquals = expand_indexqual_conditions(index, clausegroups);
14381437

1439-
/*
1440-
* Also make a flattened list of the RestrictInfo nodes; createplan.c
1441-
* will need this later. We assume here that we can destructively
1442-
* modify the passed-in clausegroups list structure.
1443-
*/
1444-
allclauses = NIL;
1445-
foreach(l, clausegroups)
1446-
{
1447-
/* nconc okay here since same clause couldn't be in two sublists */
1448-
allclauses = nconc(allclauses, (List *) lfirst(l));
1449-
}
1438+
/* Flatten the clausegroups list to produce indexclauses list */
1439+
allclauses = flatten_clausegroups_list(clausegroups);
14501440

14511441
/*
14521442
* Note that we are making a pathnode for a single-scan indexscan;
1453-
* therefore, indexinfo and indexqual should be single-element lists.
1443+
* therefore, indexinfo etc should be single-element lists.
14541444
*/
14551445
pathnode->indexinfo = makeList1(index);
1456-
pathnode->indexqual = makeList1(indexquals);
1457-
pathnode->indexjoinclauses = makeList1(allclauses);
1446+
pathnode->indexclauses = makeList1(allclauses);
1447+
pathnode->indexquals = makeList1(indexquals);
1448+
1449+
pathnode->isjoininner = true;
14581450

14591451
/* We don't actually care what order the index scans in ... */
14601452
pathnode->indexscandir = NoMovementScanDirection;
@@ -1489,6 +1481,61 @@ make_innerjoin_index_path(Query *root,
14891481
return (Path *) pathnode;
14901482
}
14911483

1484+
/*
1485+
* flatten_clausegroups_list
1486+
* Given a list of lists of RestrictInfos, flatten it to a list
1487+
* of RestrictInfos.
1488+
*
1489+
* This is used to flatten out the result of group_clauses_by_indexkey()
1490+
* or one of its sibling routines, to produce an indexclauses list.
1491+
*/
1492+
List *
1493+
flatten_clausegroups_list(List *clausegroups)
1494+
{
1495+
List *allclauses = NIL;
1496+
List *l;
1497+
1498+
foreach(l, clausegroups)
1499+
{
1500+
allclauses = nconc(allclauses, listCopy((List *) lfirst(l)));
1501+
}
1502+
return allclauses;
1503+
}
1504+
1505+
/*
1506+
* make_expr_from_indexclauses()
1507+
* Given an indexclauses structure, produce an ordinary boolean expression.
1508+
*
1509+
* This consists of stripping out the RestrictInfo nodes and inserting
1510+
* explicit AND and OR nodes as needed. There's not much to it, but
1511+
* the functionality is needed in a few places, so centralize the logic.
1512+
*/
1513+
Expr *
1514+
make_expr_from_indexclauses(List *indexclauses)
1515+
{
1516+
List *orclauses = NIL;
1517+
List *orlist;
1518+
1519+
/* There's no such thing as an indexpath with zero scans */
1520+
Assert(indexclauses != NIL);
1521+
1522+
foreach(orlist, indexclauses)
1523+
{
1524+
List *andlist = (List *) lfirst(orlist);
1525+
1526+
/* Strip RestrictInfos */
1527+
andlist = get_actual_clauses(andlist);
1528+
/* Insert AND node if needed, and add to orclauses list */
1529+
orclauses = lappend(orclauses, make_ands_explicit(andlist));
1530+
}
1531+
1532+
if (length(orclauses) > 1)
1533+
return make_orclause(orclauses);
1534+
else
1535+
return (Expr *) lfirst(orclauses);
1536+
}
1537+
1538+
14921539
/****************************************************************************
14931540
* ---- ROUTINES TO CHECK OPERANDS ----
14941541
****************************************************************************/
@@ -1799,8 +1846,7 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups)
17991846
RestrictInfo *rinfo = (RestrictInfo *) lfirst(i);
18001847

18011848
FastConc(&resultquals,
1802-
expand_indexqual_condition(rinfo->clause,
1803-
curClass));
1849+
expand_indexqual_condition(rinfo, curClass));
18041850
}
18051851

18061852
clausegroups = lnext(clausegroups);
@@ -1816,10 +1862,13 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups)
18161862

18171863
/*
18181864
* expand_indexqual_condition --- expand a single indexqual condition
1865+
*
1866+
* The input is a single RestrictInfo, the output a list of RestrictInfos
18191867
*/
18201868
static List *
1821-
expand_indexqual_condition(Expr *clause, Oid opclass)
1869+
expand_indexqual_condition(RestrictInfo *rinfo, Oid opclass)
18221870
{
1871+
Expr *clause = rinfo->clause;
18231872
/* we know these will succeed */
18241873
Node *leftop = get_leftop(clause);
18251874
Node *rightop = get_rightop(clause);
@@ -1883,7 +1932,7 @@ expand_indexqual_condition(Expr *clause, Oid opclass)
18831932
break;
18841933

18851934
default:
1886-
result = makeList1(clause);
1935+
result = makeList1(rinfo);
18871936
break;
18881937
}
18891938

@@ -1978,7 +2027,7 @@ prefix_quals(Node *leftop, Oid opclass,
19782027
elog(ERROR, "no = operator for opclass %u", opclass);
19792028
expr = make_opclause(oproid, BOOLOID, false,
19802029
(Expr *) leftop, (Expr *) prefix_const);
1981-
result = makeList1(expr);
2030+
result = makeList1(make_restrictinfo(expr, true, true));
19822031
return result;
19832032
}
19842033

@@ -1993,7 +2042,7 @@ prefix_quals(Node *leftop, Oid opclass,
19932042
elog(ERROR, "no >= operator for opclass %u", opclass);
19942043
expr = make_opclause(oproid, BOOLOID, false,
19952044
(Expr *) leftop, (Expr *) prefix_const);
1996-
result = makeList1(expr);
2045+
result = makeList1(make_restrictinfo(expr, true, true));
19972046

19982047
/*-------
19992048
* If we can create a string larger than the prefix, we can say
@@ -2009,7 +2058,7 @@ prefix_quals(Node *leftop, Oid opclass,
20092058
elog(ERROR, "no < operator for opclass %u", opclass);
20102059
expr = make_opclause(oproid, BOOLOID, false,
20112060
(Expr *) leftop, (Expr *) greaterstr);
2012-
result = lappend(result, expr);
2061+
result = lappend(result, make_restrictinfo(expr, true, true));
20132062
}
20142063

20152064
return result;
@@ -2080,7 +2129,7 @@ network_prefix_quals(Node *leftop, Oid expr_op, Oid opclass, Datum rightop)
20802129
(Expr *) leftop,
20812130
(Expr *) makeConst(datatype, -1, opr1right,
20822131
false, false));
2083-
result = makeList1(expr);
2132+
result = makeList1(make_restrictinfo(expr, true, true));
20842133

20852134
/* create clause "key <= network_scan_last( rightop )" */
20862135

@@ -2095,7 +2144,7 @@ network_prefix_quals(Node *leftop, Oid expr_op, Oid opclass, Datum rightop)
20952144
(Expr *) leftop,
20962145
(Expr *) makeConst(datatype, -1, opr2right,
20972146
false, false));
2098-
result = lappend(result, expr);
2147+
result = lappend(result, make_restrictinfo(expr, true, true));
20992148

21002149
return result;
21012150
}

0 commit comments

Comments
 (0)