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

Commit5e144cc

Browse files
committed
Revert applying column aliases to the output of whole-row Vars.
In commitbf7ca15, I had the bright idea that we could make theresult of a whole-row Var (that is, foo.*) track any column aliasesthat had been applied to the FROM entry the Var refers to. However,that's not terribly logically consistent, because now the output ofthe Var is no longer of the named composite type that the Var claimsto emit.bf7ca15 tried to handle that by changing the outputtuple values to be labeled with a blessed RECORD type, but that'sreally pretty disastrous: we can wind up storing such tuples ontodisk, whereupon they're not readable by other sessions.The only practical fix I can see is to give up on whatbf7ca15tried to do, and say that the column names of tuples produced bya whole-row Var are always those of the underlying named compositetype, query aliases or no. While this introduces some inconsistencies,it removes others, so it's not that awful in the abstract. What *is*kind of awful is to make such a behavioral change in a back-patchedbug fix. But corrupt data is worse, so back-patched it will be.(A workaround available to anyone who's unhappy about this is tointroduce an extra level of sub-SELECT, so that the whole-row Var isreferring to the sub-SELECT's output and not to a named table type.Then the Var is of type RECORD to begin with and there's no issue.)Per report from Miles Delahunty. The faulty commit dates to 9.5,so back-patch to all supported branches.Discussion:https://postgr.es/m/2950001.1638729947@sss.pgh.pa.us
1 parent27fafee commit5e144cc

File tree

5 files changed

+54
-92
lines changed

5 files changed

+54
-92
lines changed

‎src/backend/executor/execExpr.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1631,16 +1631,16 @@ ExecInitExprRec(Expr *node, ExprState *state,
16311631
{
16321632
/* generic record, use types of given expressions */
16331633
tupdesc=ExecTypeFromExprList(rowexpr->args);
1634+
/* ... but adopt RowExpr's column aliases */
1635+
ExecTypeSetColNames(tupdesc,rowexpr->colnames);
1636+
/* Bless the tupdesc so it can be looked up later */
1637+
BlessTupleDesc(tupdesc);
16341638
}
16351639
else
16361640
{
16371641
/* it's been cast to a named type, use that */
16381642
tupdesc=lookup_rowtype_tupdesc_copy(rowexpr->row_typeid,-1);
16391643
}
1640-
/* In either case, adopt RowExpr's column aliases */
1641-
ExecTypeSetColNames(tupdesc,rowexpr->colnames);
1642-
/* Bless the tupdesc in case it's now of type RECORD */
1643-
BlessTupleDesc(tupdesc);
16441644

16451645
/*
16461646
* In the named-type case, the tupdesc could have more columns

‎src/backend/executor/execExprInterp.c

Lines changed: 33 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3991,12 +3991,8 @@ ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
39913991
* generates an INT4 NULL regardless of the dropped column type).
39923992
* If we find a dropped column and cannot verify that case (1)
39933993
* holds, we have to use the slow path to check (2) for each row.
3994-
*
3995-
* If vartype is a domain over composite, just look through that
3996-
* to the base composite type.
39973994
*/
3998-
var_tupdesc=lookup_rowtype_tupdesc_domain(variable->vartype,
3999-
-1, false);
3995+
var_tupdesc=lookup_rowtype_tupdesc(variable->vartype,-1);
40003996

40013997
slot_tupdesc=slot->tts_tupleDescriptor;
40023998

@@ -4033,9 +4029,8 @@ ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
40334029

40344030
/*
40354031
* Use the variable's declared rowtype as the descriptor for the
4036-
* output values, modulo possibly assigning new column names
4037-
* below. In particular, we *must* absorb any attisdropped
4038-
* markings.
4032+
* output values. In particular, we *must* absorb any
4033+
* attisdropped markings.
40394034
*/
40404035
oldcontext=MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
40414036
output_tupdesc=CreateTupleDescCopy(var_tupdesc);
@@ -4053,39 +4048,38 @@ ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
40534048
oldcontext=MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
40544049
output_tupdesc=CreateTupleDescCopy(slot->tts_tupleDescriptor);
40554050
MemoryContextSwitchTo(oldcontext);
4056-
}
40574051

4058-
/*
4059-
* Construct a tuple descriptor for the composite values we'll
4060-
* produce, and make sure its record type is "blessed". The main
4061-
* reason to do this is to be sure that operations such as
4062-
* row_to_json() will see the desired column names when they look up
4063-
* the descriptor from the type information embedded in the composite
4064-
* values.
4065-
*
4066-
* We already got the correct physical datatype info above, but now we
4067-
* should try to find the source RTE and adopt its column aliases, in
4068-
* case they are different from the original rowtype's names. For
4069-
* example, in "SELECT foo(t) FROM tab t(x,y)", the first two columns
4070-
* in the composite output should be named "x" and "y" regardless of
4071-
* tab's column names.
4072-
*
4073-
* If we can't locate the RTE, assume the column names we've got are
4074-
* OK. (As of this writing, the only cases where we can't locate the
4075-
* RTE are in execution of trigger WHEN clauses, and then the Var will
4076-
* have the trigger's relation's rowtype, so its names are fine.)
4077-
* Also, if the creator of the RTE didn't bother to fill in an eref
4078-
* field, assume our column names are OK. (This happens in COPY, and
4079-
* perhaps other places.)
4080-
*/
4081-
if (econtext->ecxt_estate&&
4082-
variable->varno <=econtext->ecxt_estate->es_range_table_size)
4083-
{
4084-
RangeTblEntry*rte=exec_rt_fetch(variable->varno,
4085-
econtext->ecxt_estate);
4052+
/*
4053+
* It's possible that the input slot is a relation scan slot and
4054+
* so is marked with that relation's rowtype. But we're supposed
4055+
* to be returning RECORD, so reset to that.
4056+
*/
4057+
output_tupdesc->tdtypeid=RECORDOID;
4058+
output_tupdesc->tdtypmod=-1;
40864059

4087-
if (rte->eref)
4088-
ExecTypeSetColNames(output_tupdesc,rte->eref->colnames);
4060+
/*
4061+
* We already got the correct physical datatype info above, but
4062+
* now we should try to find the source RTE and adopt its column
4063+
* aliases, since it's unlikely that the input slot has the
4064+
* desired names.
4065+
*
4066+
* If we can't locate the RTE, assume the column names we've got
4067+
* are OK. (As of this writing, the only cases where we can't
4068+
* locate the RTE are in execution of trigger WHEN clauses, and
4069+
* then the Var will have the trigger's relation's rowtype, so its
4070+
* names are fine.) Also, if the creator of the RTE didn't bother
4071+
* to fill in an eref field, assume our column names are OK. (This
4072+
* happens in COPY, and perhaps other places.)
4073+
*/
4074+
if (econtext->ecxt_estate&&
4075+
variable->varno <=econtext->ecxt_estate->es_range_table_size)
4076+
{
4077+
RangeTblEntry*rte=exec_rt_fetch(variable->varno,
4078+
econtext->ecxt_estate);
4079+
4080+
if (rte->eref)
4081+
ExecTypeSetColNames(output_tupdesc,rte->eref->colnames);
4082+
}
40894083
}
40904084

40914085
/* Bless the tupdesc if needed, and save it in the execution state */

‎src/backend/executor/execTuples.c

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2022,51 +2022,40 @@ ExecTypeFromExprList(List *exprList)
20222022
}
20232023

20242024
/*
2025-
* ExecTypeSetColNames - set column names in a TupleDesc
2025+
* ExecTypeSetColNames - set column names in aRECORDTupleDesc
20262026
*
20272027
* Column names must be provided as an alias list (list of String nodes).
2028-
*
2029-
* For some callers, the supplied tupdesc has a named rowtype (not RECORD)
2030-
* and it is moderately likely that the alias list matches the column names
2031-
* already present in the tupdesc. If we do change any column names then
2032-
* we must reset the tupdesc's type to anonymous RECORD; but we avoid doing
2033-
* so if no names change.
20342028
*/
20352029
void
20362030
ExecTypeSetColNames(TupleDesctypeInfo,List*namesList)
20372031
{
2038-
boolmodified= false;
20392032
intcolno=0;
20402033
ListCell*lc;
20412034

2035+
/* It's only OK to change col names in a not-yet-blessed RECORD type */
2036+
Assert(typeInfo->tdtypeid==RECORDOID);
2037+
Assert(typeInfo->tdtypmod<0);
2038+
20422039
foreach(lc,namesList)
20432040
{
20442041
char*cname=strVal(lfirst(lc));
20452042
Form_pg_attributeattr;
20462043

2047-
/* Guard against too-long names list */
2044+
/* Guard against too-long names list(probably can't happen)*/
20482045
if (colno >=typeInfo->natts)
20492046
break;
20502047
attr=TupleDescAttr(typeInfo,colno);
20512048
colno++;
20522049

2053-
/* Ignore empty aliases (these must be for dropped columns) */
2054-
if (cname[0]=='\0')
2050+
/*
2051+
* Do nothing for empty aliases or dropped columns (these cases
2052+
* probably can't arise in RECORD types, either)
2053+
*/
2054+
if (cname[0]=='\0'||attr->attisdropped)
20552055
continue;
20562056

2057-
/* Change tupdesc only if alias is actually different */
2058-
if (strcmp(cname,NameStr(attr->attname))!=0)
2059-
{
2060-
namestrcpy(&(attr->attname),cname);
2061-
modified= true;
2062-
}
2063-
}
2064-
2065-
/* If we modified the tupdesc, it's now a new record type */
2066-
if (modified)
2067-
{
2068-
typeInfo->tdtypeid=RECORDOID;
2069-
typeInfo->tdtypmod=-1;
2057+
/* OK, assign the column name */
2058+
namestrcpy(&(attr->attname),cname);
20702059
}
20712060
}
20722061

‎src/test/regress/expected/rowtypes.out

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,18 +1004,8 @@ select row_to_json(i) from int8_tbl i;
10041004
{"q1":4567890123456789,"q2":-4567890123456789}
10051005
(5 rows)
10061006

1007+
-- since "i" is of type "int8_tbl", attaching aliases doesn't change anything:
10071008
select row_to_json(i) from int8_tbl i(x,y);
1008-
row_to_json
1009-
----------------------------------------------
1010-
{"x":123,"y":456}
1011-
{"x":123,"y":4567890123456789}
1012-
{"x":4567890123456789,"y":123}
1013-
{"x":4567890123456789,"y":4567890123456789}
1014-
{"x":4567890123456789,"y":-4567890123456789}
1015-
(5 rows)
1016-
1017-
create temp view vv1 as select * from int8_tbl;
1018-
select row_to_json(i) from vv1 i;
10191009
row_to_json
10201010
------------------------------------------------
10211011
{"q1":123,"q2":456}
@@ -1025,16 +1015,7 @@ select row_to_json(i) from vv1 i;
10251015
{"q1":4567890123456789,"q2":-4567890123456789}
10261016
(5 rows)
10271017

1028-
select row_to_json(i) from vv1 i(x,y);
1029-
row_to_json
1030-
----------------------------------------------
1031-
{"x":123,"y":456}
1032-
{"x":123,"y":4567890123456789}
1033-
{"x":4567890123456789,"y":123}
1034-
{"x":4567890123456789,"y":4567890123456789}
1035-
{"x":4567890123456789,"y":-4567890123456789}
1036-
(5 rows)
1037-
1018+
-- in these examples, we'll report the exposed column names of the subselect:
10381019
select row_to_json(ss) from
10391020
(select q1, q2 from int8_tbl) as ss;
10401021
row_to_json

‎src/test/regress/sql/rowtypes.sql

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -413,12 +413,10 @@ select longname(f) from fullname f;
413413
--
414414

415415
select row_to_json(i)from int8_tbl i;
416+
-- since "i" is of type "int8_tbl", attaching aliases doesn't change anything:
416417
select row_to_json(i)from int8_tbl i(x,y);
417418

418-
create temp view vv1asselect*from int8_tbl;
419-
select row_to_json(i)from vv1 i;
420-
select row_to_json(i)from vv1 i(x,y);
421-
419+
-- in these examples, we'll report the exposed column names of the subselect:
422420
select row_to_json(ss)from
423421
(select q1, q2from int8_tbl)as ss;
424422
select row_to_json(ss)from

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp