Skip to content

Commit da8f3eb

Browse files
committed
Don't convert Consts into Vars during setrefs.c processing.
While converting expressions in an upper-level plan node so that they reference Vars and expressions provided by the input plan node(s), don't convert plain Const items, even if there happens to be a matching Const in the input. It's silly to do so because a Var is more expensive to execute than a Const. Moreover, converting can fool ExecCheckPlanOutput's check that an insert or update query inserts nulls into dropped columns, leading to "query provides a value for a dropped column" errors during INSERT or UPDATE on a table with a dropped column. We could solve this by making that check more complicated, but I don't see the point; this fix should save a marginal number of cycles, and it also makes for less messy EXPLAIN output, as shown by the ensuing regression test result changes. Per report from Pavel Hanák. I have not incorporated a test case based on that example, as there doesn't seem to be a simple way of checking this in isolation without making a bunch of assumptions about other planner and SQL-function behavior. Back-patch to 9.6. This setrefs.c behavior exists much further back, but there is not currently reason to think that it causes problems before 9.6. Discussion: <83shraampf.fsf@is-it.eu>
1 parent 00a8685 commit da8f3eb

File tree

3 files changed

+28
-5
lines changed

3 files changed

+28
-5
lines changed

contrib/postgres_fdw/expected/postgres_fdw.out

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2447,10 +2447,10 @@ select count(c2) w, c2 x, 5 y, 7.0 z from ft1 group by 2, y, 9.0::int order by 2
24472447
QUERY PLAN
24482448
----------------------------------------------------------------------------------------------------------
24492449
Sort
2450-
Output: (count(c2)), c2, (5), (7.0), (9)
2450+
Output: (count(c2)), c2, 5, 7.0, 9
24512451
Sort Key: ft1.c2
24522452
-> Foreign Scan
2453-
Output: (count(c2)), c2, (5), (7.0), (9)
2453+
Output: (count(c2)), c2, 5, 7.0, 9
24542454
Relations: Aggregate on (public.ft1)
24552455
Remote SQL: SELECT count(c2), c2, 5, 7.0, 9 FROM "S 1"."T 1" GROUP BY c2, 5::integer, 9::integer
24562456
(7 rows)
@@ -2499,7 +2499,7 @@ select count(*) from (select c5, count(c1) from ft1 group by c5, sqrt(c2) having
24992499
Aggregate
25002500
Output: count(*)
25012501
-> Foreign Scan
2502-
Output: ft1.c5, (NULL::bigint), (sqrt((ft1.c2)::double precision))
2502+
Output: ft1.c5, NULL::bigint, (sqrt((ft1.c2)::double precision))
25032503
Filter: (((((avg(ft1.c1)) / (avg(ft1.c1))))::double precision * random()) <= '1'::double precision)
25042504
Relations: Aggregate on (public.ft1)
25052505
Remote SQL: SELECT c5, NULL::bigint, sqrt(c2), avg("C 1") FROM "S 1"."T 1" GROUP BY c5, (sqrt(c2)) HAVING ((avg("C 1") < 500::numeric))
@@ -3139,7 +3139,7 @@ select sum(q.a), count(q.b) from ft4 left join (select 13, avg(ft1.c1), sum(ft2.
31393139
-> Subquery Scan on q
31403140
Output: q.a, q.b
31413141
-> Foreign Scan
3142-
Output: (13), (avg(ft1.c1)), (NULL::bigint)
3142+
Output: 13, (avg(ft1.c1)), NULL::bigint
31433143
Relations: Aggregate on ((public.ft2) LEFT JOIN (public.ft1))
31443144
Remote SQL: SELECT 13, avg(r1."C 1"), NULL::bigint FROM ("S 1"."T 1" r2 LEFT JOIN "S 1"."T 1" r1 ON (((r1."C 1" = r2."C 1"))))
31453145
(16 rows)

src/backend/optimizer/plan/setrefs.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1823,6 +1823,19 @@ set_dummy_tlist_references(Plan *plan, int rtoffset)
18231823
Var *oldvar = (Var *) tle->expr;
18241824
Var *newvar;
18251825

1826+
/*
1827+
* As in search_indexed_tlist_for_non_var(), we prefer to keep Consts
1828+
* as Consts, not Vars referencing Consts. Here, there's no speed
1829+
* advantage to be had, but it makes EXPLAIN output look cleaner, and
1830+
* again it avoids confusing the executor.
1831+
*/
1832+
if (IsA(oldvar, Const))
1833+
{
1834+
/* just reuse the existing TLE node */
1835+
output_targetlist = lappend(output_targetlist, tle);
1836+
continue;
1837+
}
1838+
18261839
newvar = makeVar(OUTER_VAR,
18271840
tle->resno,
18281841
exprType((Node *) oldvar),
@@ -2010,6 +2023,16 @@ search_indexed_tlist_for_non_var(Node *node,
20102023
{
20112024
TargetEntry *tle;
20122025

2026+
/*
2027+
* If it's a simple Const, replacing it with a Var is silly, even if there
2028+
* happens to be an identical Const below; a Var is more expensive to
2029+
* execute than a Const. What's more, replacing it could confuse some
2030+
* places in the executor that expect to see simple Consts for, eg,
2031+
* dropped columns.
2032+
*/
2033+
if (IsA(node, Const))
2034+
return NULL;
2035+
20132036
tle = tlist_member(node, itlist->tlist);
20142037
if (tle)
20152038
{

src/test/regress/expected/inherit.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1426,7 +1426,7 @@ ORDER BY thousand, tenthous;
14261426
Sort Key: tenk1.thousand, tenk1.tenthous
14271427
-> Index Only Scan using tenk1_thous_tenthous on tenk1
14281428
-> Sort
1429-
Sort Key: (42), (42)
1429+
Sort Key: 42, 42
14301430
-> Index Only Scan using tenk1_hundred on tenk1 tenk1_1
14311431
(6 rows)
14321432

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy