* with error cases, but it's not worth changing now.)  The vartype indicates
  * a rowtype; either a named composite type, or RECORD.  This function
  * encapsulates the logic for determining the correct rowtype OID to use.
+ *
+ * If allowScalar is true, then for the case where the RTE is a function
+ * returning a non-composite result type, we produce a normal Var referencing
+ * the function's result directly, instead of the single-column composite
+ * value that the whole-row notation might otherwise suggest.
  */
 Var *
 makeWholeRowVar(RangeTblEntry *rte,
                Index varno,
-               Index varlevelsup)
+               Index varlevelsup,
+               bool allowScalar)
 {
    Var        *result;
    Oid         toid;
                                 InvalidOid,
                                 varlevelsup);
            }
-           else
+           else if (allowScalar)
            {
-               /*
-                * func returns scalar; instead of making a whole-row Var,
-                * just reference the function's scalar output.  (XXX this
-                * seems a tad inconsistent, especially if "f.*" was
-                * explicitly written ...)
-                */
+               /* func returns scalar; just return its output as-is */
                result = makeVar(varno,
                                 1,
                                 toid,
                                 -1,
+                                exprCollation(rte->funcexpr),
+                                varlevelsup);
+           }
+           else
+           {
+               /* func returns scalar, but we want a composite result */
+               result = makeVar(varno,
+                                InvalidAttrNumber,
+                                RECORDOID,
+                                -1,
                                 InvalidOid,
                                 varlevelsup);
            }
            break;
-       case RTE_VALUES:
-           toid = RECORDOID;
-           /* returns composite; same as relation case */
-           result = makeVar(varno,
-                            InvalidAttrNumber,
-                            toid,
-                            -1,
-                            InvalidOid,
-                            varlevelsup);
-           break;
        default:
 
            /*
-            * RTE is a join or subselect.  We represent this as a whole-row
-            * Var of RECORD type.  (Note that in most cases the Var will be
-            * expanded to a RowExpr during planning, but that is not our
-            * concern here.)
+            * RTE is a join, subselect, or VALUES.  We represent this as a
+            * whole-row Var of RECORD type. (Note that in most cases the Var
+            * will be expanded to a RowExpr during planning, but that is not
+            * our concern here.)
             */
            result = makeVar(varno,
                             InvalidAttrNumber,
 
            /* Not a table, so we need the whole row as a junk var */
            var = makeWholeRowVar(rt_fetch(rc->rti, range_table),
                                  rc->rti,
-                                 0);
+                                 0,
+                                 false);
            snprintf(resname, sizeof(resname), "wholerow%u", rc->rowmarkId);
            tle = makeTargetEntry((Expr *) var,
                                  list_length(tlist) + 1,
 
    /* Find the RTE's rangetable location */
    vnum = RTERangeTablePosn(pstate, rte, &sublevels_up);
 
-   /* Build the appropriate referencing node */
-   result = makeWholeRowVar(rte, vnum, sublevels_up);
+   /*
+    * Build the appropriate referencing node.  Note that if the RTE is a
+    * function returning scalar, we create just a plain reference to the
+    * function value, not a composite containing a single column.  This is
+    * pretty inconsistent at first sight, but it's what we've done
+    * historically.  One argument for it is that "rel" and "rel.*" mean the
+    * same thing for composite relations, so why not for scalar functions...
+    */
+   result = makeWholeRowVar(rte, vnum, sublevels_up, true);
 
    /* location is not filled in by makeWholeRowVar */
    result->location = location;