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
10
 *	  $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.159 2005/11/22 18:17:19 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
				 *
124 125 126 127 128 129
				 * 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.
130 131 132 133 134 135 136 137 138 139 140 141 142
				 */
				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 已提交
143

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

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


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

271
	/*
B
Bruce Momjian 已提交
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!).
274 275 276 277
	 */
	rule_action = (Query *) copyObject(rule_action);
	rule_qual = (Node *) copyObject(rule_qual);

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

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

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

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

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

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

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

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

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

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

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

414
	return rule_action;
415 416
}

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

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

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

				/*
B
Bruce Momjian 已提交
443
				 * foreach is safe because we exit loop after list_delete...
B
Bruce Momjian 已提交
444
				 */
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

	/*
B
Bruce Momjian 已提交
496 497 498 499
	 * 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.
500
	 *
B
Bruce Momjian 已提交
501 502
	 * 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
			/*
B
Bruce Momjian 已提交
533 534
			 * Copy all resjunk tlist entries to junk_tlist, and assign them
			 * resnos above the last real resno.
535
			 *
536 537
			 * Typical junk entries include ORDER BY or GROUP BY expressions
			 * (are these actually possible in an INSERT or UPDATE?), system
538 539
			 * 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
			/*
B
Bruce Momjian 已提交
575 576 577 578 579
			 * 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.
580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
			 */
			if (!new_expr)
			{
				if (commandType == CMD_INSERT)
					new_tle = NULL;
				else
				{
					new_expr = (Node *) makeConst(att_tup->atttypid,
												  att_tup->attlen,
												  (Datum) 0,
												  true, /* isnull */
												  att_tup->attbyval);
					/* this is to catch a NOT NULL domain constraint */
					new_expr = coerce_to_domain(new_expr,
												InvalidOid,
												att_tup->atttypid,
596
												COERCE_IMPLICIT_CAST,
597
												false,
598
												false);
599 600 601
				}
			}

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

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

613
	pfree(new_tles);
614

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


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

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

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

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

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

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

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

739 740 741
	result = flatCopyTargetEntry(src_tle);
	result->expr = (Expr *) newexpr;
	return result;
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 767
/*
 * 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;
}
768 769 770 771 772 773

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

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

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

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

	return expr;
}


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

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

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

867
	nlocks = rulelocks->numLocks;
868

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

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

884
	return matching_locks;
885 886
}

887

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

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

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

916 917 918 919 920
	AcquireRewriteLocks(rule_action);

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

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

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

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

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

946
	/*
947
	 * FOR UPDATE/SHARE of view?
948
	 */
949
	if (list_member_int(parsetree->rowMarks, rt_index))
950
	{
951
		/*
B
Bruce Momjian 已提交
952 953 954
		 * 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.
955
		 */
956
		parsetree->rowMarks = list_delete_int(parsetree->rowMarks, rt_index);
B
Bruce Momjian 已提交
957 958

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

965
	return parsetree;
966 967
}

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

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

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

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

1020

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

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

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


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

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

1081 1082
		++rt_index;

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

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

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

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

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

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

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

			locks = lappend(locks, rule);
		}

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

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

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

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

			activeRIRs = list_delete_first(activeRIRs);
1173 1174
		}

1175
		heap_close(rel, NoLock);
1176 1177
	}

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

	return parsetree;
}


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

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

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

1234
	return parsetree;
1235 1236 1237 1238
}


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

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

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

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

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

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

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

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

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

1340
	return results;
1341 1342
}

M
 
Marc G. Fournier 已提交
1343

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1480 1481
	return rewritten;
}
1482 1483 1484


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

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

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

1519
		query = fireRIRrules(query, NIL);
1520

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

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

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

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

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