Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit a9ae99d

Browse files
committed
Prevent bogus pullup of constant-valued functions returning composite.
Fix an oversight in commit 7266d09: as it stood, the code failed when a function-in-FROM returns composite and can be simplified to a composite constant. For the moment, just test for composite result and abandon pullup if we see one. To make it actually work, we'd have to decompose the composite constant into per-column constants; which is surely do-able, but I'm not convinced it's worth the code space. Per report from Raúl Marín Rodríguez. Discussion: https://postgr.es/m/CAM6_UM4isP+buRA5sWodO_MUEgutms-KDfnkwGmryc5DGj9XuQ@mail.gmail.com
1 parent 6d05086 commit a9ae99d

File tree

3 files changed

+74
-0
lines changed

3 files changed

+74
-0
lines changed

src/backend/optimizer/prep/prepjointree.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "postgres.h"
2727

2828
#include "catalog/pg_type.h"
29+
#include "funcapi.h"
2930
#include "nodes/makefuncs.h"
3031
#include "nodes/nodeFuncs.h"
3132
#include "optimizer/clauses.h"
@@ -1683,6 +1684,9 @@ pull_up_constant_function(PlannerInfo *root, Node *jtnode,
16831684
{
16841685
Query *parse = root->parse;
16851686
RangeTblFunction *rtf;
1687+
TypeFuncClass functypclass;
1688+
Oid funcrettype;
1689+
TupleDesc tupdesc;
16861690
pullup_replace_vars_context rvcontext;
16871691

16881692
/* Fail if the RTE has ORDINALITY - we don't implement that here. */
@@ -1696,6 +1700,20 @@ pull_up_constant_function(PlannerInfo *root, Node *jtnode,
16961700
if (!IsA(rtf->funcexpr, Const))
16971701
return jtnode;
16981702

1703+
/*
1704+
* If the function's result is not a scalar, we punt. In principle we
1705+
* could break the composite constant value apart into per-column
1706+
* constants, but for now it seems not worth the work.
1707+
*/
1708+
if (rtf->funccolcount != 1)
1709+
return jtnode; /* definitely composite */
1710+
1711+
functypclass = get_expr_result_type(rtf->funcexpr,
1712+
&funcrettype,
1713+
&tupdesc);
1714+
if (functypclass != TYPEFUNC_SCALAR)
1715+
return jtnode; /* must be a one-column composite type */
1716+
16991717
/* Create context for applying pullup_replace_vars */
17001718
rvcontext.root = root;
17011719
rvcontext.targetlist = list_make1(makeTargetEntry((Expr *) rtf->funcexpr,

src/test/regress/expected/join.out

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3365,6 +3365,43 @@ where nt3.id = 1 and ss2.b3;
33653365
(9 rows)
33663366

33673367
drop function f_immutable_int4(int);
3368+
-- test inlining when function returns composite
3369+
create function mki8(bigint, bigint) returns int8_tbl as
3370+
$$select row($1,$2)::int8_tbl$$ language sql;
3371+
create function mki4(int) returns int4_tbl as
3372+
$$select row($1)::int4_tbl$$ language sql;
3373+
explain (verbose, costs off)
3374+
select * from mki8(1,2);
3375+
QUERY PLAN
3376+
------------------------------------
3377+
Function Scan on mki8
3378+
Output: q1, q2
3379+
Function Call: '(1,2)'::int8_tbl
3380+
(3 rows)
3381+
3382+
select * from mki8(1,2);
3383+
q1 | q2
3384+
----+----
3385+
1 | 2
3386+
(1 row)
3387+
3388+
explain (verbose, costs off)
3389+
select * from mki4(42);
3390+
QUERY PLAN
3391+
-----------------------------------
3392+
Function Scan on mki4
3393+
Output: f1
3394+
Function Call: '(42)'::int4_tbl
3395+
(3 rows)
3396+
3397+
select * from mki4(42);
3398+
f1
3399+
----
3400+
42
3401+
(1 row)
3402+
3403+
drop function mki8(bigint, bigint);
3404+
drop function mki4(int);
33683405
--
33693406
-- test extraction of restriction OR clauses from join OR clause
33703407
-- (we used to only do this for indexable clauses)

src/test/regress/sql/join.sql

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,25 @@ where nt3.id = 1 and ss2.b3;
10721072

10731073
drop function f_immutable_int4(int);
10741074

1075+
-- test inlining when function returns composite
1076+
1077+
create function mki8(bigint, bigint) returns int8_tbl as
1078+
$$select row($1,$2)::int8_tbl$$ language sql;
1079+
1080+
create function mki4(int) returns int4_tbl as
1081+
$$select row($1)::int4_tbl$$ language sql;
1082+
1083+
explain (verbose, costs off)
1084+
select * from mki8(1,2);
1085+
select * from mki8(1,2);
1086+
1087+
explain (verbose, costs off)
1088+
select * from mki4(42);
1089+
select * from mki4(42);
1090+
1091+
drop function mki8(bigint, bigint);
1092+
drop function mki4(int);
1093+
10751094
--
10761095
-- test extraction of restriction OR clauses from join OR clause
10771096
-- (we used to only do this for indexable clauses)

0 commit comments

Comments
 (0)