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

Commit09989ba

Browse files
committed
Fix type-checking of RECORD-returning functions in FROM, redux.
Commit2ed8f9a intended to institute a policy that if aRangeTblFunction has a coldeflist, then the function return type iscertainly RECORD, and we should use the coldeflist as the source oftruth about what the columns of the record type are. When theoriginal function has been folded to a constant, inspection of theconstant might give a different answer. This situation will lead toa tuple-type-mismatch error at execution, but up until that point weneed to consistently believe the coldeflist, or we'll have problemsfrom different bits of code reaching different conclusions.expandRTE didn't get that memo though, and would try to produce atupdesc based on the constant in this situation, leading to anassertion failure. (Desultory testing suggests that non-assertbuilds often manage to give the expected error, although I alsosaw a "cache lookup failed for type 0" error, and it seems atleast possible that a crash could happen.)Some other callers of get_expr_result_type and get_expr_result_tupdescwere also being incautious about this. While none of them seem tohave actual bugs, they're working harder than necessary in this case,besides which it seems safest to have an explicit policy of not usingthose functions on an RTE with a coldeflist. Adjust the codeaccordingly, and add commentary to funcapi.c about this policy.Also fix an obsolete comment that claimed "get_expr_result_type()doesn't know how to extract type info from a RECORD constant".That hasn't been true since commitd575347.Per bug #18422 from Alexander Lakhin.As with the previous commit, back-patch to all supported branches.Discussion:https://postgr.es/m/18422-89ca86c8eac5246d@postgresql.org
1 parent3cd4135 commit09989ba

File tree

7 files changed

+41
-13
lines changed

7 files changed

+41
-13
lines changed

‎src/backend/catalog/dependency.c‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2385,7 +2385,11 @@ process_function_rte_ref(RangeTblEntry *rte, AttrNumber attnum,
23852385
{
23862386
TupleDesctupdesc;
23872387

2388-
tupdesc=get_expr_result_tupdesc(rtfunc->funcexpr, true);
2388+
/* If it has a coldeflist, it certainly returns RECORD */
2389+
if (rtfunc->funccolnames!=NIL)
2390+
tupdesc=NULL;/* no need to work hard */
2391+
else
2392+
tupdesc=get_expr_result_tupdesc(rtfunc->funcexpr, true);
23892393
if (tupdesc&&tupdesc->tdtypeid!=RECORDOID)
23902394
{
23912395
/*

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1822,6 +1822,10 @@ pull_up_constant_function(PlannerInfo *root, Node *jtnode,
18221822
if (rtf->funccolcount!=1)
18231823
returnjtnode;/* definitely composite */
18241824

1825+
/* If it has a coldeflist, it certainly returns RECORD */
1826+
if (rtf->funccolnames!=NIL)
1827+
returnjtnode;/* must be a one-column RECORD type */
1828+
18251829
functypclass=get_expr_result_type(rtf->funcexpr,
18261830
&funcrettype,
18271831
&tupdesc);

‎src/backend/optimizer/util/clauses.c‎

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4323,12 +4323,11 @@ evaluate_function(Oid funcid, Oid result_type, int32 result_typmod,
43234323
* Can't simplify if it returns RECORD. The immediate problem is that it
43244324
* will be needing an expected tupdesc which we can't supply here.
43254325
*
4326-
* In the case where it has OUT parameters, it could get by without an
4327-
* expected tupdesc, but we still have issues: get_expr_result_type()
4328-
* doesn't know how to extract type info from a RECORD constant, and in
4329-
* the case of a NULL function result there doesn't seem to be any clean
4330-
* way to fix that. In view of the likelihood of there being still other
4331-
* gotchas, seems best to leave the function call unreduced.
4326+
* In the case where it has OUT parameters, we could build an expected
4327+
* tupdesc from those, but there may be other gotchas lurking. In
4328+
* particular, if the function were to return NULL, we would produce a
4329+
* null constant with no remaining indication of which concrete record
4330+
* type it is. For now, seems best to leave the function call unreduced.
43324331
*/
43334332
if (funcform->prorettype==RECORDOID)
43344333
returnNULL;

‎src/backend/parser/parse_relation.c‎

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2722,12 +2722,17 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
27222722
{
27232723
RangeTblFunction*rtfunc= (RangeTblFunction*)lfirst(lc);
27242724
TypeFuncClassfunctypclass;
2725-
Oidfuncrettype;
2726-
TupleDesctupdesc;
2725+
Oidfuncrettype=InvalidOid;
2726+
TupleDesctupdesc=NULL;
2727+
2728+
/* If it has a coldeflist, it returns RECORD */
2729+
if (rtfunc->funccolnames!=NIL)
2730+
functypclass=TYPEFUNC_RECORD;
2731+
else
2732+
functypclass=get_expr_result_type(rtfunc->funcexpr,
2733+
&funcrettype,
2734+
&tupdesc);
27272735

2728-
functypclass=get_expr_result_type(rtfunc->funcexpr,
2729-
&funcrettype,
2730-
&tupdesc);
27312736
if (functypclass==TYPEFUNC_COMPOSITE||
27322737
functypclass==TYPEFUNC_COMPOSITE_DOMAIN)
27332738
{
@@ -3345,6 +3350,10 @@ get_rte_attribute_is_dropped(RangeTblEntry *rte, AttrNumber attnum)
33453350
{
33463351
TupleDesctupdesc;
33473352

3353+
/* If it has a coldeflist, it returns RECORD */
3354+
if (rtfunc->funccolnames!=NIL)
3355+
return false;/* can't have any dropped columns */
3356+
33483357
tupdesc=get_expr_result_tupdesc(rtfunc->funcexpr,
33493358
true);
33503359
if (tupdesc)

‎src/backend/utils/fmgr/funcapi.c‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,13 @@ get_call_result_type(FunctionCallInfo fcinfo,
296296
/*
297297
* get_expr_result_type
298298
*As above, but work from a calling expression node tree
299+
*
300+
* Beware of using this on the funcexpr of a RTE that has a coldeflist.
301+
* The correct conclusion in such cases is always that the function returns
302+
* RECORD with the columns defined by the coldeflist fields (funccolnames etc).
303+
* If it does not, it's the executor's responsibility to catch the discrepancy
304+
* at runtime; but code processing the query in advance of that point might
305+
* come to inconsistent conclusions if it checks the actual expression.
299306
*/
300307
TypeFuncClass
301308
get_expr_result_type(Node*expr,
@@ -546,7 +553,8 @@ internal_get_result_type(Oid funcid,
546553
* if noError is true, else throws error.
547554
*
548555
* This is a simpler version of get_expr_result_type() for use when the caller
549-
* is only interested in determinate rowtype results.
556+
* is only interested in determinate rowtype results. As with that function,
557+
* beware of using this on the funcexpr of a RTE that has a coldeflist.
550558
*/
551559
TupleDesc
552560
get_expr_result_tupdesc(Node*expr,boolnoError)

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2498,3 +2498,6 @@ with a(b) as (values (row(1,2,3)))
24982498
select * from a, coalesce(b) as c(d int, e int, f float); -- fail
24992499
ERROR: function return row and query-specified return row do not match
25002500
DETAIL: Returned type integer at ordinal position 3, but query expects double precision.
2501+
select * from int8_tbl, coalesce(row(1)) as (a int, b int); -- fail
2502+
ERROR: function return row and query-specified return row do not match
2503+
DETAIL: Returned row contains 1 attribute, but query expects 2.

‎src/test/regress/sql/rangefuncs.sql‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,3 +824,4 @@ with a(b) as (values (row(1,2,3)))
824824
select*from a, coalesce(b)as c(dint, eint, fint, gint);-- fail
825825
with a(b)as (values (row(1,2,3)))
826826
select*from a, coalesce(b)as c(dint, eint, f float);-- fail
827+
select*from int8_tbl, coalesce(row(1))as (aint, bint);-- fail

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp