rewriteHandler.c 52.9 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * rewriteHandler.c
4
 *		Primary module of query rewriter.
5
 *
6
 * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
B
Add:  
Bruce Momjian 已提交
7
 * Portions Copyright (c) 1994, Regents of the University of California
8 9
 *
 * IDENTIFICATION
B
Bruce Momjian 已提交
10
 *	  $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.167 2006/10/04 00:29:56 momjian Exp $
11 12 13 14 15
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

B
Bruce Momjian 已提交
16
#include "access/heapam.h"
17
#include "catalog/pg_type.h"
18
#include "nodes/makefuncs.h"
B
Bruce Momjian 已提交
19 20
#include "optimizer/clauses.h"
#include "parser/analyze.h"
21
#include "parser/parse_coerce.h"
22
#include "parser/parse_expr.h"
23
#include "parser/parsetree.h"
24
#include "rewrite/rewriteHandler.h"
B
Bruce Momjian 已提交
25
#include "rewrite/rewriteManip.h"
26
#include "utils/builtins.h"
B
Bruce Momjian 已提交
27
#include "utils/lsyscache.h"
28 29


30
/* We use a list of these to detect recursion in RewriteQuery */
B
Bruce Momjian 已提交
31 32
typedef struct rewrite_event
{
33 34
	Oid			relation;		/* OID of relation having rules */
	CmdType		event;			/* type of rule being fired */
35
} rewrite_event;
36

37
static bool acquireLocksOnSubLinks(Node *node, void *context);
38
static Query *rewriteRuleAction(Query *parsetree,
39 40 41
				  Query *rule_action,
				  Node *rule_qual,
				  int rt_index,
42 43
				  CmdType event,
				  bool *returning_flag);
44
static List *adjustJoinTreeList(Query *parsetree, bool removert, int rt_index);
45
static void rewriteTargetList(Query *parsetree, Relation target_relation,
B
Bruce Momjian 已提交
46
				  List **attrno_list);
47
static TargetEntry *process_matched_tle(TargetEntry *src_tle,
B
Bruce Momjian 已提交
48 49
					TargetEntry *prior_tle,
					const char *attrName);
50
static Node *get_assignment_input(Node *node);
51
static void rewriteValuesRTE(RangeTblEntry *rte, Relation target_relation,
B
Bruce Momjian 已提交
52
				 List *attrnos);
53
static void markQueryForLocking(Query *qry, bool forUpdate, bool noWait,
B
Bruce Momjian 已提交
54
					bool skipOldNew);
55
static List *matchLocks(CmdType event, RuleLock *rulelocks,
B
Bruce Momjian 已提交
56
		   int varno, Query *parsetree);
57
static Query *fireRIRrules(Query *parsetree, List *activeRIRs);
58

59

60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
/*
 * AcquireRewriteLocks -
 *	  Acquire suitable locks on all the relations mentioned in the Query.
 *	  These locks will ensure that the relation schemas don't change under us
 *	  while we are rewriting and planning the query.
 *
 * A secondary purpose of this routine is to fix up JOIN RTE references to
 * dropped columns (see details below).  Because the RTEs are modified in
 * place, it is generally appropriate for the caller of this routine to have
 * first done a copyObject() to make a writable copy of the querytree in the
 * current memory context.
 *
 * This processing can, and for efficiency's sake should, be skipped when the
 * querytree has just been built by the parser: parse analysis already got
 * all the same locks we'd get here, and the parser will have omitted dropped
 * columns from JOINs to begin with.  But we must do this whenever we are
 * dealing with a querytree produced earlier than the current command.
 *
 * About JOINs and dropped columns: although the parser never includes an
 * already-dropped column in a JOIN RTE's alias var list, it is possible for
 * such a list in a stored rule to include references to dropped columns.
 * (If the column is not explicitly referenced anywhere else in the query,
 * the dependency mechanism won't consider it used by the rule and so won't
 * prevent the column drop.)  To support get_rte_attribute_is_dropped(),
 * we replace join alias vars that reference dropped columns with NULL Const
 * nodes.
 *
 * (In PostgreSQL 8.0, we did not do this processing but instead had
 * get_rte_attribute_is_dropped() recurse to detect dropped columns in joins.
 * That approach had horrible performance unfortunately; in particular
 * construction of a nested join was O(N^2) in the nesting depth.)
 */
void
AcquireRewriteLocks(Query *parsetree)
{
	ListCell   *l;
	int			rt_index;

	/*
	 * First, process RTEs of the current query level.
	 */
	rt_index = 0;
	foreach(l, parsetree->rtable)
	{
		RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
		Relation	rel;
		LOCKMODE	lockmode;
		List	   *newaliasvars;
108 109
		Index		curinputvarno;
		RangeTblEntry *curinputrte;
110 111 112 113 114 115
		ListCell   *ll;

		++rt_index;
		switch (rte->rtekind)
		{
			case RTE_RELATION:
B
Bruce Momjian 已提交
116

117
				/*
B
Bruce Momjian 已提交
118 119 120
				 * Grab the appropriate lock type for the relation, and do not
				 * release it until end of transaction. This protects the
				 * rewriter and planner against schema changes mid-query.
121
				 *
122 123 124 125 126 127
				 * If the relation is the query's result relation, then we
				 * need RowExclusiveLock.  Otherwise, check to see if the
				 * relation is accessed FOR UPDATE/SHARE or not.  We can't
				 * just grab AccessShareLock because then the executor would
				 * be trying to upgrade the lock, leading to possible
				 * deadlocks.
128 129 130
				 */
				if (rt_index == parsetree->resultRelation)
					lockmode = RowExclusiveLock;
131
				else if (get_rowmark(parsetree, rt_index))
132 133 134 135 136 137 138 139 140
					lockmode = RowShareLock;
				else
					lockmode = AccessShareLock;

				rel = heap_open(rte->relid, lockmode);
				heap_close(rel, NoLock);
				break;

			case RTE_JOIN:
B
Bruce Momjian 已提交
141

142
				/*
B
Bruce Momjian 已提交
143 144 145
				 * Scan the join's alias var list to see if any columns have
				 * been dropped, and if so replace those Vars with NULL
				 * Consts.
146
				 *
B
Bruce Momjian 已提交
147 148 149
				 * Since a join has only two inputs, we can expect to see
				 * multiple references to the same input RTE; optimize away
				 * multiple fetches.
150 151
				 */
				newaliasvars = NIL;
152 153
				curinputvarno = 0;
				curinputrte = NULL;
154 155 156 157 158 159 160 161
				foreach(ll, rte->joinaliasvars)
				{
					Var		   *aliasvar = (Var *) lfirst(ll);

					/*
					 * If the list item isn't a simple Var, then it must
					 * represent a merged column, ie a USING column, and so it
					 * couldn't possibly be dropped, since it's referenced in
B
Bruce Momjian 已提交
162 163
					 * the join clause.  (Conceivably it could also be a NULL
					 * constant already?  But that's OK too.)
164 165 166 167 168
					 */
					if (IsA(aliasvar, Var))
					{
						/*
						 * The elements of an alias list have to refer to
B
Bruce Momjian 已提交
169 170 171 172 173 174
						 * earlier RTEs of the same rtable, because that's the
						 * order the planner builds things in.	So we already
						 * processed the referenced RTE, and so it's safe to
						 * use get_rte_attribute_is_dropped on it. (This might
						 * not hold after rewriting or planning, but it's OK
						 * to assume here.)
175 176
						 */
						Assert(aliasvar->varlevelsup == 0);
177 178 179 180 181 182 183 184 185 186 187
						if (aliasvar->varno != curinputvarno)
						{
							curinputvarno = aliasvar->varno;
							if (curinputvarno >= rt_index)
								elog(ERROR, "unexpected varno %d in JOIN RTE %d",
									 curinputvarno, rt_index);
							curinputrte = rt_fetch(curinputvarno,
												   parsetree->rtable);
						}
						if (get_rte_attribute_is_dropped(curinputrte,
														 aliasvar->varattno))
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
						{
							/*
							 * can't use vartype here, since that might be a
							 * now-dropped type OID, but it doesn't really
							 * matter what type the Const claims to be.
							 */
							aliasvar = (Var *) makeNullConst(INT4OID);
						}
					}
					newaliasvars = lappend(newaliasvars, aliasvar);
				}
				rte->joinaliasvars = newaliasvars;
				break;

			case RTE_SUBQUERY:
B
Bruce Momjian 已提交
203

204 205 206 207 208 209 210 211 212 213 214 215 216 217
				/*
				 * The subquery RTE itself is all right, but we have to
				 * recurse to process the represented subquery.
				 */
				AcquireRewriteLocks(rte->subquery);
				break;

			default:
				/* ignore other types of RTEs */
				break;
		}
	}

	/*
B
Bruce Momjian 已提交
218 219
	 * Recurse into sublink subqueries, too.  But we already did the ones in
	 * the rtable.
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
	 */
	if (parsetree->hasSubLinks)
		query_tree_walker(parsetree, acquireLocksOnSubLinks, NULL,
						  QTW_IGNORE_RT_SUBQUERIES);
}

/*
 * Walker to find sublink subqueries for AcquireRewriteLocks
 */
static bool
acquireLocksOnSubLinks(Node *node, void *context)
{
	if (node == NULL)
		return false;
	if (IsA(node, SubLink))
	{
		SubLink    *sub = (SubLink *) node;

		/* Do what we came for */
		AcquireRewriteLocks((Query *) sub->subselect);
		/* Fall through to process lefthand args of SubLink */
	}

	/*
	 * Do NOT recurse into Query nodes, because AcquireRewriteLocks already
	 * processed subselects of subselects for us.
	 */
	return expression_tree_walker(node, acquireLocksOnSubLinks, context);
}


251
/*
252 253 254
 * rewriteRuleAction -
 *	  Rewrite the rule action with appropriate qualifiers (taken from
 *	  the triggering query).
255 256 257 258 259 260 261 262 263 264 265 266
 *
 * Input arguments:
 *	parsetree - original query
 *	rule_action - one action (query) of a rule
 *	rule_qual - WHERE condition of rule, or NULL if unconditional
 *	rt_index - RT index of result relation in original query
 *	event - type of rule event
 * Output arguments:
 *	*returning_flag - set TRUE if we rewrite RETURNING clause in rule_action
 *					(must be initialized to FALSE)
 * Return value:
 *	rewritten form of rule_action
267
 */
268 269
static Query *
rewriteRuleAction(Query *parsetree,
270 271
				  Query *rule_action,
				  Node *rule_qual,
272
				  int rt_index,
273 274
				  CmdType event,
				  bool *returning_flag)
275
{
276 277 278
	int			current_varno,
				new_varno;
	int			rt_length;
279 280
	Query	   *sub_action;
	Query	  **sub_action_ptr;
281

282
	/*
B
Bruce Momjian 已提交
283 284
	 * Make modifiable copies of rule action and qual (what we're passed are
	 * the stored versions in the relcache; don't touch 'em!).
285 286 287 288
	 */
	rule_action = (Query *) copyObject(rule_action);
	rule_qual = (Node *) copyObject(rule_qual);

289 290 291 292 293 294
	/*
	 * Acquire necessary locks and fix any deleted JOIN RTE entries.
	 */
	AcquireRewriteLocks(rule_action);
	(void) acquireLocksOnSubLinks(rule_qual, NULL);

295
	current_varno = rt_index;
296
	rt_length = list_length(parsetree->rtable);
297
	new_varno = PRS2_NEW_VARNO + rt_length;
298

299
	/*
B
Bruce Momjian 已提交
300 301
	 * Adjust rule action and qual to offset its varnos, so that we can merge
	 * its rtable with the main parsetree's rtable.
302
	 *
303 304
	 * If the rule action is an INSERT...SELECT, the OLD/NEW rtable entries
	 * will be in the SELECT part, and we have to modify that rather than the
B
Bruce Momjian 已提交
305
	 * top-level INSERT (kluge!).
306
	 */
307
	sub_action = getInsertSelectQuery(rule_action, &sub_action_ptr);
308

309
	OffsetVarNodes((Node *) sub_action, rt_length, 0);
310
	OffsetVarNodes(rule_qual, rt_length, 0);
311 312 313
	/* but references to *OLD* should point at original rt_index */
	ChangeVarNodes((Node *) sub_action,
				   PRS2_OLD_VARNO + rt_length, rt_index, 0);
314
	ChangeVarNodes(rule_qual,
315 316 317
				   PRS2_OLD_VARNO + rt_length, rt_index, 0);

	/*
318 319
	 * Generate expanded rtable consisting of main parsetree's rtable plus
	 * rule action's rtable; this becomes the complete rtable for the rule
B
Bruce Momjian 已提交
320 321
	 * action.	Some of the entries may be unused after we finish rewriting,
	 * but we leave them all in place for two reasons:
322
	 *
323 324
	 * We'd have a much harder job to adjust the query's varnos if we
	 * selectively removed RT entries.
325
	 *
326 327 328
	 * If the rule is INSTEAD, then the original query won't be executed at
	 * all, and so its rtable must be preserved so that the executor will do
	 * the correct permissions checks on it.
329 330
	 *
	 * RT entries that are not referenced in the completed jointree will be
B
Bruce Momjian 已提交
331 332 333 334 335
	 * ignored by the planner, so they do not affect query semantics.  But any
	 * permissions checks specified in them will be applied during executor
	 * startup (see ExecCheckRTEPerms()).  This allows us to check that the
	 * caller has, say, insert-permission on a view, when the view is not
	 * semantically referenced at all in the resulting query.
336
	 *
337 338
	 * When a rule is not INSTEAD, the permissions checks done on its copied
	 * RT entries will be redundant with those done during execution of the
B
Bruce Momjian 已提交
339
	 * original query, but we don't bother to treat that case differently.
340
	 *
341 342 343
	 * NOTE: because planner will destructively alter rtable, we must ensure
	 * that rule action's rtable is separate and shares no substructure with
	 * the main rtable.  Hence do a deep copy here.
344
	 */
345
	sub_action->rtable = list_concat((List *) copyObject(parsetree->rtable),
B
Bruce Momjian 已提交
346
									 sub_action->rtable);
347

348 349
	/*
	 * Each rule action's jointree should be the main parsetree's jointree
B
Bruce Momjian 已提交
350 351 352 353 354 355 356 357
	 * plus that rule's jointree, but usually *without* the original rtindex
	 * that we're replacing (if present, which it won't be for INSERT). Note
	 * that if the rule action refers to OLD, its jointree will add a
	 * reference to rt_index.  If the rule action doesn't refer to OLD, but
	 * either the rule_qual or the user query quals do, then we need to keep
	 * the original rtindex in the jointree to provide data for the quals.	We
	 * don't want the original rtindex to be joined twice, however, so avoid
	 * keeping it if the rule action mentions it.
358
	 *
359 360
	 * As above, the action's jointree must not share substructure with the
	 * main parsetree's.
361
	 */
362
	if (sub_action->commandType != CMD_UTILITY)
363
	{
B
Bruce Momjian 已提交
364 365
		bool		keeporig;
		List	   *newjointree;
366

367
		Assert(sub_action->jointree != NULL);
B
Bruce Momjian 已提交
368 369
		keeporig = (!rangeTableEntry_used((Node *) sub_action->jointree,
										  rt_index, 0)) &&
370
			(rangeTableEntry_used(rule_qual, rt_index, 0) ||
B
Bruce Momjian 已提交
371
			 rangeTableEntry_used(parsetree->jointree->quals, rt_index, 0));
372
		newjointree = adjustJoinTreeList(parsetree, !keeporig, rt_index);
373 374 375
		if (newjointree != NIL)
		{
			/*
B
Bruce Momjian 已提交
376 377 378 379
			 * If sub_action is a setop, manipulating its jointree will do no
			 * good at all, because the jointree is dummy.	(Perhaps someday
			 * we could push the joining and quals down to the member
			 * statements of the setop?)
380 381
			 */
			if (sub_action->setOperations != NULL)
382 383 384
				ereport(ERROR,
						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
						 errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
385 386

			sub_action->jointree->fromlist =
387
				list_concat(newjointree, sub_action->jointree->fromlist);
388 389 390 391 392 393 394 395

			/*
			 * There could have been some SubLinks in newjointree, in which
			 * case we'd better mark the sub_action correctly.
			 */
			if (parsetree->hasSubLinks && !sub_action->hasSubLinks)
				sub_action->hasSubLinks =
					checkExprHasSubLink((Node *) newjointree);
396
		}
397 398 399
	}

	/*
B
Bruce Momjian 已提交
400 401 402
	 * Event Qualification forces copying of parsetree and splitting into two
	 * queries one w/rule_qual, one w/NOT rule_qual. Also add user query qual
	 * onto rule action
403
	 */
404
	AddQual(sub_action, rule_qual);
405 406 407 408

	AddQual(sub_action, parsetree->jointree->quals);

	/*
B
Bruce Momjian 已提交
409 410
	 * Rewrite new.attribute w/ right hand side of target-list entry for
	 * appropriate field name in insert/update.
411
	 *
412 413 414
	 * KLUGE ALERT: since ResolveNew returns a mutated copy, we can't just
	 * apply it to sub_action; we have to remember to update the sublink
	 * inside rule_action, too.
415
	 */
416 417
	if ((event == CMD_INSERT || event == CMD_UPDATE) &&
		sub_action->commandType != CMD_UTILITY)
418 419
	{
		sub_action = (Query *) ResolveNew((Node *) sub_action,
420
										  new_varno,
421
										  0,
422 423
										  rt_fetch(new_varno,
												   sub_action->rtable),
424
										  parsetree->targetList,
425 426
										  event,
										  current_varno);
427 428 429
		if (sub_action_ptr)
			*sub_action_ptr = sub_action;
		else
430
			rule_action = sub_action;
431
	}
432

433
	/*
B
Bruce Momjian 已提交
434 435 436 437
	 * If rule_action has a RETURNING clause, then either throw it away if the
	 * triggering query has no RETURNING clause, or rewrite it to emit what
	 * the triggering query's RETURNING clause asks for.  Throw an error if
	 * more than one rule has a RETURNING clause.
438 439 440 441 442 443 444 445
	 */
	if (!parsetree->returningList)
		rule_action->returningList = NIL;
	else if (rule_action->returningList)
	{
		if (*returning_flag)
			ereport(ERROR,
					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
B
Bruce Momjian 已提交
446
				   errmsg("cannot have RETURNING lists in multiple rules")));
447 448 449 450 451 452 453 454 455 456 457 458
		*returning_flag = true;
		rule_action->returningList = (List *)
			ResolveNew((Node *) parsetree->returningList,
					   parsetree->resultRelation,
					   0,
					   rt_fetch(parsetree->resultRelation,
								parsetree->rtable),
					   rule_action->returningList,
					   CMD_SELECT,
					   0);
	}

459
	return rule_action;
460 461
}

462
/*
463 464 465 466
 * Copy the query's jointree list, and optionally attempt to remove any
 * occurrence of the given rt_index as a top-level join item (we do not look
 * for it within join items; this is OK because we are only expecting to find
 * it as an UPDATE or DELETE target relation, which will be at the top level
467 468
 * of the join).  Returns modified jointree list --- this is a separate copy
 * sharing no nodes with the original.
469
 */
470
static List *
471
adjustJoinTreeList(Query *parsetree, bool removert, int rt_index)
472
{
473
	List	   *newjointree = copyObject(parsetree->jointree->fromlist);
474
	ListCell   *l;
475

476
	if (removert)
B
Bruce Momjian 已提交
477
	{
478
		foreach(l, newjointree)
479
		{
480
			RangeTblRef *rtr = lfirst(l);
481

482 483
			if (IsA(rtr, RangeTblRef) &&
				rtr->rtindex == rt_index)
484
			{
485
				newjointree = list_delete_ptr(newjointree, rtr);
B
Bruce Momjian 已提交
486 487

				/*
B
Bruce Momjian 已提交
488
				 * foreach is safe because we exit loop after list_delete...
B
Bruce Momjian 已提交
489
				 */
490 491
				break;
			}
492
		}
493
	}
494
	return newjointree;
495
}
496

497

498 499 500 501 502 503 504 505 506
/*
 * rewriteTargetList - rewrite INSERT/UPDATE targetlist into standard form
 *
 * This has the following responsibilities:
 *
 * 1. For an INSERT, add tlist entries to compute default values for any
 * attributes that have defaults and are not assigned to in the given tlist.
 * (We do not insert anything for default-less attributes, however.  The
 * planner will later insert NULLs for them, but there's no reason to slow
507 508 509
 * down rewriter processing with extra tlist nodes.)  Also, for both INSERT
 * and UPDATE, replace explicit DEFAULT specifications with column default
 * expressions.
510 511
 *
 * 2. Merge multiple entries for the same target attribute, or declare error
512 513 514
 * if we can't.  Multiple entries are only allowed for INSERT/UPDATE of
 * portions of an array or record field, for example
 *			UPDATE table SET foo[2] = 42, foo[4] = 43;
515 516 517 518 519 520 521 522
 * We can merge such operations into a single assignment op.  Essentially,
 * the expression we want to produce in this case is like
 *		foo = array_set(array_set(foo, 2, 42), 4, 43)
 *
 * 3. Sort the tlist into standard order: non-junk fields in order by resno,
 * then junk fields (these in no particular order).
 *
 * We must do items 1 and 2 before firing rewrite rules, else rewritten
B
Bruce Momjian 已提交
523
 * references to NEW.foo will produce wrong or incomplete results.	Item 3
524 525
 * is not needed for rewriting, but will be needed by the planner, and we
 * can do it essentially for free while handling items 1 and 2.
526 527 528 529 530
 *
 * If attrno_list isn't NULL, we return an additional output besides the
 * rewritten targetlist: an integer list of the assigned-to attnums, in
 * order of the original tlist's non-junk entries.  This is needed for
 * processing VALUES RTEs.
531 532
 */
static void
533 534
rewriteTargetList(Query *parsetree, Relation target_relation,
				  List **attrno_list)
535 536
{
	CmdType		commandType = parsetree->commandType;
537
	TargetEntry **new_tles;
538
	List	   *new_tlist = NIL;
539 540
	List	   *junk_tlist = NIL;
	Form_pg_attribute att_tup;
541
	int			attrno,
542
				next_junk_attrno,
543
				numattrs;
544
	ListCell   *temp;
545

546 547 548
	if (attrno_list)			/* initialize optional result list */
		*attrno_list = NIL;

549
	/*
B
Bruce Momjian 已提交
550 551 552 553
	 * We process the normal (non-junk) attributes by scanning the input tlist
	 * once and transferring TLEs into an array, then scanning the array to
	 * build an output tlist.  This avoids O(N^2) behavior for large numbers
	 * of attributes.
554
	 *
B
Bruce Momjian 已提交
555 556
	 * Junk attributes are tossed into a separate list during the same tlist
	 * scan, then appended to the reconstructed tlist.
557 558
	 */
	numattrs = RelationGetNumberOfAttributes(target_relation);
559 560
	new_tles = (TargetEntry **) palloc0(numattrs * sizeof(TargetEntry *));
	next_junk_attrno = numattrs + 1;
561

562
	foreach(temp, parsetree->targetList)
563
	{
564
		TargetEntry *old_tle = (TargetEntry *) lfirst(temp);
565

566
		if (!old_tle->resjunk)
567 568
		{
			/* Normal attr: stash it into new_tles[] */
569
			attrno = old_tle->resno;
570 571 572 573
			if (attrno < 1 || attrno > numattrs)
				elog(ERROR, "bogus resno %d in targetlist", attrno);
			att_tup = target_relation->rd_att->attrs[attrno - 1];

574 575 576 577
			/* put attrno into attrno_list even if it's dropped */
			if (attrno_list)
				*attrno_list = lappend_int(*attrno_list, attrno);

578 579 580 581 582 583 584 585 586 587 588
			/* We can (and must) ignore deleted attributes */
			if (att_tup->attisdropped)
				continue;

			/* Merge with any prior assignment to same attribute */
			new_tles[attrno - 1] =
				process_matched_tle(old_tle,
									new_tles[attrno - 1],
									NameStr(att_tup->attname));
		}
		else
589
		{
590
			/*
B
Bruce Momjian 已提交
591 592
			 * Copy all resjunk tlist entries to junk_tlist, and assign them
			 * resnos above the last real resno.
593
			 *
594 595
			 * Typical junk entries include ORDER BY or GROUP BY expressions
			 * (are these actually possible in an INSERT or UPDATE?), system
596 597
			 * attribute references, etc.
			 */
598

599
			/* Get the resno right, but don't copy unnecessarily */
600
			if (old_tle->resno != next_junk_attrno)
601
			{
602 603
				old_tle = flatCopyTargetEntry(old_tle);
				old_tle->resno = next_junk_attrno;
604
			}
605 606
			junk_tlist = lappend(junk_tlist, old_tle);
			next_junk_attrno++;
607
		}
608 609 610 611 612 613 614 615 616 617 618
	}

	for (attrno = 1; attrno <= numattrs; attrno++)
	{
		TargetEntry *new_tle = new_tles[attrno - 1];

		att_tup = target_relation->rd_att->attrs[attrno - 1];

		/* We can (and must) ignore deleted attributes */
		if (att_tup->attisdropped)
			continue;
619

620
		/*
B
Bruce Momjian 已提交
621 622 623
		 * Handle the two cases where we need to insert a default expression:
		 * it's an INSERT and there's no tlist entry for the column, or the
		 * tlist entry is a DEFAULT placeholder node.
624 625
		 */
		if ((new_tle == NULL && commandType == CMD_INSERT) ||
626
			(new_tle && new_tle->expr && IsA(new_tle->expr, SetToDefault)))
627 628 629 630 631
		{
			Node	   *new_expr;

			new_expr = build_column_default(target_relation, attrno);

632
			/*
B
Bruce Momjian 已提交
633 634 635 636 637
			 * If there is no default (ie, default is effectively NULL), we
			 * can omit the tlist entry in the INSERT case, since the planner
			 * can insert a NULL for itself, and there's no point in spending
			 * any more rewriter cycles on the entry.  But in the UPDATE case
			 * we've got to explicitly set the column to NULL.
638 639 640 641 642 643 644 645 646 647 648 649 650 651
			 */
			if (!new_expr)
			{
				if (commandType == CMD_INSERT)
					new_tle = NULL;
				else
				{
					new_expr = (Node *) makeConst(att_tup->atttypid,
												  att_tup->attlen,
												  (Datum) 0,
												  true, /* isnull */
												  att_tup->attbyval);
					/* this is to catch a NOT NULL domain constraint */
					new_expr = coerce_to_domain(new_expr,
652
												InvalidOid, -1,
653
												att_tup->atttypid,
654
												COERCE_IMPLICIT_CAST,
655
												false,
656
												false);
657 658 659
				}
			}

660
			if (new_expr)
661 662 663 664
				new_tle = makeTargetEntry((Expr *) new_expr,
										  attrno,
										  pstrdup(NameStr(att_tup->attname)),
										  false);
665 666 667 668 669 670
		}

		if (new_tle)
			new_tlist = lappend(new_tlist, new_tle);
	}

671
	pfree(new_tles);
672

673
	parsetree->targetList = list_concat(new_tlist, junk_tlist);
674 675 676 677 678 679 680
}


/*
 * Convert a matched TLE from the original tlist into a correct new TLE.
 *
 * This routine detects and handles multiple assignments to the same target
681
 * attribute.  (The attribute name is needed only for error messages.)
682 683 684
 */
static TargetEntry *
process_matched_tle(TargetEntry *src_tle,
685 686
					TargetEntry *prior_tle,
					const char *attrName)
687
{
688
	TargetEntry *result;
689 690 691 692
	Node	   *src_expr;
	Node	   *prior_expr;
	Node	   *src_input;
	Node	   *prior_input;
693
	Node	   *priorbottom;
694
	Node	   *newexpr;
695 696 697 698

	if (prior_tle == NULL)
	{
		/*
B
Bruce Momjian 已提交
699
		 * Normal case where this is the first assignment to the attribute.
700 701 702 703
		 */
		return src_tle;
	}

704
	/*----------
705
	 * Multiple assignments to same attribute.	Allow only if all are
706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722
	 * FieldStore or ArrayRef assignment operations.  This is a bit
	 * tricky because what we may actually be looking at is a nest of
	 * such nodes; consider
	 *		UPDATE tab SET col.fld1.subfld1 = x, col.fld2.subfld2 = y
	 * The two expressions produced by the parser will look like
	 *		FieldStore(col, fld1, FieldStore(placeholder, subfld1, x))
	 *		FieldStore(col, fld2, FieldStore(placeholder, subfld2, x))
	 * However, we can ignore the substructure and just consider the top
	 * FieldStore or ArrayRef from each assignment, because it works to
	 * combine these as
	 *		FieldStore(FieldStore(col, fld1,
	 *							  FieldStore(placeholder, subfld1, x)),
	 *				   fld2, FieldStore(placeholder, subfld2, x))
	 * Note the leftmost expression goes on the inside so that the
	 * assignments appear to occur left-to-right.
	 *
	 * For FieldStore, instead of nesting we can generate a single
B
Bruce Momjian 已提交
723
	 * FieldStore with multiple target fields.	We must nest when
724 725
	 * ArrayRefs are involved though.
	 *----------
726
	 */
727 728 729 730 731 732 733
	src_expr = (Node *) src_tle->expr;
	prior_expr = (Node *) prior_tle->expr;
	src_input = get_assignment_input(src_expr);
	prior_input = get_assignment_input(prior_expr);
	if (src_input == NULL ||
		prior_input == NULL ||
		exprType(src_expr) != exprType(prior_expr))
734 735
		ereport(ERROR,
				(errcode(ERRCODE_SYNTAX_ERROR),
736
				 errmsg("multiple assignments to same column \"%s\"",
737
						attrName)));
738 739

	/*
B
Bruce Momjian 已提交
740
	 * Prior TLE could be a nest of assignments if we do this more than once.
741
	 */
742 743 744
	priorbottom = prior_input;
	for (;;)
	{
B
Bruce Momjian 已提交
745
		Node	   *newbottom = get_assignment_input(priorbottom);
746 747 748 749 750 751

		if (newbottom == NULL)
			break;				/* found the original Var reference */
		priorbottom = newbottom;
	}
	if (!equal(priorbottom, src_input))
752 753
		ereport(ERROR,
				(errcode(ERRCODE_SYNTAX_ERROR),
754
				 errmsg("multiple assignments to same column \"%s\"",
755
						attrName)));
756 757 758 759

	/*
	 * Looks OK to nest 'em.
	 */
760 761
	if (IsA(src_expr, FieldStore))
	{
B
Bruce Momjian 已提交
762
		FieldStore *fstore = makeNode(FieldStore);
763 764 765 766 767 768 769

		if (IsA(prior_expr, FieldStore))
		{
			/* combine the two */
			memcpy(fstore, prior_expr, sizeof(FieldStore));
			fstore->newvals =
				list_concat(list_copy(((FieldStore *) prior_expr)->newvals),
B
Bruce Momjian 已提交
770
							list_copy(((FieldStore *) src_expr)->newvals));
771 772
			fstore->fieldnums =
				list_concat(list_copy(((FieldStore *) prior_expr)->fieldnums),
B
Bruce Momjian 已提交
773
							list_copy(((FieldStore *) src_expr)->fieldnums));
774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795
		}
		else
		{
			/* general case, just nest 'em */
			memcpy(fstore, src_expr, sizeof(FieldStore));
			fstore->arg = (Expr *) prior_expr;
		}
		newexpr = (Node *) fstore;
	}
	else if (IsA(src_expr, ArrayRef))
	{
		ArrayRef   *aref = makeNode(ArrayRef);

		memcpy(aref, src_expr, sizeof(ArrayRef));
		aref->refexpr = (Expr *) prior_expr;
		newexpr = (Node *) aref;
	}
	else
	{
		elog(ERROR, "can't happen");
		newexpr = NULL;
	}
796

797 798 799
	result = flatCopyTargetEntry(src_tle);
	result->expr = (Expr *) newexpr;
	return result;
800 801
}

802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825
/*
 * If node is an assignment node, return its input; else return NULL
 */
static Node *
get_assignment_input(Node *node)
{
	if (node == NULL)
		return NULL;
	if (IsA(node, FieldStore))
	{
		FieldStore *fstore = (FieldStore *) node;

		return (Node *) fstore->arg;
	}
	else if (IsA(node, ArrayRef))
	{
		ArrayRef   *aref = (ArrayRef *) node;

		if (aref->refassgnexpr == NULL)
			return NULL;
		return (Node *) aref->refexpr;
	}
	return NULL;
}
826 827 828 829 830 831

/*
 * Make an expression tree for the default value for a column.
 *
 * If there is no default, return a NULL instead.
 */
832
Node *
833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865
build_column_default(Relation rel, int attrno)
{
	TupleDesc	rd_att = rel->rd_att;
	Form_pg_attribute att_tup = rd_att->attrs[attrno - 1];
	Oid			atttype = att_tup->atttypid;
	int32		atttypmod = att_tup->atttypmod;
	Node	   *expr = NULL;
	Oid			exprtype;

	/*
	 * Scan to see if relation has a default for this column.
	 */
	if (rd_att->constr && rd_att->constr->num_defval > 0)
	{
		AttrDefault *defval = rd_att->constr->defval;
		int			ndef = rd_att->constr->num_defval;

		while (--ndef >= 0)
		{
			if (attrno == defval[ndef].adnum)
			{
				/*
				 * Found it, convert string representation to node tree.
				 */
				expr = stringToNode(defval[ndef].adbin);
				break;
			}
		}
	}

	if (expr == NULL)
	{
		/*
B
Bruce Momjian 已提交
866
		 * No per-column default, so look for a default for the type itself.
867
		 */
868
		expr = get_typdefault(atttype);
869 870 871 872 873 874
	}

	if (expr == NULL)
		return NULL;			/* No default anywhere */

	/*
875 876
	 * Make sure the value is coerced to the target column type; this will
	 * generally be true already, but there seem to be some corner cases
B
Bruce Momjian 已提交
877 878
	 * involving domain defaults where it might not be true. This should match
	 * the parser's processing of non-defaulted expressions --- see
879
	 * transformAssignedExpr().
880 881 882
	 */
	exprtype = exprType(expr);

B
Bruce Momjian 已提交
883
	expr = coerce_to_target_type(NULL,	/* no UNKNOWN params here */
884
								 expr, exprtype,
885 886 887 888
								 atttype, atttypmod,
								 COERCION_ASSIGNMENT,
								 COERCE_IMPLICIT_CAST);
	if (expr == NULL)
889 890 891 892 893 894 895
		ereport(ERROR,
				(errcode(ERRCODE_DATATYPE_MISMATCH),
				 errmsg("column \"%s\" is of type %s"
						" but default expression is of type %s",
						NameStr(att_tup->attname),
						format_type_be(atttype),
						format_type_be(exprtype)),
B
Bruce Momjian 已提交
896
			   errhint("You will need to rewrite or cast the expression.")));
897 898 899 900 901

	return expr;
}


902 903 904 905 906 907 908 909
/* Does VALUES RTE contain any SetToDefault items? */
static bool
searchForDefault(RangeTblEntry *rte)
{
	ListCell   *lc;

	foreach(lc, rte->values_lists)
	{
B
Bruce Momjian 已提交
910 911
		List	   *sublist = (List *) lfirst(lc);
		ListCell   *lc2;
912 913 914

		foreach(lc2, sublist)
		{
B
Bruce Momjian 已提交
915
			Node	   *col = (Node *) lfirst(lc2);
916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954

			if (IsA(col, SetToDefault))
				return true;
		}
	}
	return false;
}

/*
 * When processing INSERT ... VALUES with a VALUES RTE (ie, multiple VALUES
 * lists), we have to replace any DEFAULT items in the VALUES lists with
 * the appropriate default expressions.  The other aspects of rewriteTargetList
 * need be applied only to the query's targetlist proper.
 *
 * Note that we currently can't support subscripted or field assignment
 * in the multi-VALUES case.  The targetlist will contain simple Vars
 * referencing the VALUES RTE, and therefore process_matched_tle() will
 * reject any such attempt with "multiple assignments to same column".
 */
static void
rewriteValuesRTE(RangeTblEntry *rte, Relation target_relation, List *attrnos)
{
	List	   *newValues;
	ListCell   *lc;

	/*
	 * Rebuilding all the lists is a pretty expensive proposition in a big
	 * VALUES list, and it's a waste of time if there aren't any DEFAULT
	 * placeholders.  So first scan to see if there are any.
	 */
	if (!searchForDefault(rte))
		return;					/* nothing to do */

	/* Check list lengths (we can assume all the VALUES sublists are alike) */
	Assert(list_length(attrnos) == list_length(linitial(rte->values_lists)));

	newValues = NIL;
	foreach(lc, rte->values_lists)
	{
B
Bruce Momjian 已提交
955 956 957 958
		List	   *sublist = (List *) lfirst(lc);
		List	   *newList = NIL;
		ListCell   *lc2;
		ListCell   *lc3;
959 960 961

		forboth(lc2, sublist, lc3, attrnos)
		{
B
Bruce Momjian 已提交
962 963
			Node	   *col = (Node *) lfirst(lc2);
			int			attrno = lfirst_int(lc3);
964 965 966 967 968 969 970 971 972 973 974

			if (IsA(col, SetToDefault))
			{
				Form_pg_attribute att_tup;
				Node	   *new_expr;

				att_tup = target_relation->rd_att->attrs[attrno - 1];

				if (!att_tup->attisdropped)
					new_expr = build_column_default(target_relation, attrno);
				else
B
Bruce Momjian 已提交
975
					new_expr = NULL;	/* force a NULL if dropped */
976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006

				/*
				 * If there is no default (ie, default is effectively NULL),
				 * we've got to explicitly set the column to NULL.
				 */
				if (!new_expr)
				{
					new_expr = (Node *) makeConst(att_tup->atttypid,
												  att_tup->attlen,
												  (Datum) 0,
												  true, /* isnull */
												  att_tup->attbyval);
					/* this is to catch a NOT NULL domain constraint */
					new_expr = coerce_to_domain(new_expr,
												InvalidOid, -1,
												att_tup->atttypid,
												COERCE_IMPLICIT_CAST,
												false,
												false);
				}
				newList = lappend(newList, new_expr);
			}
			else
				newList = lappend(newList, col);
		}
		newValues = lappend(newValues, newList);
	}
	rte->values_lists = newValues;
}


1007
/*
1008 1009
 * matchLocks -
 *	  match the list of locks and returns the matching rules
1010
 */
1011 1012 1013 1014 1015
static List *
matchLocks(CmdType event,
		   RuleLock *rulelocks,
		   int varno,
		   Query *parsetree)
1016
{
1017
	List	   *matching_locks = NIL;
1018 1019
	int			nlocks;
	int			i;
1020

1021 1022
	if (rulelocks == NULL)
		return NIL;
1023

1024
	if (parsetree->commandType != CMD_SELECT)
1025
	{
1026 1027
		if (parsetree->resultRelation != varno)
			return NIL;
1028
	}
1029

1030
	nlocks = rulelocks->numLocks;
1031

1032
	for (i = 0; i < nlocks; i++)
B
Bruce Momjian 已提交
1033
	{
1034
		RewriteRule *oneLock = rulelocks->rules[i];
1035

1036
		if (oneLock->event == event)
1037
		{
1038 1039 1040 1041 1042
			if (parsetree->commandType != CMD_SELECT ||
				(oneLock->attrno == -1 ?
				 rangeTableEntry_used((Node *) parsetree, varno, 0) :
				 attribute_used((Node *) parsetree,
								varno, oneLock->attrno, 0)))
1043
				matching_locks = lappend(matching_locks, oneLock);
1044
		}
1045
	}
1046

1047
	return matching_locks;
1048 1049
}

1050

1051 1052 1053
/*
 * ApplyRetrieveRule - expand an ON SELECT rule
 */
1054 1055 1056 1057 1058 1059
static Query *
ApplyRetrieveRule(Query *parsetree,
				  RewriteRule *rule,
				  int rt_index,
				  bool relation_level,
				  Relation relation,
1060
				  List *activeRIRs)
1061 1062 1063 1064
{
	Query	   *rule_action;
	RangeTblEntry *rte,
			   *subrte;
1065
	RowMarkClause *rc;
1066

1067
	if (list_length(rule->actions) != 1)
1068
		elog(ERROR, "expected just one rule action");
1069
	if (rule->qual != NULL)
1070
		elog(ERROR, "cannot handle qualified ON SELECT rule");
B
Bruce Momjian 已提交
1071
	if (!relation_level)
1072
		elog(ERROR, "cannot handle per-attribute ON SELECT rule");
1073

1074
	/*
B
Bruce Momjian 已提交
1075 1076
	 * Make a modifiable copy of the view query, and acquire needed locks on
	 * the relations it mentions.
1077
	 */
1078
	rule_action = copyObject(linitial(rule->actions));
1079

1080 1081 1082 1083 1084
	AcquireRewriteLocks(rule_action);

	/*
	 * Recursively expand any view references inside the view.
	 */
1085
	rule_action = fireRIRrules(rule_action, activeRIRs);
1086

1087
	/*
B
Bruce Momjian 已提交
1088 1089
	 * VIEWs are really easy --- just plug the view query in as a subselect,
	 * replacing the relation's original RTE.
1090
	 */
1091
	rte = rt_fetch(rt_index, parsetree->rtable);
1092

1093
	rte->rtekind = RTE_SUBQUERY;
1094 1095 1096
	rte->relid = InvalidOid;
	rte->subquery = rule_action;
	rte->inh = false;			/* must not be set for a subquery */
1097

1098
	/*
B
Bruce Momjian 已提交
1099 1100
	 * We move the view's permission check data down to its rangetable. The
	 * checks will actually be done against the *OLD* entry therein.
1101
	 */
1102 1103
	subrte = rt_fetch(PRS2_OLD_VARNO, rule_action->rtable);
	Assert(subrte->relid == relation->rd_id);
1104
	subrte->requiredPerms = rte->requiredPerms;
1105
	subrte->checkAsUser = rte->checkAsUser;
1106

1107
	rte->requiredPerms = 0;		/* no permission check on subquery itself */
1108
	rte->checkAsUser = InvalidOid;
1109

1110
	/*
1111
	 * FOR UPDATE/SHARE of view?
1112
	 */
1113
	if ((rc = get_rowmark(parsetree, rt_index)) != NULL)
1114
	{
1115
		/*
B
Bruce Momjian 已提交
1116
		 * Remove the view from the list of rels that will actually be marked
1117
		 * FOR UPDATE/SHARE by the executor.  It will still be access-checked
B
Bruce Momjian 已提交
1118
		 * for write access, though.
1119
		 */
1120
		parsetree->rowMarks = list_delete_ptr(parsetree->rowMarks, rc);
B
Bruce Momjian 已提交
1121 1122

		/*
1123
		 * Set up the view's referenced tables as if FOR UPDATE/SHARE.
1124
		 */
1125 1126
		markQueryForLocking(rule_action, rc->forUpdate,
							rc->noWait, true);
1127 1128
	}

1129
	return parsetree;
1130 1131
}

1132
/*
1133
 * Recursively mark all relations used by a view as FOR UPDATE/SHARE.
1134 1135 1136 1137
 *
 * This may generate an invalid query, eg if some sub-query uses an
 * aggregate.  We leave it to the planner to detect that.
 *
1138
 * NB: this must agree with the parser's transformLocking() routine.
1139 1140
 */
static void
1141
markQueryForLocking(Query *qry, bool forUpdate, bool noWait, bool skipOldNew)
1142 1143
{
	Index		rti = 0;
1144
	ListCell   *l;
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156

	foreach(l, qry->rtable)
	{
		RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);

		rti++;

		/* Ignore OLD and NEW entries if we are at top level of view */
		if (skipOldNew &&
			(rti == PRS2_OLD_VARNO || rti == PRS2_NEW_VARNO))
			continue;

1157
		if (rte->rtekind == RTE_RELATION)
1158
		{
1159
			applyLockingClause(qry, rti, forUpdate, noWait);
1160
			rte->requiredPerms |= ACL_SELECT_FOR_UPDATE;
1161
		}
1162 1163
		else if (rte->rtekind == RTE_SUBQUERY)
		{
1164
			/* FOR UPDATE/SHARE of subquery is propagated to subquery's rels */
1165
			markQueryForLocking(rte->subquery, forUpdate, noWait, false);
1166
		}
1167 1168 1169
	}
}

1170

1171
/*
1172 1173 1174
 * fireRIRonSubLink -
 *	Apply fireRIRrules() to each SubLink (subselect in expression) found
 *	in the given tree.
1175 1176
 *
 * NOTE: although this has the form of a walker, we cheat and modify the
1177
 * SubLink nodes in-place.	It is caller's responsibility to ensure that
1178
 * no unwanted side-effects occur!
1179 1180 1181 1182
 *
 * This is unlike most of the other routines that recurse into subselects,
 * because we must take control at the SubLink node in order to replace
 * the SubLink's subselect link with the possibly-rewritten subquery.
1183 1184
 */
static bool
1185
fireRIRonSubLink(Node *node, List *activeRIRs)
1186 1187
{
	if (node == NULL)
1188 1189
		return false;
	if (IsA(node, SubLink))
B
Bruce Momjian 已提交
1190
	{
1191 1192 1193
		SubLink    *sub = (SubLink *) node;

		/* Do what we came for */
1194 1195
		sub->subselect = (Node *) fireRIRrules((Query *) sub->subselect,
											   activeRIRs);
1196
		/* Fall through to process lefthand args of SubLink */
1197
	}
B
Bruce Momjian 已提交
1198

1199
	/*
B
Bruce Momjian 已提交
1200 1201
	 * Do NOT recurse into Query nodes, because fireRIRrules already processed
	 * subselects of subselects for us.
1202
	 */
1203
	return expression_tree_walker(node, fireRIRonSubLink,
1204
								  (void *) activeRIRs);
1205 1206 1207 1208 1209 1210 1211 1212
}


/*
 * fireRIRrules -
 *	Apply all RIR rules on each rangetable entry in a query
 */
static Query *
1213
fireRIRrules(Query *parsetree, List *activeRIRs)
1214
{
B
Bruce Momjian 已提交
1215
	int			rt_index;
1216

1217
	/*
B
Bruce Momjian 已提交
1218 1219
	 * don't try to convert this into a foreach loop, because rtable list can
	 * get changed each time through...
1220
	 */
1221
	rt_index = 0;
1222
	while (rt_index < list_length(parsetree->rtable))
B
Bruce Momjian 已提交
1223
	{
1224 1225 1226 1227 1228 1229 1230
		RangeTblEntry *rte;
		Relation	rel;
		List	   *locks;
		RuleLock   *rules;
		RewriteRule *rule;
		int			i;

1231 1232
		++rt_index;

1233
		rte = rt_fetch(rt_index, parsetree->rtable);
1234

1235
		/*
B
Bruce Momjian 已提交
1236 1237
		 * A subquery RTE can't have associated rules, so there's nothing to
		 * do to this level of the query, but we must recurse into the
1238 1239
		 * subquery to expand any rule references in it.
		 */
1240
		if (rte->rtekind == RTE_SUBQUERY)
1241
		{
1242
			rte->subquery = fireRIRrules(rte->subquery, activeRIRs);
1243 1244 1245
			continue;
		}

1246 1247 1248 1249 1250 1251
		/*
		 * Joins and other non-relation RTEs can be ignored completely.
		 */
		if (rte->rtekind != RTE_RELATION)
			continue;

1252
		/*
1253 1254 1255
		 * If the table is not referenced in the query, then we ignore it.
		 * This prevents infinite expansion loop due to new rtable entries
		 * inserted by expansion of a rule. A table is referenced if it is
B
Bruce Momjian 已提交
1256 1257
		 * part of the join set (a source table), or is referenced by any Var
		 * nodes, or is the result table.
1258
		 */
1259 1260
		if (rt_index != parsetree->resultRelation &&
			!rangeTableEntry_used((Node *) parsetree, rt_index, 0))
1261
			continue;
B
Bruce Momjian 已提交
1262

1263
		/*
1264 1265
		 * We can use NoLock here since either the parser or
		 * AcquireRewriteLocks should have locked the rel already.
1266
		 */
1267
		rel = heap_open(rte->relid, NoLock);
1268 1269 1270 1271

		/*
		 * Collect the RIR rules that we must apply
		 */
1272 1273
		rules = rel->rd_rules;
		if (rules == NULL)
B
Bruce Momjian 已提交
1274
		{
1275
			heap_close(rel, NoLock);
1276 1277
			continue;
		}
1278
		locks = NIL;
B
Bruce Momjian 已提交
1279 1280
		for (i = 0; i < rules->numLocks; i++)
		{
1281 1282 1283
			rule = rules->rules[i];
			if (rule->event != CMD_SELECT)
				continue;
B
Bruce Momjian 已提交
1284

1285 1286 1287
			if (rule->attrno > 0)
			{
				/* per-attr rule; do we need it? */
1288
				if (!attribute_used((Node *) parsetree, rt_index,
1289
									rule->attrno, 0))
1290 1291
					continue;
			}
1292 1293 1294 1295 1296

			locks = lappend(locks, rule);
		}

		/*
1297
		 * If we found any, apply them --- but first check for recursion!
1298
		 */
1299
		if (locks != NIL)
B
Bruce Momjian 已提交
1300
		{
1301
			ListCell   *l;
1302

1303
			if (list_member_oid(activeRIRs, RelationGetRelid(rel)))
1304 1305 1306 1307
				ereport(ERROR,
						(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
						 errmsg("infinite recursion detected in rules for relation \"%s\"",
								RelationGetRelationName(rel))));
1308
			activeRIRs = lcons_oid(RelationGetRelid(rel), activeRIRs);
1309 1310 1311 1312 1313 1314 1315 1316 1317 1318

			foreach(l, locks)
			{
				rule = lfirst(l);

				parsetree = ApplyRetrieveRule(parsetree,
											  rule,
											  rt_index,
											  rule->attrno == -1,
											  rel,
1319
											  activeRIRs);
1320
			}
1321 1322

			activeRIRs = list_delete_first(activeRIRs);
1323 1324
		}

1325
		heap_close(rel, NoLock);
1326 1327
	}

1328
	/*
B
Bruce Momjian 已提交
1329 1330
	 * Recurse into sublink subqueries, too.  But we already did the ones in
	 * the rtable.
1331 1332
	 */
	if (parsetree->hasSubLinks)
1333
		query_tree_walker(parsetree, fireRIRonSubLink, (void *) activeRIRs,
1334
						  QTW_IGNORE_RT_SUBQUERIES);
1335 1336 1337 1338 1339

	return parsetree;
}


1340
/*
1341 1342 1343 1344 1345
 * Modify the given query by adding 'AND rule_qual IS NOT TRUE' to its
 * qualification.  This is used to generate suitable "else clauses" for
 * conditional INSTEAD rules.  (Unfortunately we must use "x IS NOT TRUE",
 * not just "NOT x" which the planner is much smarter about, else we will
 * do the wrong thing when the qual evaluates to NULL.)
1346
 *
B
Bruce Momjian 已提交
1347
 * The rule_qual may contain references to OLD or NEW.	OLD references are
1348 1349 1350 1351 1352
 * replaced by references to the specified rt_index (the relation that the
 * rule applies to).  NEW references are only possible for INSERT and UPDATE
 * queries on the relation itself, and so they should be replaced by copies
 * of the related entries in the query's own targetlist.
 */
1353
static Query *
1354 1355 1356 1357
CopyAndAddInvertedQual(Query *parsetree,
					   Node *rule_qual,
					   int rt_index,
					   CmdType event)
1358
{
1359
	/* Don't scribble on the passed qual (it's in the relcache!) */
1360 1361
	Node	   *new_qual = (Node *) copyObject(rule_qual);

1362 1363 1364
	/*
	 * In case there are subqueries in the qual, acquire necessary locks and
	 * fix any deleted JOIN RTE entries.  (This is somewhat redundant with
B
Bruce Momjian 已提交
1365 1366
	 * rewriteRuleAction, but not entirely ... consider restructuring so that
	 * we only need to process the qual this way once.)
1367 1368 1369
	 */
	(void) acquireLocksOnSubLinks(new_qual, NULL);

1370 1371 1372 1373 1374 1375 1376
	/* Fix references to OLD */
	ChangeVarNodes(new_qual, PRS2_OLD_VARNO, rt_index, 0);
	/* Fix references to NEW */
	if (event == CMD_INSERT || event == CMD_UPDATE)
		new_qual = ResolveNew(new_qual,
							  PRS2_NEW_VARNO,
							  0,
1377
							  rt_fetch(rt_index, parsetree->rtable),
1378 1379 1380 1381
							  parsetree->targetList,
							  event,
							  rt_index);
	/* And attach the fixed qual */
1382
	AddInvertedQual(parsetree, new_qual);
1383

1384
	return parsetree;
1385 1386 1387 1388
}


/*
1389
 *	fireRules -
M
 
Marc G. Fournier 已提交
1390
 *	   Iterate through rule locks applying rules.
1391
 *
1392 1393 1394 1395 1396 1397 1398 1399
 * Input arguments:
 *	parsetree - original query
 *	rt_index - RT index of result relation in original query
 *	event - type of rule event
 *	locks - list of rules to fire
 * Output arguments:
 *	*instead_flag - set TRUE if any unqualified INSTEAD rule is found
 *					(must be initialized to FALSE)
1400 1401
 *	*returning_flag - set TRUE if we rewrite RETURNING clause in any rule
 *					(must be initialized to FALSE)
1402 1403 1404 1405
 *	*qual_product - filled with modified original query if any qualified
 *					INSTEAD rule is found (must be initialized to NULL)
 * Return value:
 *	list of rule actions adjusted for use with this query
1406
 *
1407 1408 1409 1410 1411 1412
 * Qualified INSTEAD rules generate their action with the qualification
 * condition added.  They also generate a modified version of the original
 * query with the negated qualification added, so that it will run only for
 * rows that the qualified action doesn't act on.  (If there are multiple
 * qualified INSTEAD rules, we AND all the negated quals onto a single
 * modified original query.)  We won't execute the original, unmodified
B
Bruce Momjian 已提交
1413
 * query if we find either qualified or unqualified INSTEAD rules.	If
1414
 * we find both, the modified original query is discarded too.
1415
 */
1416
static List *
1417
fireRules(Query *parsetree,
1418 1419
		  int rt_index,
		  CmdType event,
1420
		  List *locks,
1421
		  bool *instead_flag,
1422
		  bool *returning_flag,
1423
		  Query **qual_product)
1424
{
1425
	List	   *results = NIL;
1426
	ListCell   *l;
1427

1428
	foreach(l, locks)
1429
	{
1430
		RewriteRule *rule_lock = (RewriteRule *) lfirst(l);
1431 1432
		Node	   *event_qual = rule_lock->qual;
		List	   *actions = rule_lock->actions;
B
Bruce Momjian 已提交
1433
		QuerySource qsrc;
1434
		ListCell   *r;
1435

1436 1437 1438 1439 1440 1441
		/* Determine correct QuerySource value for actions */
		if (rule_lock->isInstead)
		{
			if (event_qual != NULL)
				qsrc = QSRC_QUAL_INSTEAD_RULE;
			else
1442
			{
1443
				qsrc = QSRC_INSTEAD_RULE;
B
Bruce Momjian 已提交
1444
				*instead_flag = true;	/* report unqualified INSTEAD */
1445
			}
1446 1447 1448 1449 1450
		}
		else
			qsrc = QSRC_NON_INSTEAD_RULE;

		if (qsrc == QSRC_QUAL_INSTEAD_RULE)
1451
		{
1452
			/*
B
Bruce Momjian 已提交
1453 1454 1455 1456 1457 1458 1459
			 * If there are INSTEAD rules with qualifications, the original
			 * query is still performed. But all the negated rule
			 * qualifications of the INSTEAD rules are added so it does its
			 * actions only in cases where the rule quals of all INSTEAD rules
			 * are false. Think of it as the default action in a case. We save
			 * this in *qual_product so RewriteQuery() can add it to the query
			 * list after we mangled it up enough.
1460
			 *
B
Bruce Momjian 已提交
1461 1462
			 * If we have already found an unqualified INSTEAD rule, then
			 * *qual_product won't be used, so don't bother building it.
M
 
Marc G. Fournier 已提交
1463
			 */
B
Bruce Momjian 已提交
1464
			if (!*instead_flag)
1465 1466
			{
				if (*qual_product == NULL)
1467
					*qual_product = copyObject(parsetree);
1468 1469 1470 1471
				*qual_product = CopyAndAddInvertedQual(*qual_product,
													   event_qual,
													   rt_index,
													   event);
1472
			}
M
 
Marc G. Fournier 已提交
1473 1474
		}

1475
		/* Now process the rule's actions and add them to the result list */
1476 1477
		foreach(r, actions)
		{
1478
			Query	   *rule_action = lfirst(r);
1479

M
 
Marc G. Fournier 已提交
1480 1481 1482
			if (rule_action->commandType == CMD_NOTHING)
				continue;

1483
			rule_action = rewriteRuleAction(parsetree, rule_action,
1484 1485
											event_qual, rt_index, event,
											returning_flag);
1486

1487
			rule_action->querySource = qsrc;
1488
			rule_action->canSetTag = false;		/* might change later */
1489

1490
			results = lappend(results, rule_action);
1491 1492
		}
	}
1493

1494
	return results;
1495 1496
}

M
 
Marc G. Fournier 已提交
1497

1498
/*
1499 1500
 * RewriteQuery -
 *	  rewrites the query and apply the rules again on the queries rewritten
1501
 *
1502 1503
 * rewrite_events is a list of open query-rewrite actions, so we can detect
 * infinite recursion.
1504
 */
1505
static List *
1506
RewriteQuery(Query *parsetree, List *rewrite_events)
1507
{
1508 1509
	CmdType		event = parsetree->commandType;
	bool		instead = false;
1510
	bool		returning = false;
1511 1512
	Query	   *qual_product = NULL;
	List	   *rewritten = NIL;
1513

1514
	/*
1515 1516
	 * If the statement is an update, insert or delete - fire rules on it.
	 *
B
Bruce Momjian 已提交
1517 1518 1519
	 * SELECT rules are handled later when we have all the queries that should
	 * get executed.  Also, utilities aren't rewritten at all (do we still
	 * need that check?)
1520
	 */
1521 1522 1523 1524 1525 1526
	if (event != CMD_SELECT && event != CMD_UTILITY)
	{
		int			result_relation;
		RangeTblEntry *rt_entry;
		Relation	rt_entry_relation;
		List	   *locks;
1527

1528 1529 1530 1531
		result_relation = parsetree->resultRelation;
		Assert(result_relation != 0);
		rt_entry = rt_fetch(result_relation, parsetree->rtable);
		Assert(rt_entry->rtekind == RTE_RELATION);
M
 
Marc G. Fournier 已提交
1532

1533
		/*
1534 1535
		 * We can use NoLock here since either the parser or
		 * AcquireRewriteLocks should have locked the rel already.
1536
		 */
1537
		rt_entry_relation = heap_open(rt_entry->relid, NoLock);
1538

1539
		/*
B
Bruce Momjian 已提交
1540 1541 1542
		 * If it's an INSERT or UPDATE, rewrite the targetlist into standard
		 * form.  This will be needed by the planner anyway, and doing it now
		 * ensures that any references to NEW.field will behave sanely.
1543
		 */
1544 1545 1546 1547 1548 1549 1550
		if (event == CMD_UPDATE)
			rewriteTargetList(parsetree, rt_entry_relation, NULL);
		else if (event == CMD_INSERT)
		{
			RangeTblEntry *values_rte = NULL;

			/*
B
Bruce Momjian 已提交
1551 1552
			 * If it's an INSERT ... VALUES (...), (...), ... there will be a
			 * single RTE for the VALUES targetlists.
1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569
			 */
			if (list_length(parsetree->jointree->fromlist) == 1)
			{
				RangeTblRef *rtr = (RangeTblRef *) linitial(parsetree->jointree->fromlist);

				if (IsA(rtr, RangeTblRef))
				{
					RangeTblEntry *rte = rt_fetch(rtr->rtindex,
												  parsetree->rtable);

					if (rte->rtekind == RTE_VALUES)
						values_rte = rte;
				}
			}

			if (values_rte)
			{
B
Bruce Momjian 已提交
1570
				List	   *attrnos;
1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582

				/* Process the main targetlist ... */
				rewriteTargetList(parsetree, rt_entry_relation, &attrnos);
				/* ... and the VALUES expression lists */
				rewriteValuesRTE(values_rte, rt_entry_relation, attrnos);
			}
			else
			{
				/* Process just the main targetlist */
				rewriteTargetList(parsetree, rt_entry_relation, NULL);
			}
		}
1583

1584 1585 1586 1587 1588
		/*
		 * Collect and apply the appropriate rules.
		 */
		locks = matchLocks(event, rt_entry_relation->rd_rules,
						   result_relation, parsetree);
1589

1590 1591 1592
		if (locks != NIL)
		{
			List	   *product_queries;
1593

1594 1595 1596 1597 1598
			product_queries = fireRules(parsetree,
										result_relation,
										event,
										locks,
										&instead,
1599
										&returning,
1600
										&qual_product);
1601

1602
			/*
B
Bruce Momjian 已提交
1603 1604
			 * If we got any product queries, recursively rewrite them --- but
			 * first check for recursion!
1605 1606 1607
			 */
			if (product_queries != NIL)
			{
B
Bruce Momjian 已提交
1608 1609
				ListCell   *n;
				rewrite_event *rev;
1610

1611 1612 1613 1614 1615
				foreach(n, rewrite_events)
				{
					rev = (rewrite_event *) lfirst(n);
					if (rev->relation == RelationGetRelid(rt_entry_relation) &&
						rev->event == event)
1616
						ereport(ERROR,
B
Bruce Momjian 已提交
1617 1618 1619
								(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
								 errmsg("infinite recursion detected in rules for relation \"%s\"",
							   RelationGetRelationName(rt_entry_relation))));
1620
				}
1621

1622 1623 1624 1625
				rev = (rewrite_event *) palloc(sizeof(rewrite_event));
				rev->relation = RelationGetRelid(rt_entry_relation);
				rev->event = event;
				rewrite_events = lcons(rev, rewrite_events);
1626

1627 1628 1629 1630
				foreach(n, product_queries)
				{
					Query	   *pt = (Query *) lfirst(n);
					List	   *newstuff;
1631

1632
					newstuff = RewriteQuery(pt, rewrite_events);
1633
					rewritten = list_concat(rewritten, newstuff);
1634
				}
1635 1636

				rewrite_events = list_delete_first(rewrite_events);
1637 1638
			}
		}
1639

1640
		/*
B
Bruce Momjian 已提交
1641 1642 1643 1644 1645
		 * If there is an INSTEAD, and the original query has a RETURNING, we
		 * have to have found a RETURNING in the rule(s), else fail. (Because
		 * DefineQueryRewrite only allows RETURNING in unconditional INSTEAD
		 * rules, there's no need to worry whether the substituted RETURNING
		 * will actually be executed --- it must be.)
1646 1647 1648 1649 1650 1651 1652 1653 1654 1655
		 */
		if ((instead || qual_product != NULL) &&
			parsetree->returningList &&
			!returning)
		{
			switch (event)
			{
				case CMD_INSERT:
					ereport(ERROR,
							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
B
Bruce Momjian 已提交
1656 1657
						 errmsg("cannot INSERT RETURNING on relation \"%s\"",
								RelationGetRelationName(rt_entry_relation)),
1658 1659 1660 1661 1662
							 errhint("You need an unconditional ON INSERT DO INSTEAD rule with a RETURNING clause.")));
					break;
				case CMD_UPDATE:
					ereport(ERROR,
							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
B
Bruce Momjian 已提交
1663 1664
						 errmsg("cannot UPDATE RETURNING on relation \"%s\"",
								RelationGetRelationName(rt_entry_relation)),
1665 1666 1667 1668 1669
							 errhint("You need an unconditional ON UPDATE DO INSTEAD rule with a RETURNING clause.")));
					break;
				case CMD_DELETE:
					ereport(ERROR,
							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
B
Bruce Momjian 已提交
1670 1671
						 errmsg("cannot DELETE RETURNING on relation \"%s\"",
								RelationGetRelationName(rt_entry_relation)),
1672 1673 1674 1675 1676 1677 1678 1679 1680
							 errhint("You need an unconditional ON DELETE DO INSTEAD rule with a RETURNING clause.")));
					break;
				default:
					elog(ERROR, "unrecognized commandType: %d",
						 (int) event);
					break;
			}
		}

1681
		heap_close(rt_entry_relation, NoLock);
1682
	}
M
 
Marc G. Fournier 已提交
1683

1684
	/*
B
Bruce Momjian 已提交
1685 1686 1687 1688 1689 1690
	 * For INSERTs, the original query is done first; for UPDATE/DELETE, it is
	 * done last.  This is needed because update and delete rule actions might
	 * not do anything if they are invoked after the update or delete is
	 * performed. The command counter increment between the query executions
	 * makes the deleted (and maybe the updated) tuples disappear so the scans
	 * for them in the rule actions cannot find them.
1691
	 *
B
Bruce Momjian 已提交
1692 1693 1694
	 * If we found any unqualified INSTEAD, the original query is not done at
	 * all, in any form.  Otherwise, we add the modified form if qualified
	 * INSTEADs were found, else the unmodified form.
M
 
Marc G. Fournier 已提交
1695
	 */
1696
	if (!instead)
1697
	{
1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711
		if (parsetree->commandType == CMD_INSERT)
		{
			if (qual_product != NULL)
				rewritten = lcons(qual_product, rewritten);
			else
				rewritten = lcons(parsetree, rewritten);
		}
		else
		{
			if (qual_product != NULL)
				rewritten = lappend(rewritten, qual_product);
			else
				rewritten = lappend(rewritten, parsetree);
		}
1712
	}
M
 
Marc G. Fournier 已提交
1713

1714 1715
	return rewritten;
}
1716 1717 1718


/*
1719 1720 1721 1722 1723
 * QueryRewrite -
 *	  Primary entry point to the query rewriter.
 *	  Rewrite one query via query rewrite system, possibly returning 0
 *	  or many queries.
 *
1724 1725
 * NOTE: the parsetree must either have come straight from the parser,
 * or have been scanned by AcquireRewriteLocks to acquire suitable locks.
1726
 */
1727 1728
List *
QueryRewrite(Query *parsetree)
1729
{
B
Bruce Momjian 已提交
1730 1731
	List	   *querylist;
	List	   *results = NIL;
1732
	ListCell   *l;
1733 1734 1735
	CmdType		origCmdType;
	bool		foundOriginalQuery;
	Query	   *lastInstead;
1736 1737 1738 1739 1740 1741

	/*
	 * Step 1
	 *
	 * Apply all non-SELECT rules possibly getting 0 or many queries
	 */
1742
	querylist = RewriteQuery(parsetree, NIL);
1743 1744

	/*
1745
	 * Step 2
1746 1747 1748
	 *
	 * Apply all the RIR rules on each query
	 */
B
Bruce Momjian 已提交
1749 1750
	foreach(l, querylist)
	{
B
Bruce Momjian 已提交
1751
		Query	   *query = (Query *) lfirst(l);
B
Bruce Momjian 已提交
1752

1753
		query = fireRIRrules(query, NIL);
1754

B
Bruce Momjian 已提交
1755
		/*
1756
		 * If the query target was rewritten as a view, complain.
B
Bruce Momjian 已提交
1757
		 */
1758
		if (query->resultRelation)
B
Bruce Momjian 已提交
1759
		{
1760 1761
			RangeTblEntry *rte = rt_fetch(query->resultRelation,
										  query->rtable);
B
Bruce Momjian 已提交
1762

1763
			if (rte->rtekind == RTE_SUBQUERY)
B
Bruce Momjian 已提交
1764
			{
1765 1766 1767
				switch (query->commandType)
				{
					case CMD_INSERT:
1768 1769 1770 1771
						ereport(ERROR,
								(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
								 errmsg("cannot insert into a view"),
								 errhint("You need an unconditional ON INSERT DO INSTEAD rule.")));
1772 1773
						break;
					case CMD_UPDATE:
1774 1775 1776 1777
						ereport(ERROR,
								(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
								 errmsg("cannot update a view"),
								 errhint("You need an unconditional ON UPDATE DO INSTEAD rule.")));
1778 1779
						break;
					case CMD_DELETE:
1780 1781 1782 1783
						ereport(ERROR,
								(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
								 errmsg("cannot delete from a view"),
								 errhint("You need an unconditional ON DELETE DO INSTEAD rule.")));
1784 1785
						break;
					default:
1786
						elog(ERROR, "unrecognized commandType: %d",
1787 1788 1789
							 (int) query->commandType);
						break;
				}
B
Bruce Momjian 已提交
1790 1791 1792
			}
		}

1793
		results = lappend(results, query);
B
Bruce Momjian 已提交
1794
	}
1795

1796 1797 1798
	/*
	 * Step 3
	 *
1799 1800
	 * Determine which, if any, of the resulting queries is supposed to set
	 * the command-result tag; and update the canSetTag fields accordingly.
1801 1802
	 *
	 * If the original query is still in the list, it sets the command tag.
B
Bruce Momjian 已提交
1803 1804 1805 1806
	 * Otherwise, the last INSTEAD query of the same kind as the original is
	 * allowed to set the tag.	(Note these rules can leave us with no query
	 * setting the tag.  The tcop code has to cope with this by setting up a
	 * default tag based on the original un-rewritten query.)
1807 1808
	 *
	 * The Asserts verify that at most one query in the result list is marked
B
Bruce Momjian 已提交
1809 1810
	 * canSetTag.  If we aren't checking asserts, we can fall out of the loop
	 * as soon as we find the original query.
1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841
	 */
	origCmdType = parsetree->commandType;
	foundOriginalQuery = false;
	lastInstead = NULL;

	foreach(l, results)
	{
		Query	   *query = (Query *) lfirst(l);

		if (query->querySource == QSRC_ORIGINAL)
		{
			Assert(query->canSetTag);
			Assert(!foundOriginalQuery);
			foundOriginalQuery = true;
#ifndef USE_ASSERT_CHECKING
			break;
#endif
		}
		else
		{
			Assert(!query->canSetTag);
			if (query->commandType == origCmdType &&
				(query->querySource == QSRC_INSTEAD_RULE ||
				 query->querySource == QSRC_QUAL_INSTEAD_RULE))
				lastInstead = query;
		}
	}

	if (!foundOriginalQuery && lastInstead != NULL)
		lastInstead->canSetTag = true;

1842
	return results;
B
Hi!  
Bruce Momjian 已提交
1843
}