aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/optimizer/util/clauses.c46
-rw-r--r--src/test/regress/expected/inherit.out18
-rw-r--r--src/test/regress/sql/inherit.sql5
3 files changed, 69 insertions, 0 deletions
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 21bf5dea9c3..8df369315bf 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -3716,6 +3716,52 @@ eval_const_expressions_mutator(Node *node,
context);
}
break;
+ case T_ConvertRowtypeExpr:
+ {
+ ConvertRowtypeExpr *cre = castNode(ConvertRowtypeExpr, node);
+ Node *arg;
+ ConvertRowtypeExpr *newcre;
+
+ arg = eval_const_expressions_mutator((Node *) cre->arg,
+ context);
+
+ newcre = makeNode(ConvertRowtypeExpr);
+ newcre->resulttype = cre->resulttype;
+ newcre->convertformat = cre->convertformat;
+ newcre->location = cre->location;
+
+ /*
+ * In case of a nested ConvertRowtypeExpr, we can convert the
+ * leaf row directly to the topmost row format without any
+ * intermediate conversions. (This works because
+ * ConvertRowtypeExpr is used only for child->parent
+ * conversion in inheritance trees, which works by exact match
+ * of column name, and a column absent in an intermediate
+ * result can't be present in the final result.)
+ *
+ * No need to check more than one level deep, because the
+ * above recursion will have flattened anything else.
+ */
+ if (arg != NULL && IsA(arg, ConvertRowtypeExpr))
+ {
+ ConvertRowtypeExpr *argcre = (ConvertRowtypeExpr *) arg;
+
+ arg = (Node *) argcre->arg;
+
+ /*
+ * Make sure an outer implicit conversion can't hide an
+ * inner explicit one.
+ */
+ if (newcre->convertformat == COERCE_IMPLICIT_CAST)
+ newcre->convertformat = argcre->convertformat;
+ }
+
+ newcre->arg = (Expr *) arg;
+
+ if (arg != NULL && IsA(arg, Const))
+ return ece_evaluate_expr((Node *) newcre);
+ return (Node *) newcre;
+ }
default:
break;
}
diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out
index d768e5df2c0..1e00c849f38 100644
--- a/src/test/regress/expected/inherit.out
+++ b/src/test/regress/expected/inherit.out
@@ -764,6 +764,8 @@ NOTICE: drop cascades to table c1
-- tables. See the pgsql-hackers thread beginning Dec. 4/04
create table base (i integer);
create table derived () inherits (base);
+create table more_derived (like derived, b int) inherits (derived);
+NOTICE: merging column "i" with inherited definition
insert into derived (i) values (0);
select derived::base from derived;
derived
@@ -777,6 +779,22 @@ select NULL::derived::base;
(1 row)
+-- remove redundant conversions.
+explain (verbose on, costs off) select row(i, b)::more_derived::derived::base from more_derived;
+ QUERY PLAN
+-------------------------------------------
+ Seq Scan on public.more_derived
+ Output: (ROW(i, b)::more_derived)::base
+(2 rows)
+
+explain (verbose on, costs off) select (1, 2)::more_derived::derived::base;
+ QUERY PLAN
+-----------------------
+ Result
+ Output: '(1)'::base
+(2 rows)
+
+drop table more_derived;
drop table derived;
drop table base;
create table p1(ff1 int);
diff --git a/src/test/regress/sql/inherit.sql b/src/test/regress/sql/inherit.sql
index e8b6448f3c8..afc72f47bc8 100644
--- a/src/test/regress/sql/inherit.sql
+++ b/src/test/regress/sql/inherit.sql
@@ -237,9 +237,14 @@ drop table p1 cascade;
-- tables. See the pgsql-hackers thread beginning Dec. 4/04
create table base (i integer);
create table derived () inherits (base);
+create table more_derived (like derived, b int) inherits (derived);
insert into derived (i) values (0);
select derived::base from derived;
select NULL::derived::base;
+-- remove redundant conversions.
+explain (verbose on, costs off) select row(i, b)::more_derived::derived::base from more_derived;
+explain (verbose on, costs off) select (1, 2)::more_derived::derived::base;
+drop table more_derived;
drop table derived;
drop table base;