rewriteHandler.c 45.7 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
10
 *	  $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.164 2006/07/14 14:52:22 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 42
				  Query *rule_action,
				  Node *rule_qual,
				  int rt_index,
				  CmdType event);
43
static List *adjustJoinTreeList(Query *parsetree, bool removert, int rt_index);
44 45
static void rewriteTargetList(Query *parsetree, Relation target_relation);
static TargetEntry *process_matched_tle(TargetEntry *src_tle,
B
Bruce Momjian 已提交
46 47
					TargetEntry *prior_tle,
					const char *attrName);
48
static Node *get_assignment_input(Node *node);
49
static void markQueryForLocking(Query *qry, bool forUpdate, bool noWait,
B
Bruce Momjian 已提交
50
					bool skipOldNew);
51
static List *matchLocks(CmdType event, RuleLock *rulelocks,
B
Bruce Momjian 已提交
52
		   int varno, Query *parsetree);
53
static Query *fireRIRrules(Query *parsetree, List *activeRIRs);
54

55

56 57 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
/*
 * 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;
104 105
		Index		curinputvarno;
		RangeTblEntry *curinputrte;
106 107 108 109 110 111
		ListCell   *ll;

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

113
				/*
B
Bruce Momjian 已提交
114 115 116
				 * 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.
117
				 *
118 119 120 121 122 123
				 * 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.
124 125 126
				 */
				if (rt_index == parsetree->resultRelation)
					lockmode = RowExclusiveLock;
127
				else if (get_rowmark(parsetree, rt_index))
128 129 130 131 132 133 134 135 136
					lockmode = RowShareLock;
				else
					lockmode = AccessShareLock;

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

			case RTE_JOIN:
B
Bruce Momjian 已提交
137

138
				/*
B
Bruce Momjian 已提交
139 140 141
				 * Scan the join's alias var list to see if any columns have
				 * been dropped, and if so replace those Vars with NULL
				 * Consts.
142
				 *
B
Bruce Momjian 已提交
143 144 145
				 * Since a join has only two inputs, we can expect to see
				 * multiple references to the same input RTE; optimize away
				 * multiple fetches.
146 147
				 */
				newaliasvars = NIL;
148 149
				curinputvarno = 0;
				curinputrte = NULL;
150 151 152 153 154 155 156 157
				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 已提交
158 159
					 * the join clause.  (Conceivably it could also be a NULL
					 * constant already?  But that's OK too.)
160 161 162 163 164
					 */
					if (IsA(aliasvar, Var))
					{
						/*
						 * The elements of an alias list have to refer to
B
Bruce Momjian 已提交
165 166 167 168 169 170
						 * 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.)
171 172
						 */
						Assert(aliasvar->varlevelsup == 0);
173 174 175 176 177 178 179 180 181 182 183
						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))
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
						{
							/*
							 * 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 已提交
199

200 201 202 203 204 205 206 207 208 209 210 211 212 213
				/*
				 * 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 已提交
214 215
	 * Recurse into sublink subqueries, too.  But we already did the ones in
	 * the rtable.
216 217 218 219 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
	 */
	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);
}


247
/*
248 249 250
 * rewriteRuleAction -
 *	  Rewrite the rule action with appropriate qualifiers (taken from
 *	  the triggering query).
251
 */
252 253
static Query *
rewriteRuleAction(Query *parsetree,
254 255
				  Query *rule_action,
				  Node *rule_qual,
256
				  int rt_index,
257
				  CmdType event)
258
{
259 260 261
	int			current_varno,
				new_varno;
	int			rt_length;
262 263
	Query	   *sub_action;
	Query	  **sub_action_ptr;
264

265
	/*
B
Bruce Momjian 已提交
266 267
	 * Make modifiable copies of rule action and qual (what we're passed are
	 * the stored versions in the relcache; don't touch 'em!).
268 269 270 271
	 */
	rule_action = (Query *) copyObject(rule_action);
	rule_qual = (Node *) copyObject(rule_qual);

272 273 274 275 276 277
	/*
	 * Acquire necessary locks and fix any deleted JOIN RTE entries.
	 */
	AcquireRewriteLocks(rule_action);
	(void) acquireLocksOnSubLinks(rule_qual, NULL);

278
	current_varno = rt_index;
279
	rt_length = list_length(parsetree->rtable);
280
	new_varno = PRS2_NEW_VARNO + rt_length;
281

282
	/*
B
Bruce Momjian 已提交
283 284
	 * Adjust rule action and qual to offset its varnos, so that we can merge
	 * its rtable with the main parsetree's rtable.
285
	 *
286 287
	 * 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 已提交
288
	 * top-level INSERT (kluge!).
289
	 */
290
	sub_action = getInsertSelectQuery(rule_action, &sub_action_ptr);
291

292
	OffsetVarNodes((Node *) sub_action, rt_length, 0);
293
	OffsetVarNodes(rule_qual, rt_length, 0);
294 295 296
	/* but references to *OLD* should point at original rt_index */
	ChangeVarNodes((Node *) sub_action,
				   PRS2_OLD_VARNO + rt_length, rt_index, 0);
297
	ChangeVarNodes(rule_qual,
298 299 300
				   PRS2_OLD_VARNO + rt_length, rt_index, 0);

	/*
301 302
	 * 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 已提交
303 304
	 * action.	Some of the entries may be unused after we finish rewriting,
	 * but we leave them all in place for two reasons:
305
	 *
306 307
	 * We'd have a much harder job to adjust the query's varnos if we
	 * selectively removed RT entries.
308
	 *
309 310 311
	 * 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.
312 313
	 *
	 * RT entries that are not referenced in the completed jointree will be
B
Bruce Momjian 已提交
314 315 316 317 318
	 * 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.
319
	 *
320 321
	 * 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 已提交
322
	 * original query, but we don't bother to treat that case differently.
323
	 *
324 325 326
	 * 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.
327
	 */
328
	sub_action->rtable = list_concat((List *) copyObject(parsetree->rtable),
B
Bruce Momjian 已提交
329
									 sub_action->rtable);
330

331 332
	/*
	 * Each rule action's jointree should be the main parsetree's jointree
B
Bruce Momjian 已提交
333 334 335 336 337 338 339 340
	 * 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.
341
	 *
342 343
	 * As above, the action's jointree must not share substructure with the
	 * main parsetree's.
344
	 */
345
	if (sub_action->commandType != CMD_UTILITY)
346
	{
B
Bruce Momjian 已提交
347 348
		bool		keeporig;
		List	   *newjointree;
349

350
		Assert(sub_action->jointree != NULL);
B
Bruce Momjian 已提交
351 352
		keeporig = (!rangeTableEntry_used((Node *) sub_action->jointree,
										  rt_index, 0)) &&
353
			(rangeTableEntry_used(rule_qual, rt_index, 0) ||
B
Bruce Momjian 已提交
354
			 rangeTableEntry_used(parsetree->jointree->quals, rt_index, 0));
355
		newjointree = adjustJoinTreeList(parsetree, !keeporig, rt_index);
356 357 358
		if (newjointree != NIL)
		{
			/*
B
Bruce Momjian 已提交
359 360 361 362
			 * 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?)
363 364
			 */
			if (sub_action->setOperations != NULL)
365 366 367
				ereport(ERROR,
						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
						 errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
368 369

			sub_action->jointree->fromlist =
370
				list_concat(newjointree, sub_action->jointree->fromlist);
371 372 373 374 375 376 377 378

			/*
			 * 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);
379
		}
380 381 382
	}

	/*
B
Bruce Momjian 已提交
383 384 385
	 * 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
386
	 */
387
	AddQual(sub_action, rule_qual);
388 389 390 391

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

	/*
B
Bruce Momjian 已提交
392 393
	 * Rewrite new.attribute w/ right hand side of target-list entry for
	 * appropriate field name in insert/update.
394
	 *
395 396 397
	 * 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.
398
	 */
399 400
	if ((event == CMD_INSERT || event == CMD_UPDATE) &&
		sub_action->commandType != CMD_UTILITY)
401 402
	{
		sub_action = (Query *) ResolveNew((Node *) sub_action,
403
										  new_varno,
404
										  0,
405 406
										  rt_fetch(new_varno,
												   sub_action->rtable),
407
										  parsetree->targetList,
408 409
										  event,
										  current_varno);
410 411 412
		if (sub_action_ptr)
			*sub_action_ptr = sub_action;
		else
413
			rule_action = sub_action;
414
	}
415

416
	return rule_action;
417 418
}

419
/*
420 421 422 423
 * 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
424 425
 * of the join).  Returns modified jointree list --- this is a separate copy
 * sharing no nodes with the original.
426
 */
427
static List *
428
adjustJoinTreeList(Query *parsetree, bool removert, int rt_index)
429
{
430
	List	   *newjointree = copyObject(parsetree->jointree->fromlist);
431
	ListCell   *l;
432

433
	if (removert)
B
Bruce Momjian 已提交
434
	{
435
		foreach(l, newjointree)
436
		{
437
			RangeTblRef *rtr = lfirst(l);
438

439 440
			if (IsA(rtr, RangeTblRef) &&
				rtr->rtindex == rt_index)
441
			{
442
				newjointree = list_delete_ptr(newjointree, rtr);
B
Bruce Momjian 已提交
443 444

				/*
B
Bruce Momjian 已提交
445
				 * foreach is safe because we exit loop after list_delete...
B
Bruce Momjian 已提交
446
				 */
447 448
				break;
			}
449
		}
450
	}
451
	return newjointree;
452
}
453

454

455 456 457 458 459 460 461 462 463
/*
 * 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
464 465 466
 * down rewriter processing with extra tlist nodes.)  Also, for both INSERT
 * and UPDATE, replace explicit DEFAULT specifications with column default
 * expressions.
467 468
 *
 * 2. Merge multiple entries for the same target attribute, or declare error
469 470 471
 * 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;
472 473 474 475 476 477 478 479
 * 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 已提交
480
 * references to NEW.foo will produce wrong or incomplete results.	Item 3
481 482 483 484 485 486 487
 * 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.
 */
static void
rewriteTargetList(Query *parsetree, Relation target_relation)
{
	CmdType		commandType = parsetree->commandType;
488
	TargetEntry **new_tles;
489
	List	   *new_tlist = NIL;
490 491
	List	   *junk_tlist = NIL;
	Form_pg_attribute att_tup;
492
	int			attrno,
493
				next_junk_attrno,
494
				numattrs;
495
	ListCell   *temp;
496 497

	/*
B
Bruce Momjian 已提交
498 499 500 501
	 * 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.
502
	 *
B
Bruce Momjian 已提交
503 504
	 * Junk attributes are tossed into a separate list during the same tlist
	 * scan, then appended to the reconstructed tlist.
505 506
	 */
	numattrs = RelationGetNumberOfAttributes(target_relation);
507 508
	new_tles = (TargetEntry **) palloc0(numattrs * sizeof(TargetEntry *));
	next_junk_attrno = numattrs + 1;
509

510
	foreach(temp, parsetree->targetList)
511
	{
512
		TargetEntry *old_tle = (TargetEntry *) lfirst(temp);
513

514
		if (!old_tle->resjunk)
515 516
		{
			/* Normal attr: stash it into new_tles[] */
517
			attrno = old_tle->resno;
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532
			if (attrno < 1 || attrno > numattrs)
				elog(ERROR, "bogus resno %d in targetlist", attrno);
			att_tup = target_relation->rd_att->attrs[attrno - 1];

			/* 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
533
		{
534
			/*
B
Bruce Momjian 已提交
535 536
			 * Copy all resjunk tlist entries to junk_tlist, and assign them
			 * resnos above the last real resno.
537
			 *
538 539
			 * Typical junk entries include ORDER BY or GROUP BY expressions
			 * (are these actually possible in an INSERT or UPDATE?), system
540 541
			 * attribute references, etc.
			 */
542

543
			/* Get the resno right, but don't copy unnecessarily */
544
			if (old_tle->resno != next_junk_attrno)
545
			{
546 547
				old_tle = flatCopyTargetEntry(old_tle);
				old_tle->resno = next_junk_attrno;
548
			}
549 550
			junk_tlist = lappend(junk_tlist, old_tle);
			next_junk_attrno++;
551
		}
552 553 554 555 556 557 558 559 560 561 562
	}

	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;
563

564
		/*
B
Bruce Momjian 已提交
565 566 567
		 * 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.
568 569
		 */
		if ((new_tle == NULL && commandType == CMD_INSERT) ||
570
			(new_tle && new_tle->expr && IsA(new_tle->expr, SetToDefault)))
571 572 573 574 575
		{
			Node	   *new_expr;

			new_expr = build_column_default(target_relation, attrno);

576
			/*
B
Bruce Momjian 已提交
577 578 579 580 581
			 * 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.
582 583 584 585 586 587 588 589 590 591 592 593 594 595
			 */
			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,
596
												InvalidOid, -1,
597
												att_tup->atttypid,
598
												COERCE_IMPLICIT_CAST,
599
												false,
600
												false);
601 602 603
				}
			}

604
			if (new_expr)
605 606 607 608
				new_tle = makeTargetEntry((Expr *) new_expr,
										  attrno,
										  pstrdup(NameStr(att_tup->attname)),
										  false);
609 610 611 612 613 614
		}

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

615
	pfree(new_tles);
616

617
	parsetree->targetList = list_concat(new_tlist, junk_tlist);
618 619 620 621 622 623 624
}


/*
 * Convert a matched TLE from the original tlist into a correct new TLE.
 *
 * This routine detects and handles multiple assignments to the same target
625
 * attribute.  (The attribute name is needed only for error messages.)
626 627 628
 */
static TargetEntry *
process_matched_tle(TargetEntry *src_tle,
629 630
					TargetEntry *prior_tle,
					const char *attrName)
631
{
632
	TargetEntry *result;
633 634 635 636
	Node	   *src_expr;
	Node	   *prior_expr;
	Node	   *src_input;
	Node	   *prior_input;
637
	Node	   *priorbottom;
638
	Node	   *newexpr;
639 640 641 642

	if (prior_tle == NULL)
	{
		/*
B
Bruce Momjian 已提交
643
		 * Normal case where this is the first assignment to the attribute.
644 645 646 647
		 */
		return src_tle;
	}

648
	/*----------
649
	 * Multiple assignments to same attribute.	Allow only if all are
650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666
	 * 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 已提交
667
	 * FieldStore with multiple target fields.	We must nest when
668 669
	 * ArrayRefs are involved though.
	 *----------
670
	 */
671 672 673 674 675 676 677
	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))
678 679
		ereport(ERROR,
				(errcode(ERRCODE_SYNTAX_ERROR),
680
				 errmsg("multiple assignments to same column \"%s\"",
681
						attrName)));
682 683

	/*
B
Bruce Momjian 已提交
684
	 * Prior TLE could be a nest of assignments if we do this more than once.
685
	 */
686 687 688
	priorbottom = prior_input;
	for (;;)
	{
B
Bruce Momjian 已提交
689
		Node	   *newbottom = get_assignment_input(priorbottom);
690 691 692 693 694 695

		if (newbottom == NULL)
			break;				/* found the original Var reference */
		priorbottom = newbottom;
	}
	if (!equal(priorbottom, src_input))
696 697
		ereport(ERROR,
				(errcode(ERRCODE_SYNTAX_ERROR),
698
				 errmsg("multiple assignments to same column \"%s\"",
699
						attrName)));
700 701 702 703

	/*
	 * Looks OK to nest 'em.
	 */
704 705
	if (IsA(src_expr, FieldStore))
	{
B
Bruce Momjian 已提交
706
		FieldStore *fstore = makeNode(FieldStore);
707 708 709 710 711 712 713

		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 已提交
714
							list_copy(((FieldStore *) src_expr)->newvals));
715 716
			fstore->fieldnums =
				list_concat(list_copy(((FieldStore *) prior_expr)->fieldnums),
B
Bruce Momjian 已提交
717
							list_copy(((FieldStore *) src_expr)->fieldnums));
718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739
		}
		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;
	}
740

741 742 743
	result = flatCopyTargetEntry(src_tle);
	result->expr = (Expr *) newexpr;
	return result;
744 745
}

746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769
/*
 * 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;
}
770 771 772 773 774 775

/*
 * Make an expression tree for the default value for a column.
 *
 * If there is no default, return a NULL instead.
 */
776
Node *
777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809
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 已提交
810
		 * No per-column default, so look for a default for the type itself.
811
		 */
812
		expr = get_typdefault(atttype);
813 814 815 816 817 818
	}

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

	/*
819 820
	 * 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 已提交
821 822
	 * involving domain defaults where it might not be true. This should match
	 * the parser's processing of non-defaulted expressions --- see
B
Bruce Momjian 已提交
823
	 * updateTargetListEntry().
824 825 826
	 */
	exprtype = exprType(expr);

B
Bruce Momjian 已提交
827
	expr = coerce_to_target_type(NULL,	/* no UNKNOWN params here */
828
								 expr, exprtype,
829 830 831 832
								 atttype, atttypmod,
								 COERCION_ASSIGNMENT,
								 COERCE_IMPLICIT_CAST);
	if (expr == NULL)
833 834 835 836 837 838 839
		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 已提交
840
			   errhint("You will need to rewrite or cast the expression.")));
841 842 843 844 845

	return expr;
}


846
/*
847 848
 * matchLocks -
 *	  match the list of locks and returns the matching rules
849
 */
850 851 852 853 854
static List *
matchLocks(CmdType event,
		   RuleLock *rulelocks,
		   int varno,
		   Query *parsetree)
855
{
856
	List	   *matching_locks = NIL;
857 858
	int			nlocks;
	int			i;
859

860 861
	if (rulelocks == NULL)
		return NIL;
862

863
	if (parsetree->commandType != CMD_SELECT)
864
	{
865 866
		if (parsetree->resultRelation != varno)
			return NIL;
867
	}
868

869
	nlocks = rulelocks->numLocks;
870

871
	for (i = 0; i < nlocks; i++)
B
Bruce Momjian 已提交
872
	{
873
		RewriteRule *oneLock = rulelocks->rules[i];
874

875
		if (oneLock->event == event)
876
		{
877 878 879 880 881
			if (parsetree->commandType != CMD_SELECT ||
				(oneLock->attrno == -1 ?
				 rangeTableEntry_used((Node *) parsetree, varno, 0) :
				 attribute_used((Node *) parsetree,
								varno, oneLock->attrno, 0)))
882
				matching_locks = lappend(matching_locks, oneLock);
883
		}
884
	}
885

886
	return matching_locks;
887 888
}

889

890 891 892
/*
 * ApplyRetrieveRule - expand an ON SELECT rule
 */
893 894 895 896 897 898
static Query *
ApplyRetrieveRule(Query *parsetree,
				  RewriteRule *rule,
				  int rt_index,
				  bool relation_level,
				  Relation relation,
899
				  List *activeRIRs)
900 901 902 903
{
	Query	   *rule_action;
	RangeTblEntry *rte,
			   *subrte;
904
	RowMarkClause *rc;
905

906
	if (list_length(rule->actions) != 1)
907
		elog(ERROR, "expected just one rule action");
908
	if (rule->qual != NULL)
909
		elog(ERROR, "cannot handle qualified ON SELECT rule");
B
Bruce Momjian 已提交
910
	if (!relation_level)
911
		elog(ERROR, "cannot handle per-attribute ON SELECT rule");
912

913
	/*
B
Bruce Momjian 已提交
914 915
	 * Make a modifiable copy of the view query, and acquire needed locks on
	 * the relations it mentions.
916
	 */
917
	rule_action = copyObject(linitial(rule->actions));
918

919 920 921 922 923
	AcquireRewriteLocks(rule_action);

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

926
	/*
B
Bruce Momjian 已提交
927 928
	 * VIEWs are really easy --- just plug the view query in as a subselect,
	 * replacing the relation's original RTE.
929
	 */
930
	rte = rt_fetch(rt_index, parsetree->rtable);
931

932
	rte->rtekind = RTE_SUBQUERY;
933 934 935
	rte->relid = InvalidOid;
	rte->subquery = rule_action;
	rte->inh = false;			/* must not be set for a subquery */
936

937
	/*
B
Bruce Momjian 已提交
938 939
	 * We move the view's permission check data down to its rangetable. The
	 * checks will actually be done against the *OLD* entry therein.
940
	 */
941 942
	subrte = rt_fetch(PRS2_OLD_VARNO, rule_action->rtable);
	Assert(subrte->relid == relation->rd_id);
943
	subrte->requiredPerms = rte->requiredPerms;
944
	subrte->checkAsUser = rte->checkAsUser;
945

946
	rte->requiredPerms = 0;		/* no permission check on subquery itself */
947
	rte->checkAsUser = InvalidOid;
948

949
	/*
950
	 * FOR UPDATE/SHARE of view?
951
	 */
952
	if ((rc = get_rowmark(parsetree, rt_index)) != NULL)
953
	{
954
		/*
B
Bruce Momjian 已提交
955
		 * Remove the view from the list of rels that will actually be marked
956
		 * FOR UPDATE/SHARE by the executor.  It will still be access-checked
B
Bruce Momjian 已提交
957
		 * for write access, though.
958
		 */
959
		parsetree->rowMarks = list_delete_ptr(parsetree->rowMarks, rc);
B
Bruce Momjian 已提交
960 961

		/*
962
		 * Set up the view's referenced tables as if FOR UPDATE/SHARE.
963
		 */
964 965
		markQueryForLocking(rule_action, rc->forUpdate,
							rc->noWait, true);
966 967
	}

968
	return parsetree;
969 970
}

971
/*
972
 * Recursively mark all relations used by a view as FOR UPDATE/SHARE.
973 974 975 976
 *
 * This may generate an invalid query, eg if some sub-query uses an
 * aggregate.  We leave it to the planner to detect that.
 *
977
 * NB: this must agree with the parser's transformLocking() routine.
978 979
 */
static void
980
markQueryForLocking(Query *qry, bool forUpdate, bool noWait, bool skipOldNew)
981 982
{
	Index		rti = 0;
983
	ListCell   *l;
984 985 986 987 988 989 990 991 992 993 994 995

	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;

996
		if (rte->rtekind == RTE_RELATION)
997
		{
998
			applyLockingClause(qry, rti, forUpdate, noWait);
999
			rte->requiredPerms |= ACL_SELECT_FOR_UPDATE;
1000
		}
1001 1002
		else if (rte->rtekind == RTE_SUBQUERY)
		{
1003
			/* FOR UPDATE/SHARE of subquery is propagated to subquery's rels */
1004
			markQueryForLocking(rte->subquery, forUpdate, noWait, false);
1005
		}
1006 1007 1008
	}
}

1009

1010
/*
1011 1012 1013
 * fireRIRonSubLink -
 *	Apply fireRIRrules() to each SubLink (subselect in expression) found
 *	in the given tree.
1014 1015
 *
 * NOTE: although this has the form of a walker, we cheat and modify the
1016
 * SubLink nodes in-place.	It is caller's responsibility to ensure that
1017
 * no unwanted side-effects occur!
1018 1019 1020 1021
 *
 * 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.
1022 1023
 */
static bool
1024
fireRIRonSubLink(Node *node, List *activeRIRs)
1025 1026
{
	if (node == NULL)
1027 1028
		return false;
	if (IsA(node, SubLink))
B
Bruce Momjian 已提交
1029
	{
1030 1031 1032
		SubLink    *sub = (SubLink *) node;

		/* Do what we came for */
1033 1034
		sub->subselect = (Node *) fireRIRrules((Query *) sub->subselect,
											   activeRIRs);
1035
		/* Fall through to process lefthand args of SubLink */
1036
	}
B
Bruce Momjian 已提交
1037

1038
	/*
B
Bruce Momjian 已提交
1039 1040
	 * Do NOT recurse into Query nodes, because fireRIRrules already processed
	 * subselects of subselects for us.
1041
	 */
1042
	return expression_tree_walker(node, fireRIRonSubLink,
1043
								  (void *) activeRIRs);
1044 1045 1046 1047 1048 1049 1050 1051
}


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

1056
	/*
B
Bruce Momjian 已提交
1057 1058
	 * don't try to convert this into a foreach loop, because rtable list can
	 * get changed each time through...
1059
	 */
1060
	rt_index = 0;
1061
	while (rt_index < list_length(parsetree->rtable))
B
Bruce Momjian 已提交
1062
	{
1063 1064 1065 1066 1067 1068 1069
		RangeTblEntry *rte;
		Relation	rel;
		List	   *locks;
		RuleLock   *rules;
		RewriteRule *rule;
		int			i;

1070 1071
		++rt_index;

1072
		rte = rt_fetch(rt_index, parsetree->rtable);
1073

1074
		/*
B
Bruce Momjian 已提交
1075 1076
		 * 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
1077 1078
		 * subquery to expand any rule references in it.
		 */
1079
		if (rte->rtekind == RTE_SUBQUERY)
1080
		{
1081
			rte->subquery = fireRIRrules(rte->subquery, activeRIRs);
1082 1083 1084
			continue;
		}

1085 1086 1087 1088 1089 1090
		/*
		 * Joins and other non-relation RTEs can be ignored completely.
		 */
		if (rte->rtekind != RTE_RELATION)
			continue;

1091
		/*
1092 1093 1094
		 * 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 已提交
1095 1096
		 * part of the join set (a source table), or is referenced by any Var
		 * nodes, or is the result table.
1097
		 */
1098 1099
		if (rt_index != parsetree->resultRelation &&
			!rangeTableEntry_used((Node *) parsetree, rt_index, 0))
1100
			continue;
B
Bruce Momjian 已提交
1101

1102
		/*
1103 1104
		 * We can use NoLock here since either the parser or
		 * AcquireRewriteLocks should have locked the rel already.
1105
		 */
1106
		rel = heap_open(rte->relid, NoLock);
1107 1108 1109 1110

		/*
		 * Collect the RIR rules that we must apply
		 */
1111 1112
		rules = rel->rd_rules;
		if (rules == NULL)
B
Bruce Momjian 已提交
1113
		{
1114
			heap_close(rel, NoLock);
1115 1116
			continue;
		}
1117
		locks = NIL;
B
Bruce Momjian 已提交
1118 1119
		for (i = 0; i < rules->numLocks; i++)
		{
1120 1121 1122
			rule = rules->rules[i];
			if (rule->event != CMD_SELECT)
				continue;
B
Bruce Momjian 已提交
1123

1124 1125 1126
			if (rule->attrno > 0)
			{
				/* per-attr rule; do we need it? */
1127
				if (!attribute_used((Node *) parsetree, rt_index,
1128
									rule->attrno, 0))
1129 1130
					continue;
			}
1131 1132 1133 1134 1135

			locks = lappend(locks, rule);
		}

		/*
1136
		 * If we found any, apply them --- but first check for recursion!
1137
		 */
1138
		if (locks != NIL)
B
Bruce Momjian 已提交
1139
		{
1140
			ListCell   *l;
1141

1142
			if (list_member_oid(activeRIRs, RelationGetRelid(rel)))
1143 1144 1145 1146
				ereport(ERROR,
						(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
						 errmsg("infinite recursion detected in rules for relation \"%s\"",
								RelationGetRelationName(rel))));
1147
			activeRIRs = lcons_oid(RelationGetRelid(rel), activeRIRs);
1148 1149 1150 1151 1152 1153 1154 1155 1156 1157

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

				parsetree = ApplyRetrieveRule(parsetree,
											  rule,
											  rt_index,
											  rule->attrno == -1,
											  rel,
1158
											  activeRIRs);
1159
			}
1160 1161

			activeRIRs = list_delete_first(activeRIRs);
1162 1163
		}

1164
		heap_close(rel, NoLock);
1165 1166
	}

1167
	/*
B
Bruce Momjian 已提交
1168 1169
	 * Recurse into sublink subqueries, too.  But we already did the ones in
	 * the rtable.
1170 1171
	 */
	if (parsetree->hasSubLinks)
1172
		query_tree_walker(parsetree, fireRIRonSubLink, (void *) activeRIRs,
1173
						  QTW_IGNORE_RT_SUBQUERIES);
1174 1175 1176 1177 1178

	return parsetree;
}


1179
/*
1180 1181 1182 1183 1184
 * 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.)
1185
 *
B
Bruce Momjian 已提交
1186
 * The rule_qual may contain references to OLD or NEW.	OLD references are
1187 1188 1189 1190 1191
 * 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.
 */
1192
static Query *
1193 1194 1195 1196
CopyAndAddInvertedQual(Query *parsetree,
					   Node *rule_qual,
					   int rt_index,
					   CmdType event)
1197
{
1198
	/* Don't scribble on the passed qual (it's in the relcache!) */
1199 1200
	Node	   *new_qual = (Node *) copyObject(rule_qual);

1201 1202 1203
	/*
	 * 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 已提交
1204 1205
	 * rewriteRuleAction, but not entirely ... consider restructuring so that
	 * we only need to process the qual this way once.)
1206 1207 1208
	 */
	(void) acquireLocksOnSubLinks(new_qual, NULL);

1209 1210 1211 1212 1213 1214 1215
	/* 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,
1216
							  rt_fetch(rt_index, parsetree->rtable),
1217 1218 1219 1220
							  parsetree->targetList,
							  event,
							  rt_index);
	/* And attach the fixed qual */
1221
	AddInvertedQual(parsetree, new_qual);
1222

1223
	return parsetree;
1224 1225 1226 1227
}


/*
1228
 *	fireRules -
M
 
Marc G. Fournier 已提交
1229
 *	   Iterate through rule locks applying rules.
1230
 *
1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242
 * 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)
 *	*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
1243
 *
1244 1245 1246 1247 1248 1249
 * 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 已提交
1250
 * query if we find either qualified or unqualified INSTEAD rules.	If
1251
 * we find both, the modified original query is discarded too.
1252
 */
1253
static List *
1254
fireRules(Query *parsetree,
1255 1256
		  int rt_index,
		  CmdType event,
1257
		  List *locks,
1258 1259
		  bool *instead_flag,
		  Query **qual_product)
1260
{
1261
	List	   *results = NIL;
1262
	ListCell   *l;
1263

1264
	foreach(l, locks)
1265
	{
1266
		RewriteRule *rule_lock = (RewriteRule *) lfirst(l);
1267 1268
		Node	   *event_qual = rule_lock->qual;
		List	   *actions = rule_lock->actions;
B
Bruce Momjian 已提交
1269
		QuerySource qsrc;
1270
		ListCell   *r;
1271

1272 1273 1274 1275 1276 1277
		/* Determine correct QuerySource value for actions */
		if (rule_lock->isInstead)
		{
			if (event_qual != NULL)
				qsrc = QSRC_QUAL_INSTEAD_RULE;
			else
1278
			{
1279
				qsrc = QSRC_INSTEAD_RULE;
B
Bruce Momjian 已提交
1280
				*instead_flag = true;	/* report unqualified INSTEAD */
1281
			}
1282 1283 1284 1285 1286
		}
		else
			qsrc = QSRC_NON_INSTEAD_RULE;

		if (qsrc == QSRC_QUAL_INSTEAD_RULE)
1287
		{
1288
			/*
B
Bruce Momjian 已提交
1289 1290 1291 1292 1293 1294 1295
			 * 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.
1296
			 *
B
Bruce Momjian 已提交
1297 1298
			 * 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 已提交
1299
			 */
B
Bruce Momjian 已提交
1300
			if (!*instead_flag)
1301 1302
			{
				if (*qual_product == NULL)
1303
					*qual_product = copyObject(parsetree);
1304 1305 1306 1307
				*qual_product = CopyAndAddInvertedQual(*qual_product,
													   event_qual,
													   rt_index,
													   event);
1308
			}
M
 
Marc G. Fournier 已提交
1309 1310
		}

1311
		/* Now process the rule's actions and add them to the result list */
1312 1313
		foreach(r, actions)
		{
1314
			Query	   *rule_action = lfirst(r);
1315

M
 
Marc G. Fournier 已提交
1316 1317 1318
			if (rule_action->commandType == CMD_NOTHING)
				continue;

1319 1320
			rule_action = rewriteRuleAction(parsetree, rule_action,
											event_qual, rt_index, event);
1321

1322
			rule_action->querySource = qsrc;
1323
			rule_action->canSetTag = false;		/* might change later */
1324

1325
			results = lappend(results, rule_action);
1326 1327
		}
	}
1328

1329
	return results;
1330 1331
}

M
 
Marc G. Fournier 已提交
1332

1333
/*
1334 1335
 * RewriteQuery -
 *	  rewrites the query and apply the rules again on the queries rewritten
1336
 *
1337 1338
 * rewrite_events is a list of open query-rewrite actions, so we can detect
 * infinite recursion.
1339
 */
1340
static List *
1341
RewriteQuery(Query *parsetree, List *rewrite_events)
1342
{
1343 1344 1345 1346
	CmdType		event = parsetree->commandType;
	bool		instead = false;
	Query	   *qual_product = NULL;
	List	   *rewritten = NIL;
1347

1348
	/*
1349 1350
	 * If the statement is an update, insert or delete - fire rules on it.
	 *
B
Bruce Momjian 已提交
1351 1352 1353
	 * 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?)
1354
	 */
1355 1356 1357 1358 1359 1360
	if (event != CMD_SELECT && event != CMD_UTILITY)
	{
		int			result_relation;
		RangeTblEntry *rt_entry;
		Relation	rt_entry_relation;
		List	   *locks;
1361

1362 1363 1364 1365
		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 已提交
1366

1367
		/*
1368 1369
		 * We can use NoLock here since either the parser or
		 * AcquireRewriteLocks should have locked the rel already.
1370
		 */
1371
		rt_entry_relation = heap_open(rt_entry->relid, NoLock);
1372

1373
		/*
B
Bruce Momjian 已提交
1374 1375 1376
		 * 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.
1377 1378 1379
		 */
		if (event == CMD_INSERT || event == CMD_UPDATE)
			rewriteTargetList(parsetree, rt_entry_relation);
1380

1381 1382 1383 1384 1385
		/*
		 * Collect and apply the appropriate rules.
		 */
		locks = matchLocks(event, rt_entry_relation->rd_rules,
						   result_relation, parsetree);
1386

1387 1388 1389
		if (locks != NIL)
		{
			List	   *product_queries;
1390

1391 1392 1393 1394 1395 1396
			product_queries = fireRules(parsetree,
										result_relation,
										event,
										locks,
										&instead,
										&qual_product);
1397

1398
			/*
B
Bruce Momjian 已提交
1399 1400
			 * If we got any product queries, recursively rewrite them --- but
			 * first check for recursion!
1401 1402 1403
			 */
			if (product_queries != NIL)
			{
B
Bruce Momjian 已提交
1404 1405
				ListCell   *n;
				rewrite_event *rev;
1406

1407 1408 1409 1410 1411
				foreach(n, rewrite_events)
				{
					rev = (rewrite_event *) lfirst(n);
					if (rev->relation == RelationGetRelid(rt_entry_relation) &&
						rev->event == event)
1412
						ereport(ERROR,
B
Bruce Momjian 已提交
1413 1414 1415
								(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
								 errmsg("infinite recursion detected in rules for relation \"%s\"",
							   RelationGetRelationName(rt_entry_relation))));
1416
				}
1417

1418 1419 1420 1421
				rev = (rewrite_event *) palloc(sizeof(rewrite_event));
				rev->relation = RelationGetRelid(rt_entry_relation);
				rev->event = event;
				rewrite_events = lcons(rev, rewrite_events);
1422

1423 1424 1425 1426
				foreach(n, product_queries)
				{
					Query	   *pt = (Query *) lfirst(n);
					List	   *newstuff;
1427

1428
					newstuff = RewriteQuery(pt, rewrite_events);
1429
					rewritten = list_concat(rewritten, newstuff);
1430
				}
1431 1432

				rewrite_events = list_delete_first(rewrite_events);
1433 1434
			}
		}
1435

1436
		heap_close(rt_entry_relation, NoLock);
1437
	}
M
 
Marc G. Fournier 已提交
1438

1439
	/*
B
Bruce Momjian 已提交
1440 1441 1442 1443 1444 1445
	 * 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.
1446
	 *
B
Bruce Momjian 已提交
1447 1448 1449
	 * 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 已提交
1450
	 */
1451
	if (!instead)
1452
	{
1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466
		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);
		}
1467
	}
M
 
Marc G. Fournier 已提交
1468

1469 1470
	return rewritten;
}
1471 1472 1473


/*
1474 1475 1476 1477 1478
 * QueryRewrite -
 *	  Primary entry point to the query rewriter.
 *	  Rewrite one query via query rewrite system, possibly returning 0
 *	  or many queries.
 *
1479 1480
 * NOTE: the parsetree must either have come straight from the parser,
 * or have been scanned by AcquireRewriteLocks to acquire suitable locks.
1481
 */
1482 1483
List *
QueryRewrite(Query *parsetree)
1484
{
B
Bruce Momjian 已提交
1485 1486
	List	   *querylist;
	List	   *results = NIL;
1487
	ListCell   *l;
1488 1489 1490
	CmdType		origCmdType;
	bool		foundOriginalQuery;
	Query	   *lastInstead;
1491 1492 1493 1494 1495 1496

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

	/*
1500
	 * Step 2
1501 1502 1503
	 *
	 * Apply all the RIR rules on each query
	 */
B
Bruce Momjian 已提交
1504 1505
	foreach(l, querylist)
	{
B
Bruce Momjian 已提交
1506
		Query	   *query = (Query *) lfirst(l);
B
Bruce Momjian 已提交
1507

1508
		query = fireRIRrules(query, NIL);
1509

B
Bruce Momjian 已提交
1510
		/*
1511
		 * If the query target was rewritten as a view, complain.
B
Bruce Momjian 已提交
1512
		 */
1513
		if (query->resultRelation)
B
Bruce Momjian 已提交
1514
		{
1515 1516
			RangeTblEntry *rte = rt_fetch(query->resultRelation,
										  query->rtable);
B
Bruce Momjian 已提交
1517

1518
			if (rte->rtekind == RTE_SUBQUERY)
B
Bruce Momjian 已提交
1519
			{
1520 1521 1522
				switch (query->commandType)
				{
					case CMD_INSERT:
1523 1524 1525 1526
						ereport(ERROR,
								(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
								 errmsg("cannot insert into a view"),
								 errhint("You need an unconditional ON INSERT DO INSTEAD rule.")));
1527 1528
						break;
					case CMD_UPDATE:
1529 1530 1531 1532
						ereport(ERROR,
								(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
								 errmsg("cannot update a view"),
								 errhint("You need an unconditional ON UPDATE DO INSTEAD rule.")));
1533 1534
						break;
					case CMD_DELETE:
1535 1536 1537 1538
						ereport(ERROR,
								(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
								 errmsg("cannot delete from a view"),
								 errhint("You need an unconditional ON DELETE DO INSTEAD rule.")));
1539 1540
						break;
					default:
1541
						elog(ERROR, "unrecognized commandType: %d",
1542 1543 1544
							 (int) query->commandType);
						break;
				}
B
Bruce Momjian 已提交
1545 1546 1547
			}
		}

1548
		results = lappend(results, query);
B
Bruce Momjian 已提交
1549
	}
1550

1551 1552 1553
	/*
	 * Step 3
	 *
1554 1555
	 * Determine which, if any, of the resulting queries is supposed to set
	 * the command-result tag; and update the canSetTag fields accordingly.
1556 1557
	 *
	 * If the original query is still in the list, it sets the command tag.
B
Bruce Momjian 已提交
1558 1559 1560 1561
	 * 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.)
1562 1563
	 *
	 * The Asserts verify that at most one query in the result list is marked
B
Bruce Momjian 已提交
1564 1565
	 * canSetTag.  If we aren't checking asserts, we can fall out of the loop
	 * as soon as we find the original query.
1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596
	 */
	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;

1597
	return results;
B
Hi!  
Bruce Momjian 已提交
1598
}