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

+46
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

+18
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

+5
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)