mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	ParseComplexProjection should make use of expandRecordVariable so that
it can handle cases like (foo.x).y where foo is a subquery and x is a function-returning-RECORD RTE in that subquery.
This commit is contained in:
		@@ -8,7 +8,7 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * IDENTIFICATION
 | 
					 * IDENTIFICATION
 | 
				
			||||||
 *	  $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.179 2005/04/23 22:09:58 tgl Exp $
 | 
					 *	  $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.180 2005/05/31 01:03:23 tgl Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *-------------------------------------------------------------------------
 | 
					 *-------------------------------------------------------------------------
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -25,6 +25,7 @@
 | 
				
			|||||||
#include "parser/parse_expr.h"
 | 
					#include "parser/parse_expr.h"
 | 
				
			||||||
#include "parser/parse_func.h"
 | 
					#include "parser/parse_func.h"
 | 
				
			||||||
#include "parser/parse_relation.h"
 | 
					#include "parser/parse_relation.h"
 | 
				
			||||||
 | 
					#include "parser/parse_target.h"
 | 
				
			||||||
#include "parser/parse_type.h"
 | 
					#include "parser/parse_type.h"
 | 
				
			||||||
#include "utils/builtins.h"
 | 
					#include "utils/builtins.h"
 | 
				
			||||||
#include "utils/fmgroids.h"
 | 
					#include "utils/fmgroids.h"
 | 
				
			||||||
@@ -957,6 +958,9 @@ ParseComplexProjection(ParseState *pstate, char *funcname, Node *first_arg)
 | 
				
			|||||||
	 * function. A bonus is that we avoid generating an unnecessary
 | 
						 * function. A bonus is that we avoid generating an unnecessary
 | 
				
			||||||
	 * FieldSelect; our result can omit the whole-row Var and just be a
 | 
						 * FieldSelect; our result can omit the whole-row Var and just be a
 | 
				
			||||||
	 * Var for the selected field.
 | 
						 * Var for the selected field.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * This case could be handled by expandRecordVariable, but it's
 | 
				
			||||||
 | 
						 * more efficient to do it this way when possible.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (IsA(first_arg, Var) &&
 | 
						if (IsA(first_arg, Var) &&
 | 
				
			||||||
		((Var *) first_arg)->varattno == InvalidAttrNumber)
 | 
							((Var *) first_arg)->varattno == InvalidAttrNumber)
 | 
				
			||||||
@@ -971,12 +975,18 @@ ParseComplexProjection(ParseState *pstate, char *funcname, Node *first_arg)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Else do it the hard way.  Note that if the arg is of RECORD type,
 | 
						 * Else do it the hard way with get_expr_result_type().
 | 
				
			||||||
	 * and isn't resolvable as a function with OUT params, we will never
 | 
						 *
 | 
				
			||||||
	 * be able to recognize a column name here.
 | 
						 * If it's a Var of type RECORD, we have to work even harder: we have
 | 
				
			||||||
 | 
						 * to find what the Var refers to, and pass that to get_expr_result_type.
 | 
				
			||||||
 | 
						 * That task is handled by expandRecordVariable().
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (get_expr_result_type(first_arg, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
 | 
						if (IsA(first_arg, Var) &&
 | 
				
			||||||
 | 
							((Var *) first_arg)->vartype == RECORDOID)
 | 
				
			||||||
 | 
							tupdesc = expandRecordVariable(pstate, (Var *) first_arg, 0);
 | 
				
			||||||
 | 
						else if (get_expr_result_type(first_arg, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
 | 
				
			||||||
		return NULL;			/* unresolvable RECORD type */
 | 
							return NULL;			/* unresolvable RECORD type */
 | 
				
			||||||
 | 
						Assert(tupdesc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < tupdesc->natts; i++)
 | 
						for (i = 0; i < tupdesc->natts; i++)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * IDENTIFICATION
 | 
					 * IDENTIFICATION
 | 
				
			||||||
 *	  $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.133 2005/04/25 22:02:30 tgl Exp $
 | 
					 *	  $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.134 2005/05/31 01:03:23 tgl Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *-------------------------------------------------------------------------
 | 
					 *-------------------------------------------------------------------------
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -44,8 +44,6 @@ static Node *transformAssignmentIndirection(ParseState *pstate,
 | 
				
			|||||||
static List *ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref);
 | 
					static List *ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref);
 | 
				
			||||||
static List *ExpandAllTables(ParseState *pstate);
 | 
					static List *ExpandAllTables(ParseState *pstate);
 | 
				
			||||||
static List *ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind);
 | 
					static List *ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind);
 | 
				
			||||||
static TupleDesc expandRecordVariable(ParseState *pstate, Var *var,
 | 
					 | 
				
			||||||
									  int levelsup);
 | 
					 | 
				
			||||||
static int	FigureColnameInternal(Node *node, char **name);
 | 
					static int	FigureColnameInternal(Node *node, char **name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -905,7 +903,7 @@ ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind)
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 * levelsup is an extra offset to interpret the Var's varlevelsup correctly.
 | 
					 * levelsup is an extra offset to interpret the Var's varlevelsup correctly.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static TupleDesc
 | 
					TupleDesc
 | 
				
			||||||
expandRecordVariable(ParseState *pstate, Var *var, int levelsup)
 | 
					expandRecordVariable(ParseState *pstate, Var *var, int levelsup)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	TupleDesc	tupleDesc;
 | 
						TupleDesc	tupleDesc;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,7 @@
 | 
				
			|||||||
 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
 | 
					 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
 | 
				
			||||||
 * Portions Copyright (c) 1994, Regents of the University of California
 | 
					 * Portions Copyright (c) 1994, Regents of the University of California
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * $PostgreSQL: pgsql/src/include/parser/parse_target.h,v 1.35 2004/12/31 22:03:38 pgsql Exp $
 | 
					 * $PostgreSQL: pgsql/src/include/parser/parse_target.h,v 1.36 2005/05/31 01:03:23 tgl Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *-------------------------------------------------------------------------
 | 
					 *-------------------------------------------------------------------------
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -27,6 +27,8 @@ extern void updateTargetListEntry(ParseState *pstate, TargetEntry *tle,
 | 
				
			|||||||
					  List *indirection);
 | 
										  List *indirection);
 | 
				
			||||||
extern List *checkInsertTargets(ParseState *pstate, List *cols,
 | 
					extern List *checkInsertTargets(ParseState *pstate, List *cols,
 | 
				
			||||||
				   List **attrnos);
 | 
									   List **attrnos);
 | 
				
			||||||
 | 
					extern TupleDesc expandRecordVariable(ParseState *pstate, Var *var,
 | 
				
			||||||
 | 
														  int levelsup);
 | 
				
			||||||
extern char *FigureColname(Node *node);
 | 
					extern char *FigureColname(Node *node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif   /* PARSE_TARGET_H */
 | 
					#endif   /* PARSE_TARGET_H */
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user