Skip to content

Commit f4d865f

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 2a8783e commit f4d865f

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

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