Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitdd3bab5

Browse files
committed
Ensure that whole-row junk Vars are always of composite type.
The EvalPlanQual machinery assumes that whole-row Vars generated for theoutputs of non-table RTEs will be of composite types. However, for thecase where the RTE is a function call returning a scalar type, we weredoing the wrong thing, as a result of sharing code with a parser casewhere the function's scalar output is wanted. (Or at least, that's whatthat case has done historically; it does seem a bit inconsistent.)To fix, extend makeWholeRowVar's API so that it can support both use-cases.This fixes Belinda Cussen's report of crashes during concurrent executionof UPDATEs involving joins to the result of UNNEST() --- in READ COMMITTEDmode, we'd run the EvalPlanQual machinery after a conflicting row updatecommits, and it was expecting to get a HeapTuple not a scalar datum fromthe "wholerowN" variable referencing the function RTE.Back-patch to 9.0 where the current EvalPlanQual implementation appeared.In 9.1 and up, this patch also fixes failure to attach the correctcollation to the Var generated for a scalar-result case. An example:regression=# select upper(x.*) from textcat('ab', 'cd') x;ERROR: could not determine which collation to use for upper() function
1 parent91572ee commitdd3bab5

File tree

5 files changed

+38
-27
lines changed

5 files changed

+38
-27
lines changed

‎src/backend/nodes/makefuncs.c

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,17 @@ makeVarFromTargetEntry(Index varno,
121121
* with error cases, but it's not worth changing now.) The vartype indicates
122122
* a rowtype; either a named composite type, or RECORD. This function
123123
* encapsulates the logic for determining the correct rowtype OID to use.
124+
*
125+
* If allowScalar is true, then for the case where the RTE is a function
126+
* returning a non-composite result type, we produce a normal Var referencing
127+
* the function's result directly, instead of the single-column composite
128+
* value that the whole-row notation might otherwise suggest.
124129
*/
125130
Var*
126131
makeWholeRowVar(RangeTblEntry*rte,
127132
Indexvarno,
128-
Indexvarlevelsup)
133+
Indexvarlevelsup,
134+
boolallowScalar)
129135
{
130136
Var*result;
131137
Oidtoid;
@@ -157,39 +163,34 @@ makeWholeRowVar(RangeTblEntry *rte,
157163
InvalidOid,
158164
varlevelsup);
159165
}
160-
else
166+
elseif (allowScalar)
161167
{
162-
/*
163-
* func returns scalar; instead of making a whole-row Var,
164-
* just reference the function's scalar output. (XXX this
165-
* seems a tad inconsistent, especially if "f.*" was
166-
* explicitly written ...)
167-
*/
168+
/* func returns scalar; just return its output as-is */
168169
result=makeVar(varno,
169170
1,
170171
toid,
171172
-1,
173+
exprCollation(rte->funcexpr),
174+
varlevelsup);
175+
}
176+
else
177+
{
178+
/* func returns scalar, but we want a composite result */
179+
result=makeVar(varno,
180+
InvalidAttrNumber,
181+
RECORDOID,
182+
-1,
172183
InvalidOid,
173184
varlevelsup);
174185
}
175186
break;
176-
caseRTE_VALUES:
177-
toid=RECORDOID;
178-
/* returns composite; same as relation case */
179-
result=makeVar(varno,
180-
InvalidAttrNumber,
181-
toid,
182-
-1,
183-
InvalidOid,
184-
varlevelsup);
185-
break;
186187
default:
187188

188189
/*
189-
* RTE is a joinorsubselect.We represent this as a whole-row
190-
* Var of RECORD type.(Note that in most cases the Var will be
191-
* expanded to a RowExpr during planning, but that is not our
192-
* concern here.)
190+
* RTE is a join, subselect,orVALUES.We represent this as a
191+
*whole-rowVar of RECORD type.(Note that in most cases the Var
192+
*will beexpanded to a RowExpr during planning, but that is not
193+
*ourconcern here.)
193194
*/
194195
result=makeVar(varno,
195196
InvalidAttrNumber,

‎src/backend/optimizer/prep/preptlist.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,8 @@ preprocess_targetlist(PlannerInfo *root, List *tlist)
129129
/* Not a table, so we need the whole row as a junk var */
130130
var=makeWholeRowVar(rt_fetch(rc->rti,range_table),
131131
rc->rti,
132-
0);
132+
0,
133+
false);
133134
snprintf(resname,sizeof(resname),"wholerow%u",rc->rowmarkId);
134135
tle=makeTargetEntry((Expr*)var,
135136
list_length(tlist)+1,

‎src/backend/parser/parse_expr.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2059,8 +2059,15 @@ transformWholeRowRef(ParseState *pstate, RangeTblEntry *rte, int location)
20592059
/* Find the RTE's rangetable location */
20602060
vnum=RTERangeTablePosn(pstate,rte,&sublevels_up);
20612061

2062-
/* Build the appropriate referencing node */
2063-
result=makeWholeRowVar(rte,vnum,sublevels_up);
2062+
/*
2063+
* Build the appropriate referencing node. Note that if the RTE is a
2064+
* function returning scalar, we create just a plain reference to the
2065+
* function value, not a composite containing a single column. This is
2066+
* pretty inconsistent at first sight, but it's what we've done
2067+
* historically. One argument for it is that "rel" and "rel.*" mean the
2068+
* same thing for composite relations, so why not for scalar functions...
2069+
*/
2070+
result=makeWholeRowVar(rte,vnum,sublevels_up, true);
20642071

20652072
/* location is not filled in by makeWholeRowVar */
20662073
result->location=location;

‎src/backend/rewrite/rewriteHandler.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1188,7 +1188,8 @@ rewriteTargetListUD(Query *parsetree, RangeTblEntry *target_rte,
11881188
*/
11891189
var=makeWholeRowVar(target_rte,
11901190
parsetree->resultRelation,
1191-
0);
1191+
0,
1192+
false);
11921193

11931194
attrname="wholerow";
11941195
}

‎src/include/nodes/makefuncs.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ extern Var *makeVarFromTargetEntry(Index varno,
3535

3636
externVar*makeWholeRowVar(RangeTblEntry*rte,
3737
Indexvarno,
38-
Indexvarlevelsup);
38+
Indexvarlevelsup,
39+
boolallowScalar);
3940

4041
externTargetEntry*makeTargetEntry(Expr*expr,
4142
AttrNumberresno,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp