Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 8eb9998

Browse files
committed
Add a reference to the expression which has triggered creation of this pathkey.
For the sake of consistency in number of groups estimation in incremental sort we need to have an information about expression which caused the pathkey. It doesn't guarantee correct estimation but at least estimation doesn't rely on a SQL string.
1 parent 1bf29f5 commit 8eb9998

File tree

5 files changed

+59
-13
lines changed

5 files changed

+59
-13
lines changed

contrib/postgres_fdw/postgres_fdw.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,7 @@ get_useful_pathkeys_for_relation(PlannerInfo *root, RelOptInfo *rel)
976976
foreach(lc, useful_eclass_list)
977977
{
978978
EquivalenceClass *cur_ec = lfirst(lc);
979+
EquivalenceMember *em;
979980
PathKey *pathkey;
980981

981982
/* If redundant with what we did above, skip it. */
@@ -988,14 +989,15 @@ get_useful_pathkeys_for_relation(PlannerInfo *root, RelOptInfo *rel)
988989
continue;
989990

990991
/* If no pushable expression for this rel, skip it. */
991-
if (find_em_for_rel(root, cur_ec, rel) == NULL)
992+
if ((em = find_em_for_rel(root, cur_ec, rel)) == NULL)
992993
continue;
993994

994995
/* Looks like we can generate a pathkey, so let's do it. */
995996
pathkey = make_canonical_pathkey(root, cur_ec,
996997
linitial_oid(cur_ec->ec_opfamilies),
997998
BTLessStrategyNumber,
998-
false);
999+
false,
1000+
em->em_expr); /* TODO */
9991001
useful_pathkeys_list = lappend(useful_pathkeys_list,
10001002
list_make1(pathkey));
10011003
}

src/backend/optimizer/path/costsize.c

+24-4
Original file line numberDiff line numberDiff line change
@@ -2038,21 +2038,41 @@ cost_incremental_sort(Path *path,
20382038
foreach(l, pathkeys)
20392039
{
20402040
PathKey *key = (PathKey *) lfirst(l);
2041-
EquivalenceMember *member = (EquivalenceMember *)
2042-
linitial(key->pk_eclass->ec_members);
2041+
2042+
#ifdef USE_ASSERT_CHECKING
2043+
ListCell *lc;
2044+
2045+
/* Be paranoid, but caring about performace don't check on prod */
2046+
foreach(lc, key->pk_eclass->ec_members)
2047+
{
2048+
if (find_ec_member_matching_expr(
2049+
key->pk_eclass, key->source_expr,
2050+
pull_varnos(root, (Node *) key->source_expr)))
2051+
break;
2052+
}
2053+
if (!lc)
2054+
/*
2055+
* XXX: Can we build PathKey over derived expression and does it
2056+
* trigger this error?
2057+
*/
2058+
elog(ERROR, "PathKey source expression must be a part of EQ class");
2059+
#endif
2060+
2061+
/* Reassure ourselves no one created pathkeys alternative way */
2062+
Assert(key->source_expr != NULL);
20432063

20442064
/*
20452065
* Check if the expression contains Var with "varno 0" so that we
20462066
* don't call estimate_num_groups in that case.
20472067
*/
2048-
if (bms_is_member(0, pull_varnos(root, (Node *) member->em_expr)))
2068+
if (bms_is_member(0, pull_varnos(root, (Node *) key->source_expr)))
20492069
{
20502070
unknown_varno = true;
20512071
break;
20522072
}
20532073

20542074
/* expression not containing any Vars with "varno 0" */
2055-
presortedExprs = lappend(presortedExprs, member->em_expr);
2075+
presortedExprs = lappend(presortedExprs, key->source_expr);
20562076

20572077
if (foreach_current_index(l) + 1 >= presorted_keys)
20582078
break;

src/backend/optimizer/path/pathkeys.c

+27-6
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ static bool right_merge_direction(PlannerInfo *root, PathKey *pathkey);
5454
PathKey *
5555
make_canonical_pathkey(PlannerInfo *root,
5656
EquivalenceClass *eclass, Oid opfamily,
57-
int strategy, bool nulls_first)
57+
int strategy, bool nulls_first, Expr *src_expr)
5858
{
5959
PathKey *pk;
6060
ListCell *lc;
@@ -89,6 +89,7 @@ make_canonical_pathkey(PlannerInfo *root,
8989
pk->pk_opfamily = opfamily;
9090
pk->pk_strategy = strategy;
9191
pk->pk_nulls_first = nulls_first;
92+
pk->source_expr = src_expr;
9293

9394
root->canon_pathkeys = lappend(root->canon_pathkeys, pk);
9495

@@ -241,7 +242,7 @@ make_pathkey_from_sortinfo(PlannerInfo *root,
241242

242243
/* And finally we can find or create a PathKey node */
243244
return make_canonical_pathkey(root, eclass, opfamily,
244-
strategy, nulls_first);
245+
strategy, nulls_first, expr);
245246
}
246247

247248
/*
@@ -1117,7 +1118,8 @@ convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel,
11171118
outer_ec,
11181119
sub_pathkey->pk_opfamily,
11191120
sub_pathkey->pk_strategy,
1120-
sub_pathkey->pk_nulls_first);
1121+
sub_pathkey->pk_nulls_first,
1122+
(Expr *) outer_var);
11211123
}
11221124
}
11231125
else
@@ -1199,7 +1201,8 @@ convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel,
11991201
outer_ec,
12001202
sub_pathkey->pk_opfamily,
12011203
sub_pathkey->pk_strategy,
1202-
sub_pathkey->pk_nulls_first);
1204+
sub_pathkey->pk_nulls_first,
1205+
(Expr *) outer_var);
12031206
/* score = # of equivalence peers */
12041207
score = list_length(outer_ec->ec_members) - 1;
12051208
/* +1 if it matches the proper query_pathkeys item */
@@ -1643,6 +1646,7 @@ select_outer_pathkeys_for_merge(PlannerInfo *root,
16431646
List *pathkeys = NIL;
16441647
int nClauses = list_length(mergeclauses);
16451648
EquivalenceClass **ecs;
1649+
Expr **exprs;
16461650
int *scores;
16471651
int necs;
16481652
ListCell *lc;
@@ -1657,6 +1661,7 @@ select_outer_pathkeys_for_merge(PlannerInfo *root,
16571661
* duplicates) and their "popularity" scores.
16581662
*/
16591663
ecs = (EquivalenceClass **) palloc(nClauses * sizeof(EquivalenceClass *));
1664+
exprs = (Expr **) palloc(nClauses * sizeof(Expr *));
16601665
scores = (int *) palloc(nClauses * sizeof(int));
16611666
necs = 0;
16621667

@@ -1666,14 +1671,21 @@ select_outer_pathkeys_for_merge(PlannerInfo *root,
16661671
EquivalenceClass *oeclass;
16671672
int score;
16681673
ListCell *lc2;
1674+
Expr *expr;
16691675

16701676
/* get the outer eclass */
16711677
update_mergeclause_eclasses(root, rinfo);
16721678

16731679
if (rinfo->outer_is_left)
1680+
{
16741681
oeclass = rinfo->left_ec;
1682+
expr = (Expr *) linitial(((OpExpr *) rinfo->clause)->args);
1683+
}
16751684
else
1685+
{
16761686
oeclass = rinfo->right_ec;
1687+
expr = (Expr *) lsecond(((OpExpr *) rinfo->clause)->args);
1688+
}
16771689

16781690
/* reject duplicates */
16791691
for (j = 0; j < necs; j++)
@@ -1697,6 +1709,8 @@ select_outer_pathkeys_for_merge(PlannerInfo *root,
16971709
}
16981710

16991711
ecs[necs] = oeclass;
1712+
exprs[necs] = expr;
1713+
17001714
scores[necs] = score;
17011715
necs++;
17021716
}
@@ -1798,7 +1812,8 @@ select_outer_pathkeys_for_merge(PlannerInfo *root,
17981812
ec,
17991813
linitial_oid(ec->ec_opfamilies),
18001814
BTLessStrategyNumber,
1801-
false);
1815+
false,
1816+
exprs[best_j]);
18021817
/* can't be redundant because no duplicate ECs */
18031818
Assert(!pathkey_is_redundant(pathkey, pathkeys));
18041819
pathkeys = lappend(pathkeys, pathkey);
@@ -1852,18 +1867,23 @@ make_inner_pathkeys_for_merge(PlannerInfo *root,
18521867
EquivalenceClass *oeclass;
18531868
EquivalenceClass *ieclass;
18541869
PathKey *pathkey;
1870+
Expr *src_expr;
18551871

18561872
update_mergeclause_eclasses(root, rinfo);
18571873

1874+
Assert(IsA(rinfo->clause, OpExpr) && rinfo->orclause == NULL);
1875+
18581876
if (rinfo->outer_is_left)
18591877
{
18601878
oeclass = rinfo->left_ec;
18611879
ieclass = rinfo->right_ec;
1880+
src_expr = (Expr *) lsecond(((OpExpr *) rinfo->clause)->args);
18621881
}
18631882
else
18641883
{
18651884
oeclass = rinfo->right_ec;
18661885
ieclass = rinfo->left_ec;
1886+
src_expr = (Expr *) linitial(((OpExpr *) rinfo->clause)->args);
18671887
}
18681888

18691889
/* outer eclass should match current or next pathkeys */
@@ -1891,7 +1911,8 @@ make_inner_pathkeys_for_merge(PlannerInfo *root,
18911911
ieclass,
18921912
opathkey->pk_opfamily,
18931913
opathkey->pk_strategy,
1894-
opathkey->pk_nulls_first);
1914+
opathkey->pk_nulls_first,
1915+
src_expr);
18951916

18961917
/*
18971918
* Don't generate redundant pathkeys (which can happen if multiple

src/include/nodes/pathnodes.h

+2
Original file line numberDiff line numberDiff line change
@@ -1469,6 +1469,8 @@ typedef struct PathKey
14691469
Oid pk_opfamily; /* btree opfamily defining the ordering */
14701470
int pk_strategy; /* sort direction (ASC or DESC) */
14711471
bool pk_nulls_first; /* do NULLs come before normal values? */
1472+
1473+
Expr *source_expr; /* Expression, which triggered this creation */
14721474
} PathKey;
14731475

14741476
/*

src/include/optimizer/paths.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,8 @@ extern bool has_useful_pathkeys(PlannerInfo *root, RelOptInfo *rel);
264264
extern List *append_pathkeys(List *target, List *source);
265265
extern PathKey *make_canonical_pathkey(PlannerInfo *root,
266266
EquivalenceClass *eclass, Oid opfamily,
267-
int strategy, bool nulls_first);
267+
int strategy, bool nulls_first,
268+
Expr *src_expr);
268269
extern void add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel,
269270
List *live_childrels);
270271

0 commit comments

Comments
 (0)