rewriteHandler.c 45.8 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * rewriteHandler.c
4
 *		Primary module of query rewriter.
5
 *
P
 
PostgreSQL Daemon 已提交
6
 * Portions Copyright (c) 1996-2005, 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.156 2005/07/28 22:27:02 tgl Exp $
11 12 13 14 15
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

B
Bruce Momjian 已提交
16
#include "access/heapam.h"
17
#include "catalog/pg_operator.h"
18
#include "catalog/pg_type.h"
B
Bruce Momjian 已提交
19
#include "miscadmin.h"
20
#include "nodes/makefuncs.h"
B
Bruce Momjian 已提交
21 22
#include "optimizer/clauses.h"
#include "optimizer/prep.h"
23
#include "optimizer/var.h"
B
Bruce Momjian 已提交
24
#include "parser/analyze.h"
25
#include "parser/parse_coerce.h"
26 27
#include "parser/parse_expr.h"
#include "parser/parse_oper.h"
B
Bruce Momjian 已提交
28
#include "parser/parse_type.h"
29
#include "parser/parsetree.h"
30
#include "rewrite/rewriteHandler.h"
B
Bruce Momjian 已提交
31
#include "rewrite/rewriteManip.h"
32
#include "utils/builtins.h"
B
Bruce Momjian 已提交
33
#include "utils/lsyscache.h"
34 35


36
/* We use a list of these to detect recursion in RewriteQuery */
B
Bruce Momjian 已提交
37 38
typedef struct rewrite_event
{
39 40
	Oid			relation;		/* OID of relation having rules */
	CmdType		event;			/* type of rule being fired */
41
} rewrite_event;
42

43
static bool acquireLocksOnSubLinks(Node *node, void *context);
44
static Query *rewriteRuleAction(Query *parsetree,
45 46 47 48
				  Query *rule_action,
				  Node *rule_qual,
				  int rt_index,
				  CmdType event);
49
static List *adjustJoinTreeList(Query *parsetree, bool removert, int rt_index);
50 51
static void rewriteTargetList(Query *parsetree, Relation target_relation);
static TargetEntry *process_matched_tle(TargetEntry *src_tle,
B
Bruce Momjian 已提交
52 53
					TargetEntry *prior_tle,
					const char *attrName);
54
static Node *get_assignment_input(Node *node);
55
static void markQueryForLocking(Query *qry, bool forUpdate, bool skipOldNew);
56
static List *matchLocks(CmdType event, RuleLock *rulelocks,
B
Bruce Momjian 已提交
57
		   int varno, Query *parsetree);
58
static Query *fireRIRrules(Query *parsetree, List *activeRIRs);
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 108
/*
 * 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;
109 110
		Index		curinputvarno;
		RangeTblEntry *curinputrte;
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
		ListCell   *ll;

		++rt_index;
		switch (rte->rtekind)
		{
			case RTE_RELATION:
				/*
				 * 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.
				 *
				 * 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.
				 */
				if (rt_index == parsetree->resultRelation)
					lockmode = RowExclusiveLock;
				else if (list_member_int(parsetree->rowMarks, rt_index))
					lockmode = RowShareLock;
				else
					lockmode = AccessShareLock;

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

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

	/*
	 * Recurse into sublink subqueries, too.  But we already did the ones
	 * in the rtable.
	 */
	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);
}


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

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

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

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

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

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

	/*
303 304 305
	 * Generate expanded rtable consisting of main parsetree's rtable plus
	 * rule action's rtable; this becomes the complete rtable for the rule
	 * action.	Some of the entries may be unused after we finish
306 307
	 * rewriting, but we leave them all in place for two reasons:
	 *
B
Bruce Momjian 已提交
308 309
	 * We'd have a much harder job to adjust the query's varnos if we
	 * selectively removed RT entries.
310
	 *
B
Bruce Momjian 已提交
311 312 313
	 * 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.
314 315 316 317
	 *
	 * RT entries that are not referenced in the completed jointree will be
	 * ignored by the planner, so they do not affect query semantics.  But
	 * any permissions checks specified in them will be applied during
B
Bruce Momjian 已提交
318 319 320 321
	 * 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.
322 323
	 *
	 * When a rule is not INSTEAD, the permissions checks done on its copied
B
Bruce Momjian 已提交
324 325 326
	 * RT entries will be redundant with those done during execution of
	 * the original query, but we don't bother to treat that case
	 * differently.
327
	 *
328
	 * NOTE: because planner will destructively alter rtable, we must ensure
329 330
	 * that rule action's rtable is separate and shares no substructure
	 * with the main rtable.  Hence do a deep copy here.
331
	 */
332
	sub_action->rtable = list_concat((List *) copyObject(parsetree->rtable),
B
Bruce Momjian 已提交
333
									 sub_action->rtable);
334

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

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

			sub_action->jointree->fromlist =
375
				list_concat(newjointree, sub_action->jointree->fromlist);
376
		}
377 378 379
	}

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

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

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

413
	return rule_action;
414 415
}

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

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

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

				/*
				 * foreach is safe because we exit loop after
				 * list_delete...
				 */
445 446
				break;
			}
447
		}
448
	}
449
	return newjointree;
450
}
451

452

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

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

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

512
		if (!old_tle->resjunk)
513 514
		{
			/* Normal attr: stash it into new_tles[] */
515
			attrno = old_tle->resno;
516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
			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
531
		{
532 533 534 535 536 537 538 539
			/*
			 * Copy all resjunk tlist entries to junk_tlist, and
			 * assign them resnos above the last real resno.
			 *
			 * Typical junk entries include ORDER BY or GROUP BY expressions
			 * (are these actually possible in an INSERT or UPDATE?), system
			 * attribute references, etc.
			 */
540

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

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

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

			new_expr = build_column_default(target_relation, attrno);

574 575 576 577
			/*
			 * 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
B
Bruce Momjian 已提交
578 579 580
			 * in spending any more rewriter cycles on the entry.  But in
			 * the UPDATE case we've got to explicitly set the column to
			 * NULL.
581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596
			 */
			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,
												InvalidOid,
												att_tup->atttypid,
597
												COERCE_IMPLICIT_CAST,
598
												false,
599
												false);
600 601 602
				}
			}

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

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

614
	pfree(new_tles);
615

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


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

	if (prior_tle == NULL)
	{
		/*
		 * Normal case where this is the first assignment to the
		 * attribute.
		 */
		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

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

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

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

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

742 743 744
	result = flatCopyTargetEntry(src_tle);
	result->expr = (Expr *) newexpr;
	return result;
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 770
/*
 * 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;
}
771 772 773 774 775 776

/*
 * Make an expression tree for the default value for a column.
 *
 * If there is no default, return a NULL instead.
 */
777
Node *
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 810
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 已提交
811 812
		 * No per-column default, so look for a default for the type
		 * itself.
813
		 */
814
		expr = get_typdefault(atttype);
815 816 817 818 819 820
	}

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

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

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

	return expr;
}


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

862 863
	if (rulelocks == NULL)
		return NIL;
864

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

871
	nlocks = rulelocks->numLocks;
872

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

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

888
	return matching_locks;
889 890
}

891

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

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

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

920 921 922 923 924
	AcquireRewriteLocks(rule_action);

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

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

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

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

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

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

		/*
963
		 * Set up the view's referenced tables as if FOR UPDATE/SHARE.
964
		 */
965
		markQueryForLocking(rule_action, parsetree->forUpdate, 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 skipOldNew)
981 982
{
	Index		rti = 0;
983
	ListCell   *l;
984

985 986 987 988 989 990
	if (qry->rowMarks && forUpdate != qry->forUpdate)
		ereport(ERROR,
				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
				 errmsg("cannot use both FOR UPDATE and FOR SHARE in one query")));
	qry->forUpdate = forUpdate;

991 992 993 994 995 996 997 998 999 1000 1001
	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;

1002
		if (rte->rtekind == RTE_RELATION)
1003
		{
1004
			qry->rowMarks = list_append_unique_int(qry->rowMarks, rti);
1005
			rte->requiredPerms |= ACL_SELECT_FOR_UPDATE;
1006
		}
1007 1008
		else if (rte->rtekind == RTE_SUBQUERY)
		{
1009 1010
			/* FOR UPDATE/SHARE of subquery is propagated to subquery's rels */
			markQueryForLocking(rte->subquery, forUpdate, false);
1011
		}
1012 1013 1014
	}
}

1015

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

		/* Do what we came for */
1039 1040
		sub->subselect = (Node *) fireRIRrules((Query *) sub->subselect,
											   activeRIRs);
1041
		/* Fall through to process lefthand args of SubLink */
1042
	}
B
Bruce Momjian 已提交
1043

1044 1045
	/*
	 * Do NOT recurse into Query nodes, because fireRIRrules already
1046
	 * processed subselects of subselects for us.
1047
	 */
1048
	return expression_tree_walker(node, fireRIRonSubLink,
1049
								  (void *) activeRIRs);
1050 1051 1052 1053 1054 1055 1056 1057
}


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

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

1076 1077
		++rt_index;

1078
		rte = rt_fetch(rt_index, parsetree->rtable);
1079

1080 1081 1082 1083 1084
		/*
		 * 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
		 * subquery to expand any rule references in it.
		 */
1085
		if (rte->rtekind == RTE_SUBQUERY)
1086
		{
1087
			rte->subquery = fireRIRrules(rte->subquery, activeRIRs);
1088 1089 1090
			continue;
		}

1091 1092 1093 1094 1095 1096
		/*
		 * Joins and other non-relation RTEs can be ignored completely.
		 */
		if (rte->rtekind != RTE_RELATION)
			continue;

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

1108
		/*
1109 1110
		 * We can use NoLock here since either the parser or
		 * AcquireRewriteLocks should have locked the rel already.
1111
		 */
1112
		rel = heap_open(rte->relid, NoLock);
1113 1114 1115 1116

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

1130 1131 1132
			if (rule->attrno > 0)
			{
				/* per-attr rule; do we need it? */
1133
				if (!attribute_used((Node *) parsetree, rt_index,
1134
									rule->attrno, 0))
1135 1136
					continue;
			}
1137 1138 1139 1140 1141

			locks = lappend(locks, rule);
		}

		/*
1142
		 * If we found any, apply them --- but first check for recursion!
1143
		 */
1144
		if (locks != NIL)
B
Bruce Momjian 已提交
1145
		{
1146
			ListCell   *l;
1147

1148
			if (list_member_oid(activeRIRs, RelationGetRelid(rel)))
1149 1150 1151 1152
				ereport(ERROR,
						(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
						 errmsg("infinite recursion detected in rules for relation \"%s\"",
								RelationGetRelationName(rel))));
1153
			activeRIRs = lcons_oid(RelationGetRelid(rel), activeRIRs);
1154 1155 1156 1157 1158 1159 1160 1161 1162 1163

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

				parsetree = ApplyRetrieveRule(parsetree,
											  rule,
											  rt_index,
											  rule->attrno == -1,
											  rel,
1164
											  activeRIRs);
1165
			}
1166 1167

			activeRIRs = list_delete_first(activeRIRs);
1168 1169
		}

1170
		heap_close(rel, NoLock);
1171 1172
	}

1173
	/*
1174 1175
	 * Recurse into sublink subqueries, too.  But we already did the ones
	 * in the rtable.
1176 1177
	 */
	if (parsetree->hasSubLinks)
1178
		query_tree_walker(parsetree, fireRIRonSubLink, (void *) activeRIRs,
1179
						  QTW_IGNORE_RT_SUBQUERIES);
1180 1181 1182 1183 1184

	return parsetree;
}


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

1207 1208 1209 1210 1211 1212 1213 1214
	/*
	 * In case there are subqueries in the qual, acquire necessary locks and
	 * fix any deleted JOIN RTE entries.  (This is somewhat redundant with
	 * rewriteRuleAction, but not entirely ... consider restructuring so
	 * that we only need to process the qual this way once.)
	 */
	(void) acquireLocksOnSubLinks(new_qual, NULL);

1215 1216 1217 1218 1219 1220 1221
	/* 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,
1222
							  rt_fetch(rt_index, parsetree->rtable),
1223 1224 1225 1226
							  parsetree->targetList,
							  event,
							  rt_index);
	/* And attach the fixed qual */
1227
	AddInvertedQual(parsetree, new_qual);
1228

1229
	return parsetree;
1230 1231 1232 1233
}


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

1270
	foreach(l, locks)
1271
	{
1272
		RewriteRule *rule_lock = (RewriteRule *) lfirst(l);
1273 1274
		Node	   *event_qual = rule_lock->qual;
		List	   *actions = rule_lock->actions;
B
Bruce Momjian 已提交
1275
		QuerySource qsrc;
1276
		ListCell   *r;
1277

1278 1279 1280 1281 1282 1283
		/* Determine correct QuerySource value for actions */
		if (rule_lock->isInstead)
		{
			if (event_qual != NULL)
				qsrc = QSRC_QUAL_INSTEAD_RULE;
			else
1284
			{
1285
				qsrc = QSRC_INSTEAD_RULE;
B
Bruce Momjian 已提交
1286
				*instead_flag = true;	/* report unqualified INSTEAD */
1287
			}
1288 1289 1290 1291 1292
		}
		else
			qsrc = QSRC_NON_INSTEAD_RULE;

		if (qsrc == QSRC_QUAL_INSTEAD_RULE)
1293
		{
1294
			/*
1295
			 * If there are INSTEAD rules with qualifications, the
1296
			 * original query is still performed. But all the negated rule
1297
			 * qualifications of the INSTEAD rules are added so it does
1298
			 * its actions only in cases where the rule quals of all
1299
			 * INSTEAD rules are false. Think of it as the default action
B
Bruce Momjian 已提交
1300 1301
			 * in a case. We save this in *qual_product so RewriteQuery()
			 * can add it to the query list after we mangled it up enough.
1302
			 *
B
Bruce Momjian 已提交
1303 1304
			 * 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 已提交
1305
			 */
B
Bruce Momjian 已提交
1306
			if (!*instead_flag)
1307 1308
			{
				if (*qual_product == NULL)
1309
					*qual_product = copyObject(parsetree);
1310 1311 1312 1313
				*qual_product = CopyAndAddInvertedQual(*qual_product,
													   event_qual,
													   rt_index,
													   event);
1314
			}
M
 
Marc G. Fournier 已提交
1315 1316
		}

1317
		/* Now process the rule's actions and add them to the result list */
1318 1319
		foreach(r, actions)
		{
1320
			Query	   *rule_action = lfirst(r);
1321

M
 
Marc G. Fournier 已提交
1322 1323 1324
			if (rule_action->commandType == CMD_NOTHING)
				continue;

1325 1326
			rule_action = rewriteRuleAction(parsetree, rule_action,
											event_qual, rt_index, event);
1327

1328
			rule_action->querySource = qsrc;
1329
			rule_action->canSetTag = false;		/* might change later */
1330

1331
			results = lappend(results, rule_action);
1332 1333
		}
	}
1334

1335
	return results;
1336 1337
}

M
 
Marc G. Fournier 已提交
1338

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

1354
	/*
1355 1356
	 * If the statement is an update, insert or delete - fire rules on it.
	 *
B
Bruce Momjian 已提交
1357
	 * SELECT rules are handled later when we have all the queries that
B
Bruce Momjian 已提交
1358 1359
	 * should get executed.  Also, utilities aren't rewritten at all (do
	 * we still need that check?)
1360
	 */
1361 1362 1363 1364 1365 1366
	if (event != CMD_SELECT && event != CMD_UTILITY)
	{
		int			result_relation;
		RangeTblEntry *rt_entry;
		Relation	rt_entry_relation;
		List	   *locks;
1367

1368 1369 1370 1371
		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 已提交
1372

1373
		/*
1374 1375
		 * We can use NoLock here since either the parser or
		 * AcquireRewriteLocks should have locked the rel already.
1376
		 */
1377
		rt_entry_relation = heap_open(rt_entry->relid, NoLock);
1378

1379
		/*
B
Bruce Momjian 已提交
1380 1381 1382 1383
		 * 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.
1384 1385 1386
		 */
		if (event == CMD_INSERT || event == CMD_UPDATE)
			rewriteTargetList(parsetree, rt_entry_relation);
1387

1388 1389 1390 1391 1392
		/*
		 * Collect and apply the appropriate rules.
		 */
		locks = matchLocks(event, rt_entry_relation->rd_rules,
						   result_relation, parsetree);
1393

1394 1395 1396
		if (locks != NIL)
		{
			List	   *product_queries;
1397

1398 1399 1400 1401 1402 1403
			product_queries = fireRules(parsetree,
										result_relation,
										event,
										locks,
										&instead,
										&qual_product);
1404

1405
			/*
B
Bruce Momjian 已提交
1406 1407
			 * If we got any product queries, recursively rewrite them ---
			 * but first check for recursion!
1408 1409 1410
			 */
			if (product_queries != NIL)
			{
B
Bruce Momjian 已提交
1411 1412
				ListCell   *n;
				rewrite_event *rev;
1413

1414 1415 1416 1417 1418
				foreach(n, rewrite_events)
				{
					rev = (rewrite_event *) lfirst(n);
					if (rev->relation == RelationGetRelid(rt_entry_relation) &&
						rev->event == event)
1419
						ereport(ERROR,
B
Bruce Momjian 已提交
1420 1421 1422
							 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
							  errmsg("infinite recursion detected in rules for relation \"%s\"",
						   RelationGetRelationName(rt_entry_relation))));
1423
				}
1424

1425 1426 1427 1428
				rev = (rewrite_event *) palloc(sizeof(rewrite_event));
				rev->relation = RelationGetRelid(rt_entry_relation);
				rev->event = event;
				rewrite_events = lcons(rev, rewrite_events);
1429

1430 1431 1432 1433
				foreach(n, product_queries)
				{
					Query	   *pt = (Query *) lfirst(n);
					List	   *newstuff;
1434

1435
					newstuff = RewriteQuery(pt, rewrite_events);
1436
					rewritten = list_concat(rewritten, newstuff);
1437
				}
1438 1439

				rewrite_events = list_delete_first(rewrite_events);
1440 1441
			}
		}
1442

1443
		heap_close(rt_entry_relation, NoLock);
1444
	}
M
 
Marc G. Fournier 已提交
1445

1446
	/*
1447 1448 1449 1450
	 * 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
1451
	 * query executions makes the deleted (and maybe the updated) tuples
1452 1453
	 * disappear so the scans for them in the rule actions cannot find
	 * them.
1454
	 *
B
Bruce Momjian 已提交
1455 1456 1457
	 * 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 已提交
1458
	 */
1459
	if (!instead)
1460
	{
1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474
		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);
		}
1475
	}
M
 
Marc G. Fournier 已提交
1476

1477 1478
	return rewritten;
}
1479 1480 1481


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

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

	/*
1508
	 * Step 2
1509 1510 1511
	 *
	 * Apply all the RIR rules on each query
	 */
B
Bruce Momjian 已提交
1512 1513
	foreach(l, querylist)
	{
B
Bruce Momjian 已提交
1514
		Query	   *query = (Query *) lfirst(l);
B
Bruce Momjian 已提交
1515

1516
		query = fireRIRrules(query, NIL);
1517

B
Bruce Momjian 已提交
1518
		/*
1519
		 * If the query target was rewritten as a view, complain.
B
Bruce Momjian 已提交
1520
		 */
1521
		if (query->resultRelation)
B
Bruce Momjian 已提交
1522
		{
1523 1524
			RangeTblEntry *rte = rt_fetch(query->resultRelation,
										  query->rtable);
B
Bruce Momjian 已提交
1525

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

1556
		results = lappend(results, query);
B
Bruce Momjian 已提交
1557
	}
1558

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

1606
	return results;
B
Hi!  
Bruce Momjian 已提交
1607
}