I have applied the attached patch to HEAD in order to fix the problems
discussed in this thread:
http://archives.postgresql.org/pgsql-hackers/2004-12/msg00187.php

                        regards, tom lane
Index: src/backend/executor/execQual.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/executor/execQual.c,v
retrieving revision 1.169
diff -c -r1.169 execQual.c
*** src/backend/executor/execQual.c     22 Sep 2004 17:41:50 -0000      1.169
--- src/backend/executor/execQual.c     11 Dec 2004 16:26:02 -0000
***************
*** 87,92 ****
--- 87,95 ----
                   bool *isNull, ExprDoneCond *isDone);
  static Datum ExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext,
                        bool *isNull, ExprDoneCond *isDone);
+ static Datum ExecEvalConvertRowtype(ConvertRowtypeExprState *cstate,
+                                                                       
ExprContext *econtext,
+                                                                       bool 
*isNull, ExprDoneCond *isDone);
  static Datum ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
                         bool *isNull, ExprDoneCond *isDone);
  static Datum ExecEvalCaseTestExpr(ExprState *exprstate,
***************
*** 428,434 ****
   *
   *            Returns a Datum whose value is the value of a range
   *            variable with respect to given expression context.
!  * ---------------------------------------------------------------- */
  static Datum
  ExecEvalVar(ExprState *exprstate, ExprContext *econtext,
                        bool *isNull, ExprDoneCond *isDone)
--- 431,438 ----
   *
   *            Returns a Datum whose value is the value of a range
   *            variable with respect to given expression context.
!  * ----------------------------------------------------------------
!  */
  static Datum
  ExecEvalVar(ExprState *exprstate, ExprContext *econtext,
                        bool *isNull, ExprDoneCond *isDone)
***************
*** 1844,1849 ****
--- 1848,1922 ----
        return BoolGetDatum(!AnyNull);
  }
  
+ /* ----------------------------------------------------------------
+  *            ExecEvalConvertRowtype
+  *
+  *            Evaluate a rowtype coercion operation.  This may require
+  *            rearranging field positions.
+  * ----------------------------------------------------------------
+  */
+ static Datum
+ ExecEvalConvertRowtype(ConvertRowtypeExprState *cstate,
+                                          ExprContext *econtext,
+                                          bool *isNull, ExprDoneCond *isDone)
+ {
+       HeapTuple       result;
+       Datum           tupDatum;
+       HeapTupleHeader tuple;
+       HeapTupleData tmptup;
+       AttrNumber *attrMap = cstate->attrMap;
+       Datum      *invalues = cstate->invalues;
+       char       *innulls = cstate->innulls;
+       Datum      *outvalues = cstate->outvalues;
+       char       *outnulls = cstate->outnulls;
+       int                     i;
+       int                     outnatts = cstate->outdesc->natts;
+ 
+       tupDatum = ExecEvalExpr(cstate->arg, econtext, isNull, isDone);
+ 
+       /* this test covers the isDone exception too: */
+       if (*isNull)
+               return tupDatum;
+ 
+       tuple = DatumGetHeapTupleHeader(tupDatum);
+ 
+       Assert(HeapTupleHeaderGetTypeId(tuple) == cstate->indesc->tdtypeid);
+       Assert(HeapTupleHeaderGetTypMod(tuple) == cstate->indesc->tdtypmod);
+ 
+       /*
+        * heap_deformtuple needs a HeapTuple not a bare HeapTupleHeader.
+        */
+       tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
+       tmptup.t_data = tuple;
+ 
+       /*
+        * Extract all the values of the old tuple, offsetting the arrays
+        * so that invalues[0] is NULL and invalues[1] is the first
+        * source attribute; this exactly matches the numbering convention
+        * in attrMap.
+        */
+       heap_deformtuple(&tmptup, cstate->indesc, invalues + 1, innulls + 1);
+       invalues[0] = (Datum) 0;
+       innulls[0] = 'n';
+ 
+       /*
+        * Transpose into proper fields of the new tuple.
+        */
+       for (i = 0; i < outnatts; i++)
+       {
+               int                     j = attrMap[i];
+ 
+               outvalues[i] = invalues[j];
+               outnulls[i] = innulls[j];
+       }
+ 
+       /*
+        * Now form the new tuple.
+        */
+       result = heap_formtuple(cstate->outdesc, outvalues, outnulls);
+ 
+       return HeapTupleGetDatum(result);
+ }
  
  /* ----------------------------------------------------------------
   *            ExecEvalCase
***************
*** 2969,2974 ****
--- 3042,3109 ----
                                state = (ExprState *) gstate;
                        }
                        break;
+               case T_ConvertRowtypeExpr:
+                       {
+                               ConvertRowtypeExpr *convert = 
(ConvertRowtypeExpr *) node;
+                               ConvertRowtypeExprState *cstate = 
makeNode(ConvertRowtypeExprState);
+                               int             i;
+                               int             n;
+ 
+                               cstate->xprstate.evalfunc = (ExprStateEvalFunc) 
ExecEvalConvertRowtype;
+                               cstate->arg = ExecInitExpr(convert->arg, 
parent);
+                               /* save copies of needed tuple descriptors */
+                               cstate->indesc = 
lookup_rowtype_tupdesc(exprType((Node *) convert->arg), -1);
+                               cstate->indesc = 
CreateTupleDescCopy(cstate->indesc);
+                               cstate->outdesc = 
lookup_rowtype_tupdesc(convert->resulttype, -1);
+                               cstate->outdesc = 
CreateTupleDescCopy(cstate->outdesc);
+                               /* prepare map from old to new attribute 
numbers */
+                               n = cstate->outdesc->natts;
+                               cstate->attrMap = (AttrNumber *) palloc0(n * 
sizeof(AttrNumber));
+                               for (i = 0; i < n; i++)
+                               {
+                                       Form_pg_attribute att = 
cstate->outdesc->attrs[i];
+                                       char       *attname;
+                                       Oid                     atttypid;
+                                       int32           atttypmod;
+                                       int                     j;
+ 
+                                       if (att->attisdropped)
+                                               continue;       /* attrMap[i] 
is already 0 */
+                                       attname = NameStr(att->attname);
+                                       atttypid = att->atttypid;
+                                       atttypmod = att->atttypmod;
+                                       for (j = 0; j < cstate->indesc->natts; 
j++)
+                                       {
+                                               att = cstate->indesc->attrs[j];
+                                               if (att->attisdropped)
+                                                       continue;
+                                               if (strcmp(attname, 
NameStr(att->attname)) == 0)
+                                               {
+                                                       /* Found it, check type 
*/
+                                                       if (atttypid != 
att->atttypid || atttypmod != att->atttypmod)
+                                                               elog(ERROR, 
"attribute \"%s\" of type %s does not match corresponding attribute of type %s",
+                                                                        
attname,
+                                                                        
format_type_be(cstate->indesc->tdtypeid),
+                                                                        
format_type_be(cstate->outdesc->tdtypeid));
+                                                       cstate->attrMap[i] = 
(AttrNumber) (j + 1);
+                                                       break;
+                                               }
+                                       }
+                                       if (cstate->attrMap[i] == 0)
+                                               elog(ERROR, "attribute \"%s\" 
of type %s does not exist",
+                                                        attname,
+                                                        
format_type_be(cstate->indesc->tdtypeid));
+                               }
+                               /* preallocate workspace for Datum arrays */
+                               n = cstate->indesc->natts + 1;  /* +1 for NULL 
*/
+                               cstate->invalues = (Datum *) palloc(n * 
sizeof(Datum));
+                               cstate->innulls = (char *) palloc(n * 
sizeof(char));
+                               n = cstate->outdesc->natts;
+                               cstate->outvalues = (Datum *) palloc(n * 
sizeof(Datum));
+                               cstate->outnulls = (char *) palloc(n * 
sizeof(char));
+                               state = (ExprState *) cstate;
+                       }
+                       break;
                case T_CaseExpr:
                        {
                                CaseExpr   *caseexpr = (CaseExpr *) node;
Index: src/backend/nodes/copyfuncs.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v
retrieving revision 1.293
diff -c -r1.293 copyfuncs.c
*** src/backend/nodes/copyfuncs.c       5 Nov 2004 19:15:59 -0000       1.293
--- src/backend/nodes/copyfuncs.c       11 Dec 2004 16:26:02 -0000
***************
*** 877,882 ****
--- 877,897 ----
  }
  
  /*
+  * _copyConvertRowtypeExpr
+  */
+ static ConvertRowtypeExpr *
+ _copyConvertRowtypeExpr(ConvertRowtypeExpr *from)
+ {
+       ConvertRowtypeExpr *newnode = makeNode(ConvertRowtypeExpr);
+ 
+       COPY_NODE_FIELD(arg);
+       COPY_SCALAR_FIELD(resulttype);
+       COPY_SCALAR_FIELD(convertformat);
+ 
+       return newnode;
+ }
+ 
+ /*
   * _copyCaseExpr
   */
  static CaseExpr *
***************
*** 2696,2701 ****
--- 2711,2719 ----
                case T_RelabelType:
                        retval = _copyRelabelType(from);
                        break;
+               case T_ConvertRowtypeExpr:
+                       retval = _copyConvertRowtypeExpr(from);
+                       break;
                case T_CaseExpr:
                        retval = _copyCaseExpr(from);
                        break;
Index: src/backend/nodes/equalfuncs.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v
retrieving revision 1.232
diff -c -r1.232 equalfuncs.c
*** src/backend/nodes/equalfuncs.c      5 Nov 2004 19:15:59 -0000       1.232
--- src/backend/nodes/equalfuncs.c      11 Dec 2004 16:26:02 -0000
***************
*** 381,386 ****
--- 381,404 ----
  }
  
  static bool
+ _equalConvertRowtypeExpr(ConvertRowtypeExpr *a, ConvertRowtypeExpr *b)
+ {
+       COMPARE_NODE_FIELD(arg);
+       COMPARE_SCALAR_FIELD(resulttype);
+ 
+       /*
+        * Special-case COERCE_DONTCARE, so that planner can build coercion
+        * nodes that are equal() to both explicit and implicit coercions.
+        */
+       if (a->convertformat != b->convertformat &&
+               a->convertformat != COERCE_DONTCARE &&
+               b->convertformat != COERCE_DONTCARE)
+               return false;
+ 
+       return true;
+ }
+ 
+ static bool
  _equalCaseExpr(CaseExpr *a, CaseExpr *b)
  {
        COMPARE_SCALAR_FIELD(casetype);
***************
*** 1844,1849 ****
--- 1862,1870 ----
                case T_RelabelType:
                        retval = _equalRelabelType(a, b);
                        break;
+               case T_ConvertRowtypeExpr:
+                       retval = _equalConvertRowtypeExpr(a, b);
+                       break;
                case T_CaseExpr:
                        retval = _equalCaseExpr(a, b);
                        break;
Index: src/backend/nodes/outfuncs.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v
retrieving revision 1.243
diff -c -r1.243 outfuncs.c
*** src/backend/nodes/outfuncs.c        29 Aug 2004 05:06:43 -0000      1.243
--- src/backend/nodes/outfuncs.c        11 Dec 2004 16:26:02 -0000
***************
*** 768,773 ****
--- 768,783 ----
  }
  
  static void
+ _outConvertRowtypeExpr(StringInfo str, ConvertRowtypeExpr *node)
+ {
+       WRITE_NODE_TYPE("CONVERTROWTYPEEXPR");
+ 
+       WRITE_NODE_FIELD(arg);
+       WRITE_OID_FIELD(resulttype);
+       WRITE_ENUM_FIELD(convertformat, CoercionForm);
+ }
+ 
+ static void
  _outCaseExpr(StringInfo str, CaseExpr *node)
  {
        WRITE_NODE_TYPE("CASE");
***************
*** 1728,1733 ****
--- 1738,1746 ----
                        case T_RelabelType:
                                _outRelabelType(str, obj);
                                break;
+                       case T_ConvertRowtypeExpr:
+                               _outConvertRowtypeExpr(str, obj);
+                               break;
                        case T_CaseExpr:
                                _outCaseExpr(str, obj);
                                break;
Index: src/backend/nodes/readfuncs.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v
retrieving revision 1.173
diff -c -r1.173 readfuncs.c
*** src/backend/nodes/readfuncs.c       29 Aug 2004 04:12:33 -0000      1.173
--- src/backend/nodes/readfuncs.c       11 Dec 2004 16:26:02 -0000
***************
*** 576,581 ****
--- 576,596 ----
  }
  
  /*
+  * _readConvertRowtypeExpr
+  */
+ static ConvertRowtypeExpr *
+ _readConvertRowtypeExpr(void)
+ {
+       READ_LOCALS(ConvertRowtypeExpr);
+ 
+       READ_NODE_FIELD(arg);
+       READ_OID_FIELD(resulttype);
+       READ_ENUM_FIELD(convertformat, CoercionForm);
+ 
+       READ_DONE();
+ }
+ 
+ /*
   * _readCaseExpr
   */
  static CaseExpr *
***************
*** 971,976 ****
--- 986,993 ----
                return_value = _readFieldStore();
        else if (MATCH("RELABELTYPE", 11))
                return_value = _readRelabelType();
+       else if (MATCH("CONVERTROWTYPEEXPR", 18))
+               return_value = _readConvertRowtypeExpr();
        else if (MATCH("CASE", 4))
                return_value = _readCaseExpr();
        else if (MATCH("WHEN", 4))
Index: src/backend/optimizer/prep/prepjointree.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/optimizer/prep/prepjointree.c,v
retrieving revision 1.23
diff -c -r1.23 prepjointree.c
*** src/backend/optimizer/prep/prepjointree.c   29 Aug 2004 05:06:44 -0000      
1.23
--- src/backend/optimizer/prep/prepjointree.c   11 Dec 2004 16:26:02 -0000
***************
*** 839,844 ****
--- 839,851 ----
  
                result = find_nonnullable_rels((Node *) expr->arg, top_level);
        }
+       else if (IsA(node, ConvertRowtypeExpr))
+       {
+               /* not clear this is useful, but it can't hurt */
+               ConvertRowtypeExpr *expr = (ConvertRowtypeExpr *) node;
+ 
+               result = find_nonnullable_rels((Node *) expr->arg, top_level);
+       }
        else if (IsA(node, NullTest))
        {
                NullTest   *expr = (NullTest *) node;
Index: src/backend/optimizer/prep/prepunion.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v
retrieving revision 1.117
diff -c -r1.117 prepunion.c
*** src/backend/optimizer/prep/prepunion.c      2 Oct 2004 22:39:47 -0000       
1.117
--- src/backend/optimizer/prep/prepunion.c      11 Dec 2004 16:26:03 -0000
***************
*** 40,45 ****
--- 40,47 ----
  {
        Index           old_rt_index;
        Index           new_rt_index;
+       Oid                     old_rel_type;
+       Oid                     new_rel_type;
        TupleDesc       old_tupdesc;
        TupleDesc       new_tupdesc;
        char       *old_rel_name;
***************
*** 826,831 ****
--- 828,835 ----
  
        context.old_rt_index = old_rt_index;
        context.new_rt_index = new_rt_index;
+       context.old_rel_type = oldrelation->rd_rel->reltype;
+       context.new_rel_type = newrelation->rd_rel->reltype;
        context.old_tupdesc = RelationGetDescr(oldrelation);
        context.new_tupdesc = RelationGetDescr(newrelation);
        context.old_rel_name = RelationGetRelationName(oldrelation);
***************
*** 910,959 ****
        return 0;                                       /* keep compiler quiet 
*/
  }
  
- /*
-  * Translate a whole-row Var to be correct for a child table.
-  *
-  * In general the child will not have a suitable field layout to be used
-  * directly, so we translate the simple whole-row Var into a ROW() construct.
-  */
- static Node *
- generate_whole_row(Var *var,
-                                  adjust_inherited_attrs_context *context)
- {
-       RowExpr    *rowexpr;
-       List       *fields = NIL;
-       int                     oldnatts = context->old_tupdesc->natts;
-       int                     i;
- 
-       for (i = 0; i < oldnatts; i++)
-       {
-               Form_pg_attribute att = context->old_tupdesc->attrs[i];
-               Var                *newvar;
- 
-               if (att->attisdropped)
-               {
-                       /*
-                        * can't use atttypid here, but it doesn't really 
matter what
-                        * type the Const claims to be.
-                        */
-                       newvar = (Var *) makeNullConst(INT4OID);
-               }
-               else
-                       newvar = makeVar(context->new_rt_index,
-                                                        
translate_inherited_attnum(i + 1, context),
-                                                        att->atttypid,
-                                                        att->atttypmod,
-                                                        0);
-               fields = lappend(fields, newvar);
-       }
-       rowexpr = makeNode(RowExpr);
-       rowexpr->args = fields;
-       rowexpr->row_typeid = var->vartype; /* report parent's rowtype */
-       rowexpr->row_format = COERCE_IMPLICIT_CAST;
- 
-       return (Node *) rowexpr;
- }
- 
  static Node *
  adjust_inherited_attrs_mutator(Node *node,
                                                           
adjust_inherited_attrs_context *context)
--- 914,919 ----
***************
*** 977,984 ****
                        }
                        else if (var->varattno == 0)
                        {
!                               /* expand whole-row reference into a ROW() 
construct */
!                               return generate_whole_row(var, context);
                        }
                        /* system attributes don't need any translation */
                }
--- 937,958 ----
                        }
                        else if (var->varattno == 0)
                        {
!                               /*
!                                * Whole-row Var: we need to insert a coercion 
step to convert
!                                * the tuple layout to the parent's rowtype.
!                                */
!                               if (context->old_rel_type != 
context->new_rel_type)
!                               {
!                                       ConvertRowtypeExpr *r = 
makeNode(ConvertRowtypeExpr);
! 
!                                       r->arg = (Expr *) var;
!                                       r->resulttype = context->old_rel_type;
!                                       r->convertformat = COERCE_IMPLICIT_CAST;
!                                       /* Make sure the Var node has the right 
type ID, too */
!                                       Assert(var->vartype == 
context->old_rel_type);
!                                       var->vartype = context->new_rel_type;
!                                       return (Node *) r;
!                               }
                        }
                        /* system attributes don't need any translation */
                }
Index: src/backend/optimizer/util/clauses.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v
retrieving revision 1.184
diff -c -r1.184 clauses.c
*** src/backend/optimizer/util/clauses.c        9 Nov 2004 21:42:53 -0000       
1.184
--- src/backend/optimizer/util/clauses.c        11 Dec 2004 16:26:03 -0000
***************
*** 1047,1052 ****
--- 1047,1059 ----
                if (r->relabelformat == COERCE_IMPLICIT_CAST)
                        return strip_implicit_coercions((Node *) r->arg);
        }
+       else if (IsA(node, ConvertRowtypeExpr))
+       {
+               ConvertRowtypeExpr *c = (ConvertRowtypeExpr *) node;
+ 
+               if (c->convertformat == COERCE_IMPLICIT_CAST)
+                       return strip_implicit_coercions((Node *) c->arg);
+       }
        else if (IsA(node, CoerceToDomain))
        {
                CoerceToDomain *c = (CoerceToDomain *) node;
***************
*** 1082,1092 ****
                return false;
        if (IsA(node, FuncExpr))
                ((FuncExpr *) node)->funcformat = COERCE_DONTCARE;
!       if (IsA(node, RelabelType))
                ((RelabelType *) node)->relabelformat = COERCE_DONTCARE;
!       if (IsA(node, RowExpr))
                ((RowExpr *) node)->row_format = COERCE_DONTCARE;
!       if (IsA(node, CoerceToDomain))
                ((CoerceToDomain *) node)->coercionformat = COERCE_DONTCARE;
        return expression_tree_walker(node, set_coercionform_dontcare_walker,
                                                                  context);
--- 1089,1101 ----
                return false;
        if (IsA(node, FuncExpr))
                ((FuncExpr *) node)->funcformat = COERCE_DONTCARE;
!       else if (IsA(node, RelabelType))
                ((RelabelType *) node)->relabelformat = COERCE_DONTCARE;
!       else if (IsA(node, ConvertRowtypeExpr))
!               ((ConvertRowtypeExpr *) node)->convertformat = COERCE_DONTCARE;
!       else if (IsA(node, RowExpr))
                ((RowExpr *) node)->row_format = COERCE_DONTCARE;
!       else if (IsA(node, CoerceToDomain))
                ((CoerceToDomain *) node)->coercionformat = COERCE_DONTCARE;
        return expression_tree_walker(node, set_coercionform_dontcare_walker,
                                                                  context);
***************
*** 2647,2652 ****
--- 2656,2663 ----
                        break;
                case T_RelabelType:
                        return walker(((RelabelType *) node)->arg, context);
+               case T_ConvertRowtypeExpr:
+                       return walker(((ConvertRowtypeExpr *) node)->arg, 
context);
                case T_CaseExpr:
                        {
                                CaseExpr   *caseexpr = (CaseExpr *) node;
***************
*** 3057,3062 ****
--- 3068,3083 ----
                                return (Node *) newnode;
                        }
                        break;
+               case T_ConvertRowtypeExpr:
+                       {
+                               ConvertRowtypeExpr *convexpr = 
(ConvertRowtypeExpr *) node;
+                               ConvertRowtypeExpr *newnode;
+ 
+                               FLATCOPY(newnode, convexpr, ConvertRowtypeExpr);
+                               MUTATE(newnode->arg, convexpr->arg, Expr *);
+                               return (Node *) newnode;
+                       }
+                       break;
                case T_CaseExpr:
                        {
                                CaseExpr   *caseexpr = (CaseExpr *) node;
Index: src/backend/parser/parse_coerce.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v
retrieving revision 2.124
diff -c -r2.124 parse_coerce.c
*** src/backend/parser/parse_coerce.c   6 Nov 2004 17:46:33 -0000       2.124
--- src/backend/parser/parse_coerce.c   11 Dec 2004 16:26:03 -0000
***************
*** 321,333 ****
        if (typeInheritsFrom(inputTypeId, targetTypeId))
        {
                /*
!                * Input class type is a subclass of target, so nothing to do 
---
!                * except relabel the type.  This is binary compatibility for
!                * complex types.
                 */
!               return (Node *) makeRelabelType((Expr *) node,
!                                                                               
targetTypeId, -1,
!                                                                               
cformat);
        }
        /* If we get here, caller blew it */
        elog(ERROR, "failed to find conversion function from %s to %s",
--- 321,336 ----
        if (typeInheritsFrom(inputTypeId, targetTypeId))
        {
                /*
!                * Input class type is a subclass of target, so generate an
!                * appropriate runtime conversion (removing unneeded columns
!                * and possibly rearranging the ones that are wanted).
                 */
!               ConvertRowtypeExpr *r = makeNode(ConvertRowtypeExpr);
! 
!               r->arg = (Expr *) node;
!               r->resulttype = targetTypeId;
!               r->convertformat = cformat;
!               return (Node *) r;
        }
        /* If we get here, caller blew it */
        elog(ERROR, "failed to find conversion function from %s to %s",
***************
*** 567,572 ****
--- 570,577 ----
                ((FuncExpr *) node)->funcformat = COERCE_IMPLICIT_CAST;
        else if (IsA(node, RelabelType))
                ((RelabelType *) node)->relabelformat = COERCE_IMPLICIT_CAST;
+       else if (IsA(node, ConvertRowtypeExpr))
+               ((ConvertRowtypeExpr *) node)->convertformat = 
COERCE_IMPLICIT_CAST;
        else if (IsA(node, RowExpr))
                ((RowExpr *) node)->row_format = COERCE_IMPLICIT_CAST;
        else if (IsA(node, CoerceToDomain))
Index: src/backend/parser/parse_expr.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v
retrieving revision 1.176
diff -c -r1.176 parse_expr.c
*** src/backend/parser/parse_expr.c     29 Aug 2004 05:06:44 -0000      1.176
--- src/backend/parser/parse_expr.c     11 Dec 2004 16:26:03 -0000
***************
*** 940,945 ****
--- 940,946 ----
                case T_FieldSelect:
                case T_FieldStore:
                case T_RelabelType:
+               case T_ConvertRowtypeExpr:
                case T_CaseTestExpr:
                case T_CoerceToDomain:
                case T_CoerceToDomainValue:
***************
*** 1406,1411 ****
--- 1407,1415 ----
                case T_RelabelType:
                        type = ((RelabelType *) expr)->resulttype;
                        break;
+               case T_ConvertRowtypeExpr:
+                       type = ((ConvertRowtypeExpr *) expr)->resulttype;
+                       break;
                case T_CaseExpr:
                        type = ((CaseExpr *) expr)->casetype;
                        break;
Index: src/backend/utils/adt/ruleutils.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v
retrieving revision 1.185
diff -c -r1.185 ruleutils.c
*** src/backend/utils/adt/ruleutils.c   5 Nov 2004 19:16:11 -0000       1.185
--- src/backend/utils/adt/ruleutils.c   11 Dec 2004 16:26:03 -0000
***************
*** 2622,2627 ****
--- 2622,2630 ----
                case T_RelabelType:
                        return isSimpleNode((Node *) ((RelabelType *) 
node)->arg,
                                                                node, 
prettyFlags);
+               case T_ConvertRowtypeExpr:
+                       return isSimpleNode((Node *) ((ConvertRowtypeExpr *) 
node)->arg,
+                                                               node, 
prettyFlags);
  
                case T_OpExpr:
                        {
***************
*** 3133,3138 ****
--- 3136,3165 ----
                        }
                        break;
  
+               case T_ConvertRowtypeExpr:
+                       {
+                               ConvertRowtypeExpr *convert = 
(ConvertRowtypeExpr *) node;
+                               Node       *arg = (Node *) convert->arg;
+ 
+                               if (convert->convertformat == 
COERCE_IMPLICIT_CAST &&
+                                       !showimplicit)
+                               {
+                                       /* don't show the implicit cast */
+                                       get_rule_expr_paren(arg, context, 
false, node);
+                               }
+                               else
+                               {
+                                       if (!PRETTY_PAREN(context))
+                                               appendStringInfoChar(buf, '(');
+                                       get_rule_expr_paren(arg, context, 
false, node);
+                                       if (!PRETTY_PAREN(context))
+                                               appendStringInfoChar(buf, ')');
+                                       appendStringInfo(buf, "::%s",
+                                                       
format_type_with_typemod(convert->resulttype, -1));
+                               }
+                       }
+                       break;
+ 
                case T_CaseExpr:
                        {
                                CaseExpr   *caseexpr = (CaseExpr *) node;
Index: src/include/nodes/execnodes.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/nodes/execnodes.h,v
retrieving revision 1.120
diff -c -r1.120 execnodes.h
*** src/include/nodes/execnodes.h       7 Oct 2004 18:38:51 -0000       1.120
--- src/include/nodes/execnodes.h       11 Dec 2004 16:26:03 -0000
***************
*** 579,584 ****
--- 579,601 ----
  } FieldStoreState;
  
  /* ----------------
+  *            ConvertRowtypeExprState node
+  * ----------------
+  */
+ typedef struct ConvertRowtypeExprState
+ {
+       ExprState       xprstate;
+       ExprState  *arg;                        /* input tuple value */
+       TupleDesc       indesc;                 /* tupdesc for source rowtype */
+       TupleDesc       outdesc;                /* tupdesc for result rowtype */
+       AttrNumber *attrMap;            /* indexes of input fields, or 0 for 
null */
+       Datum      *invalues;           /* workspace for deconstructing source 
*/
+       char       *innulls;
+       Datum      *outvalues;          /* workspace for constructing result */
+       char       *outnulls;
+ } ConvertRowtypeExprState;
+ 
+ /* ----------------
   *            CaseExprState node
   * ----------------
   */
Index: src/include/nodes/nodes.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/nodes/nodes.h,v
retrieving revision 1.161
diff -c -r1.161 nodes.h
*** src/include/nodes/nodes.h   14 Sep 2004 03:21:25 -0000      1.161
--- src/include/nodes/nodes.h   11 Dec 2004 16:26:03 -0000
***************
*** 112,117 ****
--- 112,118 ----
        T_FieldSelect,
        T_FieldStore,
        T_RelabelType,
+       T_ConvertRowtypeExpr,
        T_CaseExpr,
        T_CaseWhen,
        T_CaseTestExpr,
***************
*** 145,150 ****
--- 146,152 ----
        T_SubPlanState,
        T_FieldSelectState,
        T_FieldStoreState,
+       T_ConvertRowtypeExprState,
        T_CaseExprState,
        T_CaseWhenState,
        T_ArrayExprState,
Index: src/include/nodes/primnodes.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/nodes/primnodes.h,v
retrieving revision 1.104
diff -c -r1.104 primnodes.h
*** src/include/nodes/primnodes.h       29 Aug 2004 05:06:57 -0000      1.104
--- src/include/nodes/primnodes.h       11 Dec 2004 16:26:03 -0000
***************
*** 591,596 ****
--- 591,617 ----
        CoercionForm relabelformat; /* how to display this node */
  } RelabelType;
  
+ /* ----------------
+  * ConvertRowtypeExpr
+  *
+  * ConvertRowtypeExpr represents a type coercion from one composite type
+  * to another, where the source type is guaranteed to contain all the columns
+  * needed for the destination type plus possibly others; the columns need not
+  * be in the same positions, but are matched up by name.  This is primarily
+  * used to convert a whole-row value of an inheritance child table into a
+  * valid whole-row value of its parent table's rowtype.
+  * ----------------
+  */
+ 
+ typedef struct ConvertRowtypeExpr
+ {
+       Expr            xpr;
+       Expr       *arg;                        /* input expression */
+       Oid                     resulttype;             /* output type (always 
a composite type) */
+       /* result typmod is not stored, but must be -1; see RowExpr comments */
+       CoercionForm convertformat; /* how to display this node */
+ } ConvertRowtypeExpr;
+ 
  /*----------
   * CaseExpr - a CASE expression
   *
Index: src/pl/plpgsql/src/pl_exec.c
===================================================================
RCS file: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v
retrieving revision 1.123
diff -c -r1.123 pl_exec.c
*** src/pl/plpgsql/src/pl_exec.c        30 Nov 2004 03:50:29 -0000      1.123
--- src/pl/plpgsql/src/pl_exec.c        11 Dec 2004 16:26:03 -0000
***************
*** 4024,4029 ****
--- 4024,4032 ----
                case T_RelabelType:
                        return exec_simple_check_node((Node *) ((RelabelType *) 
node)->arg);
  
+               case T_ConvertRowtypeExpr:
+                       return exec_simple_check_node((Node *) 
((ConvertRowtypeExpr *) node)->arg);
+ 
                case T_CaseExpr:
                        {
                                CaseExpr   *expr = (CaseExpr *) node;
---------------------------(end of broadcast)---------------------------
TIP 4: Don't 'kill -9' the postmaster

Reply via email to