rewriteHandler.c 46.0 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
B
Bruce Momjian 已提交
10
 *	  $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.158 2005/10/15 02:49:24 momjian 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 noWait,
B
Bruce Momjian 已提交
56
					bool skipOldNew);
57
static List *matchLocks(CmdType event, RuleLock *rulelocks,
B
Bruce Momjian 已提交
58
		   int varno, Query *parsetree);
59
static Query *fireRIRrules(Query *parsetree, List *activeRIRs);
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 109
/*
 * 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;
110 111
		Index		curinputvarno;
		RangeTblEntry *curinputrte;
112 113 114 115 116 117
		ListCell   *ll;

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

119
				/*
B
Bruce Momjian 已提交
120 121 122
				 * 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.
123
				 *
B
Bruce Momjian 已提交
124 125 126 127 128
				 * 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.
129 130 131 132 133 134 135 136 137 138 139 140 141
				 */
				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:
B
Bruce Momjian 已提交
142

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

205 206 207 208 209 210 211 212 213 214 215 216 217 218
				/*
				 * 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 已提交
219 220
	 * Recurse into sublink subqueries, too.  But we already did the ones in
	 * the rtable.
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
	 */
	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);
}


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

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

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

283
	current_varno = rt_index;
284
	rt_length = list_length(parsetree->rtable);
285
	new_varno = PRS2_NEW_VARNO + rt_length;
286

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

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

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

336 337
	/*
	 * Each rule action's jointree should be the main parsetree's jointree
B
Bruce Momjian 已提交
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
	 *
B
Bruce Momjian 已提交
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) ||
B
Bruce Momjian 已提交
359
			 rangeTableEntry_used(parsetree->jointree->quals, rt_index, 0));
360
		newjointree = adjustJoinTreeList(parsetree, !keeporig, rt_index);
361 362 363
		if (newjointree != NIL)
		{
			/*
B
Bruce Momjian 已提交
364 365 366 367
			 * 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?)
368 369
			 */
			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
	 *
B
Bruce Momjian 已提交
392 393 394
	 * 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.
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

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

451

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

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

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

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

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

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

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

			new_expr = build_column_default(target_relation, attrno);

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

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

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

612
	pfree(new_tles);
613

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


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

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

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

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

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

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

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

738 739 740
	result = flatCopyTargetEntry(src_tle);
	result->expr = (Expr *) newexpr;
	return result;
741 742
}

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

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

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

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

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

	return expr;
}


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

857 858
	if (rulelocks == NULL)
		return NIL;
859

860
	if (parsetree->commandType != CMD_SELECT)
861
	{
862 863
		if (parsetree->resultRelation != varno)
			return NIL;
864
	}
865

866
	nlocks = rulelocks->numLocks;
867

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

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

883
	return matching_locks;
884 885
}

886

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

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

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

915 916 917 918 919
	AcquireRewriteLocks(rule_action);

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

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

928
	rte->rtekind = RTE_SUBQUERY;
929 930 931
	rte->relid = InvalidOid;
	rte->subquery = rule_action;
	rte->inh = false;			/* must not be set for a subquery */
932

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

942
	rte->requiredPerms = 0;		/* no permission check on subquery itself */
943
	rte->checkAsUser = InvalidOid;
944

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

		/*
958
		 * Set up the view's referenced tables as if FOR UPDATE/SHARE.
959
		 */
960 961
		markQueryForLocking(rule_action, parsetree->forUpdate,
							parsetree->rowNoWait, true);
962 963
	}

964
	return parsetree;
965 966
}

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

981 982 983 984 985
	if (qry->rowMarks)
	{
		if (forUpdate != qry->forUpdate)
			ereport(ERROR,
					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
B
Bruce Momjian 已提交
986
			errmsg("cannot use both FOR UPDATE and FOR SHARE in one query")));
987 988 989 990 991
		if (noWait != qry->rowNoWait)
			ereport(ERROR,
					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
					 errmsg("cannot use both wait and NOWAIT in one query")));
	}
992
	qry->forUpdate = forUpdate;
993
	qry->rowNoWait = noWait;
994

995 996 997 998 999 1000 1001 1002 1003 1004 1005
	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;

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

1019

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

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

1048
	/*
B
Bruce Momjian 已提交
1049 1050
	 * Do NOT recurse into Query nodes, because fireRIRrules already processed
	 * subselects of subselects for us.
1051
	 */
1052
	return expression_tree_walker(node, fireRIRonSubLink,
1053
								  (void *) activeRIRs);
1054 1055 1056 1057 1058 1059 1060 1061
}


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

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

1080 1081
		++rt_index;

1082
		rte = rt_fetch(rt_index, parsetree->rtable);
1083

1084
		/*
B
Bruce Momjian 已提交
1085 1086
		 * 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
1087 1088
		 * subquery to expand any rule references in it.
		 */
1089
		if (rte->rtekind == RTE_SUBQUERY)
1090
		{
1091
			rte->subquery = fireRIRrules(rte->subquery, activeRIRs);
1092 1093 1094
			continue;
		}

1095 1096 1097 1098 1099 1100
		/*
		 * Joins and other non-relation RTEs can be ignored completely.
		 */
		if (rte->rtekind != RTE_RELATION)
			continue;

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

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

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

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

			locks = lappend(locks, rule);
		}

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

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

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

				parsetree = ApplyRetrieveRule(parsetree,
											  rule,
											  rt_index,
											  rule->attrno == -1,
											  rel,
1168
											  activeRIRs);
1169
			}
1170 1171

			activeRIRs = list_delete_first(activeRIRs);
1172 1173
		}

1174
		heap_close(rel, NoLock);
1175 1176
	}

1177
	/*
B
Bruce Momjian 已提交
1178 1179
	 * Recurse into sublink subqueries, too.  But we already did the ones in
	 * the rtable.
1180 1181
	 */
	if (parsetree->hasSubLinks)
1182
		query_tree_walker(parsetree, fireRIRonSubLink, (void *) activeRIRs,
1183
						  QTW_IGNORE_RT_SUBQUERIES);
1184 1185 1186 1187 1188

	return parsetree;
}


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

1211 1212 1213
	/*
	 * 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 已提交
1214 1215
	 * rewriteRuleAction, but not entirely ... consider restructuring so that
	 * we only need to process the qual this way once.)
1216 1217 1218
	 */
	(void) acquireLocksOnSubLinks(new_qual, NULL);

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

1233
	return parsetree;
1234 1235 1236 1237
}


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

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

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

		if (qsrc == QSRC_QUAL_INSTEAD_RULE)
1297
		{
1298
			/*
B
Bruce Momjian 已提交
1299 1300 1301 1302 1303 1304 1305
			 * 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.
1306
			 *
B
Bruce Momjian 已提交
1307 1308
			 * 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 已提交
1309
			 */
B
Bruce Momjian 已提交
1310
			if (!*instead_flag)
1311 1312
			{
				if (*qual_product == NULL)
1313
					*qual_product = copyObject(parsetree);
1314 1315 1316 1317
				*qual_product = CopyAndAddInvertedQual(*qual_product,
													   event_qual,
													   rt_index,
													   event);
1318
			}
M
 
Marc G. Fournier 已提交
1319 1320
		}

1321
		/* Now process the rule's actions and add them to the result list */
1322 1323
		foreach(r, actions)
		{
1324
			Query	   *rule_action = lfirst(r);
1325

M
 
Marc G. Fournier 已提交
1326 1327 1328
			if (rule_action->commandType == CMD_NOTHING)
				continue;

1329 1330
			rule_action = rewriteRuleAction(parsetree, rule_action,
											event_qual, rt_index, event);
1331

1332
			rule_action->querySource = qsrc;
1333
			rule_action->canSetTag = false;		/* might change later */
1334

1335
			results = lappend(results, rule_action);
1336 1337
		}
	}
1338

1339
	return results;
1340 1341
}

M
 
Marc G. Fournier 已提交
1342

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

1358
	/*
1359 1360
	 * If the statement is an update, insert or delete - fire rules on it.
	 *
B
Bruce Momjian 已提交
1361 1362 1363
	 * 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?)
1364
	 */
1365 1366 1367 1368 1369 1370
	if (event != CMD_SELECT && event != CMD_UTILITY)
	{
		int			result_relation;
		RangeTblEntry *rt_entry;
		Relation	rt_entry_relation;
		List	   *locks;
1371

1372 1373 1374 1375
		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 已提交
1376

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

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

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

1397 1398 1399
		if (locks != NIL)
		{
			List	   *product_queries;
1400

1401 1402 1403 1404 1405 1406
			product_queries = fireRules(parsetree,
										result_relation,
										event,
										locks,
										&instead,
										&qual_product);
1407

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

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

1428 1429 1430 1431
				rev = (rewrite_event *) palloc(sizeof(rewrite_event));
				rev->relation = RelationGetRelid(rt_entry_relation);
				rev->event = event;
				rewrite_events = lcons(rev, rewrite_events);
1432

1433 1434 1435 1436
				foreach(n, product_queries)
				{
					Query	   *pt = (Query *) lfirst(n);
					List	   *newstuff;
1437

1438
					newstuff = RewriteQuery(pt, rewrite_events);
1439
					rewritten = list_concat(rewritten, newstuff);
1440
				}
1441 1442

				rewrite_events = list_delete_first(rewrite_events);
1443 1444
			}
		}
1445

1446
		heap_close(rt_entry_relation, NoLock);
1447
	}
M
 
Marc G. Fournier 已提交
1448

1449
	/*
B
Bruce Momjian 已提交
1450 1451 1452 1453 1454 1455
	 * 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.
1456
	 *
B
Bruce Momjian 已提交
1457 1458 1459
	 * 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 已提交
1460
	 */
1461
	if (!instead)
1462
	{
1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476
		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);
		}
1477
	}
M
 
Marc G. Fournier 已提交
1478

1479 1480
	return rewritten;
}
1481 1482 1483


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

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

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

1518
		query = fireRIRrules(query, NIL);
1519

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

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

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

1561 1562 1563
	/*
	 * Step 3
	 *
B
Bruce Momjian 已提交
1564 1565
	 * Determine which, if any, of the resulting queries is supposed to set the
	 * command-result tag; and update the canSetTag fields accordingly.
1566 1567
	 *
	 * If the original query is still in the list, it sets the command tag.
B
Bruce Momjian 已提交
1568 1569 1570 1571
	 * 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.)
1572 1573
	 *
	 * The Asserts verify that at most one query in the result list is marked
B
Bruce Momjian 已提交
1574 1575
	 * canSetTag.  If we aren't checking asserts, we can fall out of the loop
	 * as soon as we find the original query.
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 1606
	 */
	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;

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