Skip to content

Commit 5613da4

Browse files
committed
Optimize nested ConvertRowtypeExpr nodes.
A ConvertRowtypeExpr is used to translate a whole-row reference of a child to that of a parent. The planner produces nested ConvertRowtypeExpr while translating whole-row reference of a leaf partition in a multi-level partition hierarchy. Executor then translates the whole-row reference from the leaf partition into all the intermediate parent's whole-row references before arriving at the final whole-row reference. It could instead translate the whole-row reference from the leaf partition directly to the top-most parent's whole-row reference skipping any intermediate translations. Ashutosh Bapat, with tests by Kyotaro Horiguchi and some editorialization by me. Reviewed by Andres Freund, Pavel Stehule, Kyotaro Horiguchi, Dmitry Dolgov, Tom Lane.
1 parent c24dcd0 commit 5613da4

File tree

3 files changed

+69
-0
lines changed

3 files changed

+69
-0
lines changed

src/backend/optimizer/util/clauses.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3716,6 +3716,52 @@ eval_const_expressions_mutator(Node *node,
37163716
context);
37173717
}
37183718
break;
3719+
case T_ConvertRowtypeExpr:
3720+
{
3721+
ConvertRowtypeExpr *cre = castNode(ConvertRowtypeExpr, node);
3722+
Node *arg;
3723+
ConvertRowtypeExpr *newcre;
3724+
3725+
arg = eval_const_expressions_mutator((Node *) cre->arg,
3726+
context);
3727+
3728+
newcre = makeNode(ConvertRowtypeExpr);
3729+
newcre->resulttype = cre->resulttype;
3730+
newcre->convertformat = cre->convertformat;
3731+
newcre->location = cre->location;
3732+
3733+
/*
3734+
* In case of a nested ConvertRowtypeExpr, we can convert the
3735+
* leaf row directly to the topmost row format without any
3736+
* intermediate conversions. (This works because
3737+
* ConvertRowtypeExpr is used only for child->parent
3738+
* conversion in inheritance trees, which works by exact match
3739+
* of column name, and a column absent in an intermediate
3740+
* result can't be present in the final result.)
3741+
*
3742+
* No need to check more than one level deep, because the
3743+
* above recursion will have flattened anything else.
3744+
*/
3745+
if (arg != NULL && IsA(arg, ConvertRowtypeExpr))
3746+
{
3747+
ConvertRowtypeExpr *argcre = (ConvertRowtypeExpr *) arg;
3748+
3749+
arg = (Node *) argcre->arg;
3750+
3751+
/*
3752+
* Make sure an outer implicit conversion can't hide an
3753+
* inner explicit one.
3754+
*/
3755+
if (newcre->convertformat == COERCE_IMPLICIT_CAST)
3756+
newcre->convertformat = argcre->convertformat;
3757+
}
3758+
3759+
newcre->arg = (Expr *) arg;
3760+
3761+
if (arg != NULL && IsA(arg, Const))
3762+
return ece_evaluate_expr((Node *) newcre);
3763+
return (Node *) newcre;
3764+
}
37193765
default:
37203766
break;
37213767
}

src/test/regress/expected/inherit.out

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,8 @@ NOTICE: drop cascades to table c1
764764
-- tables. See the pgsql-hackers thread beginning Dec. 4/04
765765
create table base (i integer);
766766
create table derived () inherits (base);
767+
create table more_derived (like derived, b int) inherits (derived);
768+
NOTICE: merging column "i" with inherited definition
767769
insert into derived (i) values (0);
768770
select derived::base from derived;
769771
derived
@@ -777,6 +779,22 @@ select NULL::derived::base;
777779

778780
(1 row)
779781

782+
-- remove redundant conversions.
783+
explain (verbose on, costs off) select row(i, b)::more_derived::derived::base from more_derived;
784+
QUERY PLAN
785+
-------------------------------------------
786+
Seq Scan on public.more_derived
787+
Output: (ROW(i, b)::more_derived)::base
788+
(2 rows)
789+
790+
explain (verbose on, costs off) select (1, 2)::more_derived::derived::base;
791+
QUERY PLAN
792+
-----------------------
793+
Result
794+
Output: '(1)'::base
795+
(2 rows)
796+
797+
drop table more_derived;
780798
drop table derived;
781799
drop table base;
782800
create table p1(ff1 int);

src/test/regress/sql/inherit.sql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,9 +237,14 @@ drop table p1 cascade;
237237
-- tables. See the pgsql-hackers thread beginning Dec. 4/04
238238
create table base (i integer);
239239
create table derived () inherits (base);
240+
create table more_derived (like derived, b int) inherits (derived);
240241
insert into derived (i) values (0);
241242
select derived::base from derived;
242243
select NULL::derived::base;
244+
-- remove redundant conversions.
245+
explain (verbose on, costs off) select row(i, b)::more_derived::derived::base from more_derived;
246+
explain (verbose on, costs off) select (1, 2)::more_derived::derived::base;
247+
drop table more_derived;
243248
drop table derived;
244249
drop table base;
245250

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