diff options
| -rw-r--r-- | src/backend/nodes/makefuncs.c | 43 | ||||
| -rw-r--r-- | src/backend/optimizer/prep/preptlist.c | 3 | ||||
| -rw-r--r-- | src/backend/parser/parse_expr.c | 11 | ||||
| -rw-r--r-- | src/include/nodes/makefuncs.h | 3 | 
4 files changed, 35 insertions, 25 deletions
| diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c index c9344f724d3..dae2368b3f1 100644 --- a/src/backend/nodes/makefuncs.c +++ b/src/backend/nodes/makefuncs.c @@ -101,11 +101,17 @@ makeVar(Index varno,   * 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; @@ -135,37 +141,32 @@ makeWholeRowVar(RangeTblEntry *rte,  								 -1,  								 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,  								 varlevelsup);  			} -			break; -		case RTE_VALUES: -			toid = RECORDOID; -			/* returns composite; same as relation case */ -			result = makeVar(varno, -							 InvalidAttrNumber, -							 toid, -							 -1, -							 varlevelsup); +			else +			{ +				/* func returns scalar, but we want a composite result */ +				result = makeVar(varno, +								 InvalidAttrNumber, +								 RECORDOID, +								 -1, +								 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, diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c index 425d80c6244..ebe581cbe08 100644 --- a/src/backend/optimizer/prep/preptlist.c +++ b/src/backend/optimizer/prep/preptlist.c @@ -160,7 +160,8 @@ preprocess_targetlist(PlannerInfo *root, List *tlist)  			/* 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, diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 5e6daaede5d..ccc1e67c027 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -2029,8 +2029,15 @@ transformWholeRowRef(ParseState *pstate, RangeTblEntry *rte, int location)  	/* 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; diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h index 6d009a2bbab..69e2b17b871 100644 --- a/src/include/nodes/makefuncs.h +++ b/src/include/nodes/makefuncs.h @@ -31,7 +31,8 @@ extern Var *makeVar(Index varno,  extern Var *makeWholeRowVar(RangeTblEntry *rte,  				Index varno, -				Index varlevelsup); +				Index varlevelsup, +				bool allowScalar);  extern TargetEntry *makeTargetEntry(Expr *expr,  				AttrNumber resno, | 
