parse_target.c 12.9 KB
Newer Older
1 2 3 4 5
/*-------------------------------------------------------------------------
 *
 * parse_target.c
 *	  handle target lists
 *
B
Bruce Momjian 已提交
6
 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
B
Add:  
Bruce Momjian 已提交
7
 * Portions Copyright (c) 1994, Regents of the University of California
8 9 10
 *
 *
 * IDENTIFICATION
11
 *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.93 2002/12/12 15:49:39 tgl Exp $
12 13 14 15
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"
16

17
#include "miscadmin.h"
18
#include "nodes/makefuncs.h"
19
#include "parser/parsetree.h"
B
Bruce Momjian 已提交
20
#include "parser/parse_coerce.h"
21
#include "parser/parse_expr.h"
B
Bruce Momjian 已提交
22
#include "parser/parse_func.h"
23 24
#include "parser/parse_relation.h"
#include "parser/parse_target.h"
B
Bruce Momjian 已提交
25
#include "parser/parse_type.h"
26
#include "utils/builtins.h"
27

28

29
static List *ExpandAllTables(ParseState *pstate);
30
static char *FigureColname(Node *node);
31
static int	FigureColnameInternal(Node *node, char **name);
32

M
 
Marc G. Fournier 已提交
33

34 35 36 37 38
/*
 * transformTargetEntry()
 *	Transform any ordinary "expression-type" node into a targetlist entry.
 *	This is exported so that parse_clause.c can generate targetlist entries
 *	for ORDER/GROUP BY items that are not already in the targetlist.
39
 *
40 41 42 43 44
 * node		the (untransformed) parse tree for the value expression.
 * expr		the transformed expression, or NULL if caller didn't do it yet.
 * colname	the column name to be assigned, or NULL if none yet set.
 * resjunk	true if the target should be marked resjunk, ie, it is not
 *			wanted in the final projected tuple.
M
 
Marc G. Fournier 已提交
45
 */
46
TargetEntry *
47
transformTargetEntry(ParseState *pstate,
48
					 Node *node,
49
					 Node *expr,
50
					 char *colname,
B
Bruce Momjian 已提交
51
					 bool resjunk)
M
 
Marc G. Fournier 已提交
52
{
53 54
	Oid			type_id;
	int32		type_mod;
B
cleanup  
Bruce Momjian 已提交
55 56
	Resdom	   *resnode;

57
	/* Transform the node if caller didn't do it already */
B
cleanup  
Bruce Momjian 已提交
58
	if (expr == NULL)
B
Bruce Momjian 已提交
59
		expr = transformExpr(pstate, node, NULL);
B
cleanup  
Bruce Momjian 已提交
60

61
	if (IsA(expr, RangeVar))
62
		elog(ERROR, "You can't use relation names alone in the target list, try relation.*.");
63

B
cleanup  
Bruce Momjian 已提交
64
	type_id = exprType(expr);
65
	type_mod = exprTypmod(expr);
B
cleanup  
Bruce Momjian 已提交
66

67
	if (colname == NULL)
B
cleanup  
Bruce Momjian 已提交
68
	{
69 70
		/*
		 * Generate a suitable column name for a column without any
71
		 * explicit 'AS ColumnName' clause.
B
cleanup  
Bruce Momjian 已提交
72
		 */
73
		colname = FigureColname(node);
B
cleanup  
Bruce Momjian 已提交
74 75
	}

76 77 78
	resnode = makeResdom((AttrNumber) pstate->p_last_resno++,
						 type_id,
						 type_mod,
B
cleanup  
Bruce Momjian 已提交
79 80 81
						 colname,
						 resjunk);

82
	return makeTargetEntry(resnode, (Expr *) expr);
83
}
T
Thomas G. Lockhart 已提交
84 85


86
/*
87 88 89 90 91
 * transformTargetList()
 * Turns a list of ResTarget's into a list of TargetEntry's.
 *
 * At this point, we don't care whether we are doing SELECT, INSERT,
 * or UPDATE; we just transform the given expressions.
92
 */
93 94
List *
transformTargetList(ParseState *pstate, List *targetlist)
95
{
96
	List	   *p_target = NIL;
97

98
	while (targetlist != NIL)
99
	{
100
		ResTarget  *res = (ResTarget *) lfirst(targetlist);
B
cleanup  
Bruce Momjian 已提交
101

102
		if (IsA(res->val, ColumnRef))
103
		{
104 105 106
			ColumnRef  *cref = (ColumnRef *) res->val;
			List	   *fields = cref->fields;
			int			numnames = length(fields);
B
cleanup  
Bruce Momjian 已提交
107

108
			if (numnames == 1 && strcmp(strVal(lfirst(fields)), "*") == 0)
109
			{
110
				/*
111 112
				 * Target item is a single '*', expand all tables (eg.
				 * SELECT * FROM emp)
113
				 */
114 115
				p_target = nconc(p_target,
								 ExpandAllTables(pstate));
116
			}
B
Bruce Momjian 已提交
117
			else if (strcmp(strVal(nth(numnames - 1, fields)), "*") == 0)
118 119
			{
				/*
120 121
				 * Target item is relation.*, expand that table (eg.
				 * SELECT emp.*, dname FROM emp, dept)
122
				 */
123 124
				char	   *schemaname;
				char	   *relname;
125
				RangeTblEntry *rte;
126 127
				int			sublevels_up;

128 129 130 131 132 133 134 135 136 137 138
				switch (numnames)
				{
					case 2:
						schemaname = NULL;
						relname = strVal(lfirst(fields));
						break;
					case 3:
						schemaname = strVal(lfirst(fields));
						relname = strVal(lsecond(fields));
						break;
					case 4:
B
Bruce Momjian 已提交
139 140 141 142 143 144 145 146 147 148 149 150 151
						{
							char	   *name1 = strVal(lfirst(fields));

							/*
							 * We check the catalog name and then ignore
							 * it.
							 */
							if (strcmp(name1, DatabaseName) != 0)
								elog(ERROR, "Cross-database references are not implemented");
							schemaname = strVal(lsecond(fields));
							relname = strVal(lfirst(lnext(lnext(fields))));
							break;
						}
152 153
					default:
						elog(ERROR, "Invalid qualified name syntax (too many names)");
B
Bruce Momjian 已提交
154
						schemaname = NULL;		/* keep compiler quiet */
155 156 157 158
						relname = NULL;
						break;
				}

159
				rte = refnameRangeTblEntry(pstate, schemaname, relname,
160 161
										   &sublevels_up);
				if (rte == NULL)
162 163
					rte = addImplicitRTE(pstate, makeRangeVar(schemaname,
															  relname));
164 165 166

				p_target = nconc(p_target,
								 expandRelAttrs(pstate, rte));
167 168
			}
			else
169
			{
170
				/* Plain ColumnRef node, treat it as an expression */
171 172 173 174 175 176 177
				p_target = lappend(p_target,
								   transformTargetEntry(pstate,
														res->val,
														NULL,
														res->name,
														false));
			}
178
		}
B
Bruce Momjian 已提交
179 180 181 182 183
		else if (IsA(res->val, InsertDefault))
		{
			InsertDefault *newnode = makeNode(InsertDefault);

			/*
B
Bruce Momjian 已提交
184 185
			 * If this is a DEFAULT element, we make a junk entry which
			 * will get dropped on return to transformInsertStmt().
B
Bruce Momjian 已提交
186 187 188
			 */
			p_target = lappend(p_target, newnode);
		}
189
		else
190
		{
B
Bruce Momjian 已提交
191
			/* Everything else but ColumnRef and InsertDefault */
192 193 194 195 196 197
			p_target = lappend(p_target,
							   transformTargetEntry(pstate,
													res->val,
													NULL,
													res->name,
													false));
198 199
		}

200
		targetlist = lnext(targetlist);
201
	}
202 203

	return p_target;
204 205
}

206

207
/*
208
 * updateTargetListEntry()
209
 *	This is used in INSERT and UPDATE statements only.	It prepares a
210 211 212 213 214 215 216 217
 *	TargetEntry for assignment to a column of the target table.
 *	This includes coercing the given value to the target column's type
 *	(if necessary), and dealing with any subscripts attached to the target
 *	column itself.
 *
 * pstate		parse state
 * tle			target list entry to be modified
 * colname		target column name (ie, name of attribute to be assigned to)
218
 * attrno		target attribute number
219
 * indirection	subscripts for target column, if any
220
 */
221 222 223 224
void
updateTargetListEntry(ParseState *pstate,
					  TargetEntry *tle,
					  char *colname,
225
					  int attrno,
226
					  List *indirection)
227
{
228
	Oid			type_id = exprType((Node *) tle->expr);	/* type of value provided */
229 230 231 232
	Oid			attrtype;		/* type of target column */
	int32		attrtypmod;
	Resdom	   *resnode = tle->resdom;
	Relation	rd = pstate->p_target_relation;
233

234
	Assert(rd != NULL);
235
	if (attrno <= 0)
236
		elog(ERROR, "Cannot assign to system attribute '%s'", colname);
237 238
	attrtype = attnumTypeId(rd, attrno);
	attrtypmod = rd->rd_att->attrs[attrno - 1]->atttypmod;
239

240
	/*
241 242 243 244 245
	 * If there are subscripts on the target column, prepare an array
	 * assignment expression.  This will generate an array value that the
	 * source value has been inserted into, which can then be placed in
	 * the new tuple constructed by INSERT or UPDATE. Note that
	 * transformArraySubscripts takes care of type coercion.
246
	 */
247
	if (indirection)
248
	{
249 250 251 252
		Node	   *arrayBase;
		ArrayRef   *aref;

		if (pstate->p_is_insert)
253
		{
254 255 256
			/*
			 * The command is INSERT INTO table (arraycol[subscripts]) ...
			 * so there is not really a source array value to work with.
257
			 * Let the executor do something reasonable, if it can. Notice
258 259 260 261 262 263 264 265 266 267
			 * that we force transformArraySubscripts to treat the
			 * subscripting op as an array-slice op below, so the source
			 * data will have been coerced to the array type.
			 */
			arrayBase = NULL;	/* signal there is no source array */
		}
		else
		{
			/*
			 * Build a Var for the array to be updated.
268
			 */
269 270 271
			arrayBase = (Node *) make_var(pstate,
										  pstate->p_target_rangetblentry,
										  attrno);
272
		}
273 274 275 276

		aref = transformArraySubscripts(pstate,
										arrayBase,
										attrtype,
277
										attrtypmod,
278 279
										indirection,
										pstate->p_is_insert,
280 281
										(Node *) tle->expr);
		tle->expr = (Expr *) aref;
282 283 284 285
	}
	else
	{
		/*
286 287
		 * For normal non-subscripted target column, do type checking and
		 * coercion.  But accept InvalidOid, which indicates the source is
288
		 * a NULL constant.  (XXX is that still true?)
289
		 */
290
		if (type_id != InvalidOid)
291
		{
292 293 294 295 296
			tle->expr = (Expr *)
				coerce_to_target_type((Node *) tle->expr, type_id,
									  attrtype, attrtypmod,
									  COERCION_ASSIGNMENT,
									  COERCE_IMPLICIT_CAST);
297 298 299 300 301 302 303
			if (tle->expr == NULL)
				elog(ERROR, "column \"%s\" is of type %s"
					 " but expression is of type %s"
					 "\n\tYou will need to rewrite or cast the expression",
					 colname,
					 format_type_be(attrtype),
					 format_type_be(type_id));
304 305 306
		}
	}

307
	/*
308 309 310 311
	 * The result of the target expression should now match the
	 * destination column's type.  Also, reset the resname and resno to
	 * identify the destination column --- rewriter and planner depend on
	 * that!
312 313 314 315
	 */
	resnode->restype = attrtype;
	resnode->restypmod = attrtypmod;
	resnode->resname = colname;
316
	resnode->resno = (AttrNumber) attrno;
317
}
318 319 320


/*
321
 * checkInsertTargets -
322
 *	  generate a list of INSERT column targets if not supplied, or
323
 *	  test supplied column names to make sure they are in target table.
324
 *	  Also return an integer list of the columns' attribute numbers.
325 326
 */
List *
327
checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
328
{
329 330
	*attrnos = NIL;

331 332
	if (cols == NIL)
	{
333 334 335
		/*
		 * Generate default column list for INSERT.
		 */
336
		Form_pg_attribute *attr = pstate->p_target_relation->rd_att->attrs;
337 338
		int			numcol = pstate->p_target_relation->rd_rel->relnatts;
		int			i;
339 340 341

		for (i = 0; i < numcol; i++)
		{
B
Bruce Momjian 已提交
342
			ResTarget  *col;
343

344 345 346 347
			if (attr[i]->attisdropped)
				continue;

			col = makeNode(ResTarget);
348 349 350 351
			col->name = pstrdup(NameStr(attr[i]->attname));
			col->indirection = NIL;
			col->val = NULL;
			cols = lappend(cols, col);
352
			*attrnos = lappendi(*attrnos, i + 1);
353 354 355 356
		}
	}
	else
	{
357 358 359 360 361
		/*
		 * Do initial validation of user-supplied INSERT column list.
		 */
		List	   *tl;

362 363
		foreach(tl, cols)
		{
364
			char	   *name = ((ResTarget *) lfirst(tl))->name;
365
			int			attrno;
366

367
			/* Lookup column name, elog on failure */
368
			attrno = attnameAttNum(pstate->p_target_relation, name, false);
369
			/* Check for duplicates */
370 371 372
			if (intMember(attrno, *attrnos))
				elog(ERROR, "Attribute '%s' specified more than once", name);
			*attrnos = lappendi(*attrnos, attrno);
373 374
		}
	}
375

376 377 378
	return cols;
}

379
/* ExpandAllTables()
380 381
 * Turns '*' (in the target list) into a list of targetlist entries.
 *
382 383 384
 * tlist entries are generated for each relation appearing at the top level
 * of the query's namespace, except for RTEs marked not inFromCl.  (These
 * may include NEW/OLD pseudo-entries, implicit RTEs, etc.)
385
 */
386
static List *
387
ExpandAllTables(ParseState *pstate)
388 389
{
	List	   *target = NIL;
390
	bool		found_table = false;
391
	List	   *ns;
392

393
	foreach(ns, pstate->p_namespace)
394
	{
395
		Node	   *n = (Node *) lfirst(ns);
396
		RangeTblEntry *rte;
397

398 399 400 401
		if (IsA(n, RangeTblRef))
			rte = rt_fetch(((RangeTblRef *) n)->rtindex,
						   pstate->p_rtable);
		else if (IsA(n, JoinExpr))
402 403
			rte = rt_fetch(((JoinExpr *) n)->rtindex,
						   pstate->p_rtable);
404
		else
405
		{
406 407
			elog(ERROR, "ExpandAllTables: unexpected node (internal error)"
				 "\n\t%s", nodeToString(n));
408 409 410 411 412 413 414 415 416 417
			rte = NULL;			/* keep compiler quiet */
		}

		/*
		 * Ignore added-on relations that were not listed in the FROM
		 * clause.
		 */
		if (!rte->inFromCl)
			continue;

418
		found_table = true;
419
		target = nconc(target, expandRelAttrs(pstate, rte));
420
	}
421

422
	/* Check for SELECT *; */
423
	if (!found_table)
424 425
		elog(ERROR, "Wildcard with no tables specified not allowed");

426 427 428 429
	return target;
}

/*
430
 * FigureColname -
431
 *	  if the name of the resulting column is not specified in the target
432 433
 *	  list, we have to guess a suitable name.  The SQL spec provides some
 *	  guidance, but not much...
434
 *
435 436
 * Note that the argument is the *untransformed* parse tree for the target
 * item.  This is a shade easier to work with than the transformed tree.
437
 */
438
static char *
439
FigureColname(Node *node)
440
{
441
	char	   *name = NULL;
442 443 444 445 446 447 448 449 450 451 452

	FigureColnameInternal(node, &name);
	if (name != NULL)
		return name;
	/* default result if we can't guess anything */
	return "?column?";
}

static int
FigureColnameInternal(Node *node, char **name)
{
453
	int			strength = 0;
454

455
	if (node == NULL)
456
		return strength;
457

458
	switch (nodeTag(node))
459
	{
460
		case T_ColumnRef:
461
			{
B
Bruce Momjian 已提交
462
				char	   *cname = strVal(llast(((ColumnRef *) node)->fields));
463

464
				if (strcmp(cname, "*") != 0)
465
				{
466
					*name = cname;
467
					return 2;
468
				}
469 470
			}
			break;
471 472
		case T_ExprFieldSelect:
			{
B
Bruce Momjian 已提交
473
				char	   *fname = strVal(llast(((ExprFieldSelect *) node)->fields));
474

475
				if (strcmp(fname, "*") != 0)
476
				{
477 478
					*name = fname;
					return 2;
479 480 481
				}
			}
			break;
482
		case T_FuncCall:
483
			*name = strVal(llast(((FuncCall *) node)->funcname));
484 485 486 487
			return 2;
		case T_A_Const:
			if (((A_Const *) node)->typename != NULL)
			{
488 489
				*name = strVal(llast(((A_Const *) node)->typename->names));
				return 1;
490 491
			}
			break;
492
		case T_TypeCast:
493 494 495
			strength = FigureColnameInternal(((TypeCast *) node)->arg,
											 name);
			if (strength <= 1)
496
			{
497 498
				if (((TypeCast *) node)->typename != NULL)
				{
499 500
					*name = strVal(llast(((TypeCast *) node)->typename->names));
					return 1;
501
				}
502 503
			}
			break;
504
		case T_CaseExpr:
505
			strength = FigureColnameInternal((Node *) ((CaseExpr *) node)->defresult,
506 507
											 name);
			if (strength <= 1)
508
			{
509 510
				*name = "case";
				return 1;
511 512
			}
			break;
513 514 515
		default:
			break;
	}
516 517

	return strength;
518
}