Thanks for the review.

On 2017/08/03 13:54, Amit Khandekar wrote:
> On 2 August 2017 at 11:51, Amit Langote wrote:
>> On 2017/08/02 1:33, Amit Khandekar wrote:
>>> Instead of callers of map_partition_varattnos() reporting error, we
>>> can have map_partition_varattnos() itself report error. Instead of the
>>> found_whole_row parameter of map_partition_varattnos(), we can have
>>> error_on_whole_row parameter. So callers who don't expect whole row,
>>> would pass error_on_whole_row=true to map_partition_varattnos(). This
>>> will simplify the resultant code a bit.
>>
>> So, I think it's only the callers of
>> map_partition_varattnos() who know whether finding whole-row vars is an
>> error and *what kind* of error.
> 
> Ok. Got it. Thanks for the explanation.
> 
> How about making found_whole_row as an optional parameter ?
> map_partition_varattnos() would populate it only if its not NULL. This
> way, callers who don't bother about whether it is found or not don't
> have to declare a variable and pass its address. In current code,
> ExecInitModifyTable() is the one who has to declare found_whole_row
> without needing it.

Sure, done.  But while implementing that, I avoided changing anything in
map_variable_attnos(), such as adding a check for not-NULLness of
found_whole_row.  The only check added is in map_partition_varattnos().

Attached updated patches.

Thanks,
Amit
From 00a46ef3cfac3b3b197ccf39b8749f06d0d942ad Mon Sep 17 00:00:00 2001
From: amit <amitlangot...@gmail.com>
Date: Wed, 26 Jul 2017 16:45:46 +0900
Subject: [PATCH 1/2] Fix map_partition_varattnos to not error on
 found_whole_row

It was designed assuming that the expressions passed to it can never
contain whole-row vars, but it's wrong since it's called from places
that pass it WCO constraint expressions and RETURNING target list
expressions, which can very well contain whole-row vars.

Move the responsibility of error'ing out to the callers, because they
are in position to know that finding whole-row vars is an error
condition.

Adds test in insert.sql and updatable_views.sql.

Reported by: Rajkumar Raghuwanshi
Report: 
https://postgr.es/m/CAKcux6%3Dz38gH4K6YAFi%2BYvo5tHTwBL4tam4VM33CAPZ5dDMk1Q%40mail.gmail.com
---
 src/backend/catalog/partition.c               | 17 +++++++++++------
 src/backend/commands/tablecmds.c              |  8 +++++++-
 src/backend/executor/nodeModifyTable.c        | 14 ++++++++++----
 src/include/catalog/partition.h               |  3 ++-
 src/test/regress/expected/insert.out          | 10 ++++++++++
 src/test/regress/expected/updatable_views.out | 10 ++++++++++
 src/test/regress/sql/insert.sql               |  6 ++++++
 src/test/regress/sql/updatable_views.sql      |  9 +++++++++
 8 files changed, 65 insertions(+), 12 deletions(-)

diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c
index 9d50efb6a0..5891af9cf2 100644
--- a/src/backend/catalog/partition.c
+++ b/src/backend/catalog/partition.c
@@ -904,10 +904,11 @@ get_qual_from_partbound(Relation rel, Relation parent,
  */
 List *
 map_partition_varattnos(List *expr, int target_varno,
-                                               Relation partrel, Relation 
parent)
+                                               Relation partrel, Relation 
parent,
+                                               bool *found_whole_row)
 {
        AttrNumber *part_attnos;
-       bool            found_whole_row;
+       bool            my_found_whole_row;
 
        if (expr == NIL)
                return NIL;
@@ -919,10 +920,9 @@ map_partition_varattnos(List *expr, int target_varno,
                                                                                
target_varno, 0,
                                                                                
part_attnos,
                                                                                
RelationGetDescr(parent)->natts,
-                                                                               
&found_whole_row);
-       /* There can never be a whole-row reference here */
+                                                                               
&my_found_whole_row);
        if (found_whole_row)
-               elog(ERROR, "unexpected whole-row reference found in partition 
key");
+               *found_whole_row = my_found_whole_row;
 
        return expr;
 }
@@ -1783,6 +1783,7 @@ generate_partition_qual(Relation rel)
        List       *my_qual = NIL,
                           *result = NIL;
        Relation        parent;
+       bool            found_whole_row;
 
        /* Guard against stack overflow due to overly deep partition tree */
        check_stack_depth();
@@ -1825,7 +1826,11 @@ generate_partition_qual(Relation rel)
         * in it to bear this relation's attnos. It's safe to assume varno = 1
         * here.
         */
-       result = map_partition_varattnos(result, 1, rel, parent);
+       result = map_partition_varattnos(result, 1, rel, parent,
+                                                                        
&found_whole_row);
+       /* There can never be a whole-row reference here */
+       if (found_whole_row)
+               elog(ERROR, "unexpected whole-row reference found in partition 
key");
 
        /* Save a copy in the relcache */
        oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index bb00858ad1..cc5d3d6faf 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -13713,6 +13713,7 @@ ATExecAttachPartition(List **wqueue, Relation rel, 
PartitionCmd *cmd)
                        Oid                     part_relid = lfirst_oid(lc);
                        Relation        part_rel;
                        Expr       *constr;
+                       bool            found_whole_row;
 
                        /* Lock already taken */
                        if (part_relid != RelationGetRelid(attachRel))
@@ -13738,7 +13739,12 @@ ATExecAttachPartition(List **wqueue, Relation rel, 
PartitionCmd *cmd)
                        constr = linitial(partConstraint);
                        tab->partition_constraint = (Expr *)
                                map_partition_varattnos((List *) constr, 1,
-                                                                               
part_rel, rel);
+                                                                               
part_rel, rel,
+                                                                               
&found_whole_row);
+                       /* There can never be a whole-row reference here */
+                       if (found_whole_row)
+                               elog(ERROR, "unexpected whole-row reference 
found in partition key");
+
                        /* keep our lock until commit */
                        if (part_rel != attachRel)
                                heap_close(part_rel, NoLock);
diff --git a/src/backend/executor/nodeModifyTable.c 
b/src/backend/executor/nodeModifyTable.c
index 0dde0ed6eb..361241a6ce 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -1993,10 +1993,13 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, 
int eflags)
                        List       *wcoExprs = NIL;
                        ListCell   *ll;
 
-                       /* varno = node->nominalRelation */
+                       /*
+                        * We are passing node->nominalRelation as the varno.  
wcoList
+                        * might contain whole-row vars which is legal.
+                        */
                        mapped_wcoList = map_partition_varattnos(wcoList,
                                                                                
                         node->nominalRelation,
-                                                                               
                         partrel, rel);
+                                                                               
                         partrel, rel, NULL);
                        foreach(ll, mapped_wcoList)
                        {
                                WithCheckOption *wco = 
castNode(WithCheckOption, lfirst(ll));
@@ -2066,10 +2069,13 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, 
int eflags)
                        Relation        partrel = 
resultRelInfo->ri_RelationDesc;
                        List       *rlist;
 
-                       /* varno = node->nominalRelation */
+                       /*
+                        * We are passing node->nominalRelation as the varno.
+                        * returningList might contain wholerow vars which is 
legal.
+                        */
                        rlist = map_partition_varattnos(returningList,
                                                                                
        node->nominalRelation,
-                                                                               
        partrel, rel);
+                                                                               
        partrel, rel, NULL);
                        resultRelInfo->ri_projectReturning =
                                ExecBuildProjectionInfo(rlist, econtext, slot, 
&mtstate->ps,
                                                                                
resultRelInfo->ri_RelationDesc->rd_att);
diff --git a/src/include/catalog/partition.h b/src/include/catalog/partition.h
index f10879a162..434ded37d7 100644
--- a/src/include/catalog/partition.h
+++ b/src/include/catalog/partition.h
@@ -80,7 +80,8 @@ extern Oid    get_partition_parent(Oid relid);
 extern List *get_qual_from_partbound(Relation rel, Relation parent,
                                                PartitionBoundSpec *spec);
 extern List *map_partition_varattnos(List *expr, int target_varno,
-                                               Relation partrel, Relation 
parent);
+                                               Relation partrel, Relation 
parent,
+                                               bool *found_whole_row);
 extern List *RelationGetPartitionQual(Relation rel);
 extern Expr *get_partition_qual_relid(Oid relid);
 
diff --git a/src/test/regress/expected/insert.out 
b/src/test/regress/expected/insert.out
index 0dcc86fef4..b642de39d5 100644
--- a/src/test/regress/expected/insert.out
+++ b/src/test/regress/expected/insert.out
@@ -659,3 +659,13 @@ select tableoid::regclass, * from mcrparted order by a, b;
 (11 rows)
 
 drop table mcrparted;
+-- check that wholerow vars in the RETUNING list work with partitioned tables
+create table returningwrtest (a int) partition by list (a);
+create table returningwrtest1 partition of returningwrtest for values in (1);
+insert into returningwrtest values (1) returning returningwrtest;
+ returningwrtest 
+-----------------
+ (1)
+(1 row)
+
+drop table returningwrtest;
diff --git a/src/test/regress/expected/updatable_views.out 
b/src/test/regress/expected/updatable_views.out
index eab5c0334c..51a21f10c2 100644
--- a/src/test/regress/expected/updatable_views.out
+++ b/src/test/regress/expected/updatable_views.out
@@ -2428,3 +2428,13 @@ ERROR:  new row violates check option for view "ptv_wco"
 DETAIL:  Failing row contains (1, 2, null).
 drop view ptv, ptv_wco;
 drop table pt, pt1, pt11;
+-- check that wholerow vars appearing in WITH CHECK OPTION constraint 
expressions
+-- work fine with partitioned tables
+create table wcowrtest (a int) partition by list (a);
+create table wcowrtest1 partition of wcowrtest for values in (1);
+create view wcowrtest_v as select * from wcowrtest where wcowrtest = 
'(2)'::wcowrtest with check option;
+insert into wcowrtest_v values (1);
+ERROR:  new row violates check option for view "wcowrtest_v"
+DETAIL:  Failing row contains (1).
+drop view wcowrtest_v;
+drop table wcowrtest;
diff --git a/src/test/regress/sql/insert.sql b/src/test/regress/sql/insert.sql
index 6adf25da40..2eff832e59 100644
--- a/src/test/regress/sql/insert.sql
+++ b/src/test/regress/sql/insert.sql
@@ -399,3 +399,9 @@ insert into mcrparted values ('aaa', 0), ('b', 0), ('bz', 
10), ('c', -10),
     ('commons', 0), ('d', -10), ('e', 0);
 select tableoid::regclass, * from mcrparted order by a, b;
 drop table mcrparted;
+
+-- check that wholerow vars in the RETUNING list work with partitioned tables
+create table returningwrtest (a int) partition by list (a);
+create table returningwrtest1 partition of returningwrtest for values in (1);
+insert into returningwrtest values (1) returning returningwrtest;
+drop table returningwrtest;
diff --git a/src/test/regress/sql/updatable_views.sql 
b/src/test/regress/sql/updatable_views.sql
index 2ede44c02b..af8499a019 100644
--- a/src/test/regress/sql/updatable_views.sql
+++ b/src/test/regress/sql/updatable_views.sql
@@ -1141,3 +1141,12 @@ create view ptv_wco as select * from pt where a = 0 with 
check option;
 insert into ptv_wco values (1, 2);
 drop view ptv, ptv_wco;
 drop table pt, pt1, pt11;
+
+-- check that wholerow vars appearing in WITH CHECK OPTION constraint 
expressions
+-- work fine with partitioned tables
+create table wcowrtest (a int) partition by list (a);
+create table wcowrtest1 partition of wcowrtest for values in (1);
+create view wcowrtest_v as select * from wcowrtest where wcowrtest = 
'(2)'::wcowrtest with check option;
+insert into wcowrtest_v values (1);
+drop view wcowrtest_v;
+drop table wcowrtest;
-- 
2.11.0

From f2703383d3ddff50b4325f5686011b20a486aa02 Mon Sep 17 00:00:00 2001
From: amit <amitlangot...@gmail.com>
Date: Mon, 31 Jul 2017 17:48:07 +0900
Subject: [PATCH 2/2] Teach map_variable_attnos_mutator to convert whole-row
 Vars

Partitioning code that uses it requires it.
---
 src/backend/catalog/partition.c               |  5 ++-
 src/backend/commands/tablecmds.c              |  4 +--
 src/backend/executor/nodeModifyTable.c        | 10 ++----
 src/backend/parser/parse_utilcmd.c            |  6 ++--
 src/backend/rewrite/rewriteManip.c            | 50 ++++++++++++++++++++-------
 src/include/rewrite/rewriteManip.h            |  2 +-
 src/include/utils/rel.h                       |  7 ++++
 src/test/regress/expected/insert.out          | 10 ++++++
 src/test/regress/expected/updatable_views.out | 20 +++++++++--
 src/test/regress/sql/insert.sql               |  6 ++++
 src/test/regress/sql/updatable_views.sql      | 22 ++++++++++--
 11 files changed, 111 insertions(+), 31 deletions(-)

diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c
index 5891af9cf2..889d9635bc 100644
--- a/src/backend/catalog/partition.c
+++ b/src/backend/catalog/partition.c
@@ -909,6 +909,7 @@ map_partition_varattnos(List *expr, int target_varno,
 {
        AttrNumber *part_attnos;
        bool            my_found_whole_row;
+       Oid             to_rowtype;
 
        if (expr == NIL)
                return NIL;
@@ -916,11 +917,13 @@ map_partition_varattnos(List *expr, int target_varno,
        part_attnos = convert_tuples_by_name_map(RelationGetDescr(partrel),
                                                                                
         RelationGetDescr(parent),
                                                                                
         gettext_noop("could not convert row type"));
+
+       to_rowtype = RelationGetRelType(partrel);
        expr = (List *) map_variable_attnos((Node *) expr,
                                                                                
target_varno, 0,
                                                                                
part_attnos,
                                                                                
RelationGetDescr(parent)->natts,
-                                                                               
&my_found_whole_row);
+                                                                               
&my_found_whole_row, to_rowtype);
        if (found_whole_row)
                *found_whole_row = my_found_whole_row;
 
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index cc5d3d6faf..86cefe4696 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1989,7 +1989,7 @@ MergeAttributes(List *schema, List *supers, char 
relpersistence,
                                expr = 
map_variable_attnos(stringToNode(check[i].ccbin),
                                                                                
   1, 0,
                                                                                
   newattno, tupleDesc->natts,
-                                                                               
   &found_whole_row);
+                                                                               
   &found_whole_row, InvalidOid);
 
                                /*
                                 * For the moment we have to reject whole-row 
variables. We
@@ -8874,7 +8874,7 @@ ATPrepAlterColumnType(List **wqueue,
                                        map_variable_attnos(def->cooked_default,
                                                                                
1, 0,
                                                                                
attmap, RelationGetDescr(rel)->natts,
-                                                                               
&found_whole_row);
+                                                                               
&found_whole_row, InvalidOid);
                                if (found_whole_row)
                                        ereport(ERROR,
                                                        
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
diff --git a/src/backend/executor/nodeModifyTable.c 
b/src/backend/executor/nodeModifyTable.c
index 361241a6ce..435aed3b8b 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -1993,10 +1993,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, 
int eflags)
                        List       *wcoExprs = NIL;
                        ListCell   *ll;
 
-                       /*
-                        * We are passing node->nominalRelation as the varno.  
wcoList
-                        * might contain whole-row vars which is legal.
-                        */
+                       /* varno = node->nominalRelation */
                        mapped_wcoList = map_partition_varattnos(wcoList,
                                                                                
                         node->nominalRelation,
                                                                                
                         partrel, rel, NULL);
@@ -2069,10 +2066,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, 
int eflags)
                        Relation        partrel = 
resultRelInfo->ri_RelationDesc;
                        List       *rlist;
 
-                       /*
-                        * We are passing node->nominalRelation as the varno.
-                        * returningList might contain wholerow vars which is 
legal.
-                        */
+                       /* varno = node->nominalRelation */
                        rlist = map_partition_varattnos(returningList,
                                                                                
        node->nominalRelation,
                                                                                
        partrel, rel, NULL);
diff --git a/src/backend/parser/parse_utilcmd.c 
b/src/backend/parser/parse_utilcmd.c
index 9f37f1b920..f2f0ea540b 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -1107,7 +1107,7 @@ transformTableLikeClause(CreateStmtContext *cxt, 
TableLikeClause *table_like_cla
                        ccbin_node = map_variable_attnos(stringToNode(ccbin),
                                                                                
         1, 0,
                                                                                
         attmap, tupleDesc->natts,
-                                                                               
         &found_whole_row);
+                                                                               
         &found_whole_row, InvalidOid);
 
                        /*
                         * We reject whole-row variables because the whole 
point of LIKE
@@ -1463,7 +1463,7 @@ generateClonedIndexStmt(CreateStmtContext *cxt, Relation 
source_idx,
                        indexkey = map_variable_attnos(indexkey,
                                                                                
   1, 0,
                                                                                
   attmap, attmap_length,
-                                                                               
   &found_whole_row);
+                                                                               
   &found_whole_row, InvalidOid);
 
                        /* As in transformTableLikeClause, reject whole-row 
variables */
                        if (found_whole_row)
@@ -1539,7 +1539,7 @@ generateClonedIndexStmt(CreateStmtContext *cxt, Relation 
source_idx,
                pred_tree = map_variable_attnos(pred_tree,
                                                                                
1, 0,
                                                                                
attmap, attmap_length,
-                                                                               
&found_whole_row);
+                                                                               
&found_whole_row, InvalidOid);
 
                /* As in transformTableLikeClause, reject whole-row variables */
                if (found_whole_row)
diff --git a/src/backend/rewrite/rewriteManip.c 
b/src/backend/rewrite/rewriteManip.c
index b89b435da0..bd3129b7cd 100644
--- a/src/backend/rewrite/rewriteManip.c
+++ b/src/backend/rewrite/rewriteManip.c
@@ -1202,15 +1202,18 @@ replace_rte_variables_mutator(Node *node,
  * A zero in the mapping array represents a dropped column, which should not
  * appear in the expression.
  *
- * If the expression tree contains a whole-row Var for the target RTE,
- * the Var is not changed but *found_whole_row is returned as TRUE.
- * For most callers this is an error condition, but we leave it to the caller
- * to report the error so that useful context can be provided.  (In some
- * usages it would be appropriate to modify the Var's vartype and insert a
- * ConvertRowtypeExpr node to map back to the original vartype.  We might
- * someday extend this function's API to support that.  For now, the only
- * concession to that future need is that this function is a tree mutator
- * not just a walker.)
+ * Depending on the caller, whole-row Vars in the expression tree are
+ * converted if the necessary information is provided (see below.)  If the
+ * caller cannot provide the information, it might mean that finding a
+ * whole-row Var in the first place is an error.  In that case, we let the
+ * caller know that a whole-row Var was found by returning *found_whole_row
+ * as TRUE, which the caller then can report as an error by providing useful
+ * context information.
+ *
+ * When the information necessary to convert whole-row Vars is present, we
+ * substitute the Var's vartype (replace by to_rowtype) and add a
+ * ConvertRowtypeExpr node to map back to the original vartype.  Currently,
+ * only map_partition_varattnos() requests conversion of whole-row Vars.
  *
  * This could be built using replace_rte_variables and a callback function,
  * but since we don't ever need to insert sublinks, replace_rte_variables is
@@ -1224,6 +1227,8 @@ typedef struct
        const AttrNumber *attno_map;    /* map array for user attnos */
        int                     map_length;             /* number of entries in 
attno_map[] */
        bool       *found_whole_row;    /* output flag */
+       /* Target type when converting whole-row vars */
+       Oid                     to_rowtype;
 } map_variable_attnos_context;
 
 static Node *
@@ -1240,10 +1245,9 @@ map_variable_attnos_mutator(Node *node,
                        var->varlevelsup == context->sublevels_up)
                {
                        /* Found a matching variable, make the substitution */
-                       Var                *newvar = (Var *) 
palloc(sizeof(Var));
+                       Var                *newvar = copyObject(var);
                        int                     attno = var->varattno;
 
-                       *newvar = *var;
                        if (attno > 0)
                        {
                                /* user-defined column, replace attno */
@@ -1257,6 +1261,27 @@ map_variable_attnos_mutator(Node *node,
                        {
                                /* whole-row variable, warn caller */
                                *(context->found_whole_row) = true;
+
+                               /* If the callers expects us to convert the 
same, do so. */
+                               if (OidIsValid(context->to_rowtype))
+                               {
+                                       ConvertRowtypeExpr *r;
+
+                                       /* Var itself is converted to the 
requested rowtype. */
+                                       newvar->vartype = context->to_rowtype;
+
+                                       /*
+                                        * And a conversion step on top to 
convert back to the
+                                        * original type.
+                                        */
+                                       r = makeNode(ConvertRowtypeExpr);
+                                       r->arg = (Expr *) newvar;
+                                       r->resulttype = var->vartype;
+                                       r->convertformat = COERCE_IMPLICIT_CAST;
+                                       r->location = -1;
+
+                                       return (Node *) r;
+                               }
                        }
                        return (Node *) newvar;
                }
@@ -1283,7 +1308,7 @@ Node *
 map_variable_attnos(Node *node,
                                        int target_varno, int sublevels_up,
                                        const AttrNumber *attno_map, int 
map_length,
-                                       bool *found_whole_row)
+                                       bool *found_whole_row, Oid to_rowtype)
 {
        map_variable_attnos_context context;
 
@@ -1291,6 +1316,7 @@ map_variable_attnos(Node *node,
        context.sublevels_up = sublevels_up;
        context.attno_map = attno_map;
        context.map_length = map_length;
+       context.to_rowtype = to_rowtype;
        context.found_whole_row = found_whole_row;
 
        *found_whole_row = false;
diff --git a/src/include/rewrite/rewriteManip.h 
b/src/include/rewrite/rewriteManip.h
index 282ff9967f..56f9bb8013 100644
--- a/src/include/rewrite/rewriteManip.h
+++ b/src/include/rewrite/rewriteManip.h
@@ -72,7 +72,7 @@ extern Node *replace_rte_variables_mutator(Node *node,
 extern Node *map_variable_attnos(Node *node,
                                        int target_varno, int sublevels_up,
                                        const AttrNumber *attno_map, int 
map_length,
-                                       bool *found_whole_row);
+                                       bool *found_whole_row, Oid to_rowtype);
 
 extern Node *ReplaceVarsFromTargetList(Node *node,
                                                  int target_varno, int 
sublevels_up,
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index 4bc61e5380..bd5428f72f 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -444,6 +444,13 @@ typedef struct ViewOptions
        ((relation)->rd_rel->relnamespace)
 
 /*
+ * RelationGetRelType
+ *             Returns the rel's pg_type OID.
+ */
+#define RelationGetRelType(relation) \
+       ((relation)->rd_rel->reltype)
+
+/*
  * RelationIsMapped
  *             True if the relation uses the relfilenode map.
  *
diff --git a/src/test/regress/expected/insert.out 
b/src/test/regress/expected/insert.out
index b642de39d5..38b364d10f 100644
--- a/src/test/regress/expected/insert.out
+++ b/src/test/regress/expected/insert.out
@@ -668,4 +668,14 @@ insert into returningwrtest values (1) returning 
returningwrtest;
  (1)
 (1 row)
 
+alter table returningwrtest add b text;
+create table returningwrtest2 (b text, c int, a int);
+alter table returningwrtest2 drop c;
+alter table returningwrtest attach partition returningwrtest2 for values in 
(2);
+insert into returningwrtest values (2, 'foo') returning returningwrtest;
+ returningwrtest 
+-----------------
+ (2,foo)
+(1 row)
+
 drop table returningwrtest;
diff --git a/src/test/regress/expected/updatable_views.out 
b/src/test/regress/expected/updatable_views.out
index 51a21f10c2..2090a411fe 100644
--- a/src/test/regress/expected/updatable_views.out
+++ b/src/test/regress/expected/updatable_views.out
@@ -2436,5 +2436,21 @@ create view wcowrtest_v as select * from wcowrtest where 
wcowrtest = '(2)'::wcow
 insert into wcowrtest_v values (1);
 ERROR:  new row violates check option for view "wcowrtest_v"
 DETAIL:  Failing row contains (1).
-drop view wcowrtest_v;
-drop table wcowrtest;
+alter table wcowrtest add b text;
+create table wcowrtest2 (b text, c int, a int);
+alter table wcowrtest2 drop c;
+alter table wcowrtest attach partition wcowrtest2 for values in (2);
+create table sometable (a int, b text);
+insert into sometable values (1, 'a'), (2, 'b');
+create view wcowrtest_v2 as
+    select *
+      from wcowrtest r
+      where r in (select s from sometable s where r.a = s.a)
+with check option;
+-- WITH CHECK qual will be processed with wcowrtest2's
+-- rowtype after tuple-routing
+insert into wcowrtest_v2 values (2, 'no such row in sometable');
+ERROR:  new row violates check option for view "wcowrtest_v2"
+DETAIL:  Failing row contains (2, no such row in sometable).
+drop view wcowrtest_v, wcowrtest_v2;
+drop table wcowrtest, sometable;
diff --git a/src/test/regress/sql/insert.sql b/src/test/regress/sql/insert.sql
index 2eff832e59..f51d72484d 100644
--- a/src/test/regress/sql/insert.sql
+++ b/src/test/regress/sql/insert.sql
@@ -404,4 +404,10 @@ drop table mcrparted;
 create table returningwrtest (a int) partition by list (a);
 create table returningwrtest1 partition of returningwrtest for values in (1);
 insert into returningwrtest values (1) returning returningwrtest;
+
+alter table returningwrtest add b text;
+create table returningwrtest2 (b text, c int, a int);
+alter table returningwrtest2 drop c;
+alter table returningwrtest attach partition returningwrtest2 for values in 
(2);
+insert into returningwrtest values (2, 'foo') returning returningwrtest;
 drop table returningwrtest;
diff --git a/src/test/regress/sql/updatable_views.sql 
b/src/test/regress/sql/updatable_views.sql
index af8499a019..a6ba5aad9e 100644
--- a/src/test/regress/sql/updatable_views.sql
+++ b/src/test/regress/sql/updatable_views.sql
@@ -1148,5 +1148,23 @@ create table wcowrtest (a int) partition by list (a);
 create table wcowrtest1 partition of wcowrtest for values in (1);
 create view wcowrtest_v as select * from wcowrtest where wcowrtest = 
'(2)'::wcowrtest with check option;
 insert into wcowrtest_v values (1);
-drop view wcowrtest_v;
-drop table wcowrtest;
+
+alter table wcowrtest add b text;
+create table wcowrtest2 (b text, c int, a int);
+alter table wcowrtest2 drop c;
+alter table wcowrtest attach partition wcowrtest2 for values in (2);
+
+create table sometable (a int, b text);
+insert into sometable values (1, 'a'), (2, 'b');
+create view wcowrtest_v2 as
+    select *
+      from wcowrtest r
+      where r in (select s from sometable s where r.a = s.a)
+with check option;
+
+-- WITH CHECK qual will be processed with wcowrtest2's
+-- rowtype after tuple-routing
+insert into wcowrtest_v2 values (2, 'no such row in sometable');
+
+drop view wcowrtest_v, wcowrtest_v2;
+drop table wcowrtest, sometable;
-- 
2.11.0

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to