subselect.c 17.1 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * subselect.c
4 5 6 7 8
 *	  Planning routines for subselects and parameters.
 *
 * Copyright (c) 1994, Regents of the University of California
 *
 * IDENTIFICATION
9
 *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.23 1999/08/22 20:14:49 tgl Exp $
10 11 12 13 14 15 16 17 18
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

#include "catalog/pg_type.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
B
Bruce Momjian 已提交
19 20
#include "optimizer/planner.h"
#include "optimizer/subselect.h"
21

22 23
int			PlannerQueryLevel;	/* level of current query */
List	   *PlannerInitPlan;	/* init subplans for current query */
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
List	   *PlannerParamVar;	/* to get Var from Param->paramid */
int			PlannerPlanId;		/* to assign unique ID to subquery plans */

/*--------------------
 * PlannerParamVar is a list of Var nodes, wherein the n'th entry
 * (n counts from 0) corresponds to Param->paramid = n.  The Var nodes
 * are ordinary except for one thing: their varlevelsup field does NOT
 * have the usual interpretation of "subplan levels out from current".
 * Instead, it contains the absolute plan level, with the outermost
 * plan being level 1 and nested plans having higher level numbers.
 * This nonstandardness is useful because we don't have to run around
 * and update the list elements when we enter or exit a subplan
 * recursion level.  But we must pay attention not to confuse this
 * meaning with the normal meaning of varlevelsup.
 *--------------------
 */
40 41


42 43 44 45 46 47
/*
 * Create a new entry in the PlannerParamVar list, and return its index.
 *
 * var contains the data to be copied, except for varlevelsup which
 * is set from the absolute level value given by varlevel.
 */
48
static int
49
_new_param(Var *var, int varlevel)
50
{
51
	Var		   *paramVar = (Var *) copyObject(var);
52

53
	paramVar->varlevelsup = varlevel;
54

55
	PlannerParamVar = lappend(PlannerParamVar, paramVar);
56

57
	return length(PlannerParamVar) - 1;
58 59
}

60 61 62 63
/*
 * Generate a Param node to replace the given Var,
 * which is expected to have varlevelsup > 0 (ie, it is not local).
 */
64 65
static Param *
_replace_var(Var *var)
66
{
67
	List	   *ppv;
68
	Param	   *retval;
69
	int			varlevel;
70 71
	int			i;

72 73
	Assert(var->varlevelsup > 0 && var->varlevelsup < PlannerQueryLevel);
	varlevel = PlannerQueryLevel - var->varlevelsup;
74

75 76 77 78 79 80 81 82 83 84 85 86
	/*
	 * If there's already a PlannerParamVar entry for this same Var,
	 * just use it.  NOTE: in situations involving UNION or inheritance,
	 * it is possible for the same varno/varlevel to refer to different RTEs
	 * in different parts of the parsetree, so that different fields might
	 * end up sharing the same Param number.  As long as we check the vartype
	 * as well, I believe that this sort of aliasing will cause no trouble.
	 * The correct field should get stored into the Param slot at execution
	 * in each part of the tree.
	 */
	i = 0;
	foreach(ppv, PlannerParamVar)
87
	{
88 89 90 91 92 93
		Var	   *pvar = lfirst(ppv);

		if (pvar->varno == var->varno &&
			pvar->varattno == var->varattno &&
			pvar->varlevelsup == varlevel &&
			pvar->vartype == var->vartype)
94
			break;
95
		i++;
96
	}
97

98 99 100 101 102
	if (! ppv)
	{
		/* Nope, so make a new one */
		i = _new_param(var, varlevel);
	}
103

104 105 106 107
	retval = makeNode(Param);
	retval->paramkind = PARAM_EXEC;
	retval->paramid = (AttrNumber) i;
	retval->paramtype = var->vartype;
108

109
	return retval;
110 111
}

112 113
static Node *
_make_subplan(SubLink *slink)
114
{
115
	SubPlan    *node = makeNode(SubPlan);
116 117 118 119
	Plan	   *plan;
	List	   *lst;
	Node	   *result;
	List	   *saved_ip = PlannerInitPlan;
120

121
	PlannerInitPlan = NULL;
122

123
	PlannerQueryLevel++;		/* we becomes child */
124 125 126 127 128 129 130

	node->plan = plan = union_planner((Query *) slink->subselect);

	/*
	 * Assign subPlan, extParam and locParam to plan nodes. At the moment,
	 * SS_finalize_plan doesn't handle initPlan-s and so we assigne them
	 * to the topmost plan node and take care about its extParam too.
131
	 */
132
	(void) SS_finalize_plan(plan);
133
	plan->initPlan = PlannerInitPlan;
134

135
	/* Create extParam list as union of InitPlan-s' lists */
136
	foreach(lst, PlannerInitPlan)
137
	{
138 139 140
		List	   *lp;

		foreach(lp, ((SubPlan *) lfirst(lst))->plan->extParam)
141
		{
142 143
			if (!intMember(lfirsti(lp), plan->extParam))
				plan->extParam = lappendi(plan->extParam, lfirsti(lp));
144 145
		}
	}
146

147 148 149
	/* and now we are parent again */
	PlannerInitPlan = saved_ip;
	PlannerQueryLevel--;
150

151
	node->plan_id = PlannerPlanId++;
152
	node->rtable = ((Query *) slink->subselect)->rtable;
153 154
	node->sublink = slink;
	slink->subselect = NULL;	/* cool ?! */
155

156
	/* make parParam list of params coming from current query level */
157
	foreach(lst, plan->extParam)
158
	{
159 160
		Var		   *var = nth(lfirsti(lst), PlannerParamVar);

161
		/* note varlevelsup is absolute level number */
162 163
		if (var->varlevelsup == PlannerQueryLevel)
			node->parParam = lappendi(node->parParam, lfirsti(lst));
164
	}
165 166 167 168

	/*
	 * Un-correlated or undirect correlated plans of EXISTS or EXPR types
	 * can be used as initPlans...
169
	 */
170
	if (node->parParam == NULL && slink->subLinkType == EXPR_SUBLINK)
171
	{
172 173
		int			i = 0;

174
		/* transform right side of all sublink Oper-s into Param */
175
		foreach(lst, slink->oper)
176
		{
177 178 179
			List	   *rside = lnext(((Expr *) lfirst(lst))->args);
			TargetEntry *te = nth(i, plan->targetlist);
			Var		   *var = makeVar(0, 0, te->resdom->restype,
180
									  te->resdom->restypmod, 0);
181 182
			Param	   *prm = makeNode(Param);

183
			prm->paramkind = PARAM_EXEC;
184
			prm->paramid = (AttrNumber) _new_param(var, PlannerQueryLevel);
185 186
			prm->paramtype = var->vartype;
			lfirst(rside) = prm;
187 188
			node->setParam = lappendi(node->setParam, prm->paramid);
			pfree(var);
189 190
			i++;
		}
191 192 193 194
		PlannerInitPlan = lappend(PlannerInitPlan, node);
		if (i > 1)
			result = (Node *) ((slink->useor) ? make_orclause(slink->oper) :
							   make_andclause(slink->oper));
195
		else
196
			result = (Node *) lfirst(slink->oper);
197
	}
198
	else if (node->parParam == NULL && slink->subLinkType == EXISTS_SUBLINK)
199
	{
200
		Var		   *var = makeVar(0, 0, BOOLOID, -1, 0);
201
		Param	   *prm = makeNode(Param);
202

203
		prm->paramkind = PARAM_EXEC;
204
		prm->paramid = (AttrNumber) _new_param(var, PlannerQueryLevel);
205
		prm->paramtype = var->vartype;
206 207 208 209
		node->setParam = lappendi(node->setParam, prm->paramid);
		pfree(var);
		PlannerInitPlan = lappend(PlannerInitPlan, node);
		result = (Node *) prm;
210
	}
211
	else
212
	{
213
		/* make expression of SUBPLAN type */
214
		Expr	   *expr = makeNode(Expr);
215
		List	   *args = NIL;
216 217
		int			i = 0;

218 219
		expr->typeOid = BOOLOID;
		expr->opType = SUBPLAN_EXPR;
220 221 222 223 224 225
		expr->oper = (Node *) node;

		/*
		 * Make expr->args from parParam. Left sides of sublink Oper-s are
		 * handled by optimizer directly... Also, transform right side of
		 * sublink Oper-s into Const.
226
		 */
227
		foreach(lst, node->parParam)
228
		{
229 230 231
			Var		   *var = nth(lfirsti(lst), PlannerParamVar);

			var = (Var *) copyObject(var);
232 233 234 235
			/* Must fix absolute-level varlevelsup from the
			 * PlannerParamVar entry.  But since var is at current
			 * subplan level, this is easy:
			 */
236
			var->varlevelsup = 0;
237
			args = lappend(args, var);
238
		}
239
		foreach(lst, slink->oper)
240
		{
241 242 243 244 245
			List	   *rside = lnext(((Expr *) lfirst(lst))->args);
			TargetEntry *te = nth(i, plan->targetlist);
			Const	   *con = makeConst(te->resdom->restype,
										0, 0, true, 0, 0, 0);

246 247 248 249
			lfirst(rside) = con;
			i++;
		}
		expr->args = args;
250
		result = (Node *) expr;
251
	}
252

253
	return result;
254 255 256
}

static List *
257
set_unioni(List *l1, List *l2)
258 259
{
	if (l1 == NULL)
260
		return l2;
261
	if (l2 == NULL)
262
		return l1;
263

264
	return nconc(l1, set_differencei(l2, l1));
265 266
}

267 268 269 270
typedef struct finalize_primnode_results {
	List	*subplans;			/* List of subplans found in expr */
	List	*paramids;			/* List of PARAM_EXEC paramids found */
} finalize_primnode_results;
271

272 273
static bool finalize_primnode_walker(Node *node,
									 finalize_primnode_results *results);
274

275 276 277 278 279 280 281
static void
finalize_primnode(Node *expr, finalize_primnode_results *results)
{
	results->subplans = NIL;	/* initialize */
	results->paramids = NIL;
	(void) finalize_primnode_walker(expr, results);
}
282

283 284 285 286 287 288 289
static bool
finalize_primnode_walker(Node *node,
						 finalize_primnode_results *results)
{
	if (node == NULL)
		return false;
	if (IsA(node, Param))
290
	{
291 292 293 294 295 296 297 298
		if (((Param *) node)->paramkind == PARAM_EXEC)
		{
			int		paramid = (int) ((Param *) node)->paramid;

			if (! intMember(paramid, results->paramids))
				results->paramids = lconsi(paramid, results->paramids);
		}
		return false;			/* no more to do here */
299
	}
300
	if (is_subplan(node))
301
	{
302
		SubPlan	   *subplan = (SubPlan *) ((Expr *) node)->oper;
303 304
		List	   *lst;

305 306 307 308
		/* Add subplan to subplans list */
		results->subplans = lappend(results->subplans, subplan);
		/* Check extParam list for params to add to paramids */
		foreach(lst, subplan->plan->extParam)
309
		{
310 311
			int			paramid = lfirsti(lst);
			Var		   *var = nth(paramid, PlannerParamVar);
312

313
			/* note varlevelsup is absolute level number */
314
			if (var->varlevelsup < PlannerQueryLevel &&
315 316
				! intMember(paramid, results->paramids))
				results->paramids = lconsi(paramid, results->paramids);
317
		}
318 319 320 321 322
		/* XXX We do NOT allow expression_tree_walker to examine the args
		 * passed to the subplan.  Is that correct???  It's what the
		 * old code did, but it seems mighty bogus...  tgl 7/14/99
		 */
		return false;			/* don't recurse into subplan args */
323
	}
324 325
	return expression_tree_walker(node, finalize_primnode_walker,
								  (void *) results);
326 327
}

328 329 330 331 332 333
/* Replace correlation vars (uplevel vars) with Params. */

/* XXX should replace this with use of a generalized tree rebuilder,
 * designed along the same lines as expression_tree_walker.
 * Not done yet.
 */
334
Node *
335
SS_replace_correlation_vars(Node *expr)
336
{
337
	if (expr == NULL)
338
		return NULL;
339 340 341 342 343 344 345 346
	if (IsA(expr, Var))
	{
		if (((Var *) expr)->varlevelsup > 0)
			expr = (Node *) _replace_var((Var *) expr);
	}
	else if (single_node(expr))
		return expr;
	else if (IsA(expr, List))
347
	{
348 349 350 351
		List	   *le;

		foreach(le, (List *) expr)
			lfirst(le) = SS_replace_correlation_vars((Node *) lfirst(le));
352
	}
353
	else if (IsA(expr, Expr))
354
	{
355
		/* XXX do we need to do anything special with subplans? */
356 357
		((Expr *) expr)->args = (List *)
			SS_replace_correlation_vars((Node *) ((Expr *) expr)->args);
358
	}
B
Bruce Momjian 已提交
359
	else if (IsA(expr, Aggref))
360 361 362
		((Aggref *) expr)->target = SS_replace_correlation_vars(((Aggref *) expr)->target);
	else if (IsA(expr, Iter))
		((Iter *) expr)->iterexpr = SS_replace_correlation_vars(((Iter *) expr)->iterexpr);
363
	else if (IsA(expr, ArrayRef))
364
	{
365 366 367 368
		((ArrayRef *) expr)->refupperindexpr = (List *)
			SS_replace_correlation_vars((Node *) ((ArrayRef *) expr)->refupperindexpr);
		((ArrayRef *) expr)->reflowerindexpr = (List *)
			SS_replace_correlation_vars((Node *) ((ArrayRef *) expr)->reflowerindexpr);
369
		((ArrayRef *) expr)->refexpr = SS_replace_correlation_vars(((ArrayRef *) expr)->refexpr);
370
		((ArrayRef *) expr)->refassgnexpr = SS_replace_correlation_vars(((ArrayRef *) expr)->refassgnexpr);
371
	}
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387
	else if (IsA(expr, CaseExpr))
	{
		CaseExpr   *caseexpr = (CaseExpr *) expr;
		List	   *le;

		foreach(le, caseexpr->args)
		{
			CaseWhen   *when = (CaseWhen *) lfirst(le);
			Assert(IsA(when, CaseWhen));
			when->expr = SS_replace_correlation_vars(when->expr);
			when->result = SS_replace_correlation_vars(when->result);
		}
		/* caseexpr->arg should be null, but we'll check it anyway */
		caseexpr->arg = SS_replace_correlation_vars(caseexpr->arg);
		caseexpr->defresult = SS_replace_correlation_vars(caseexpr->defresult);
	}
388
	else if (IsA(expr, TargetEntry))
389
		((TargetEntry *) expr)->expr = SS_replace_correlation_vars(((TargetEntry *) expr)->expr);
390
	else if (IsA(expr, SubLink))
391
	{
392 393 394
		List	   *le;

		foreach(le, ((SubLink *) expr)->oper)	/* left sides only */
395
		{
396 397 398 399
			List	   *oparg = ((Expr *) lfirst(le))->args;

			lfirst(oparg) = (List *)
				SS_replace_correlation_vars((Node *) lfirst(oparg));
400
		}
401 402
		((SubLink *) expr)->lefthand = (List *)
			SS_replace_correlation_vars((Node *) ((SubLink *) expr)->lefthand);
403 404
	}
	else
405
		elog(ERROR, "SS_replace_correlation_vars: can't handle node %d",
406 407
			 nodeTag(expr));

408
	return expr;
409 410
}

411 412 413 414 415 416
/* Replace sublinks by subplans in the given expression */

/* XXX should replace this with use of a generalized tree rebuilder,
 * designed along the same lines as expression_tree_walker.
 * Not done yet.
 */
417 418
Node *
SS_process_sublinks(Node *expr)
419
{
420
	if (expr == NULL)
421
		return NULL;
422 423 424 425 426 427 428
	if (IsA(expr, SubLink))
	{
		expr = _make_subplan((SubLink *) expr);
	}
	else if (single_node(expr))
		return expr;
	else if (IsA(expr, List))
429
	{
430 431 432 433
		List	   *le;

		foreach(le, (List *) expr)
			lfirst(le) = SS_process_sublinks((Node *) lfirst(le));
434
	}
435 436 437 438 439
	else if (IsA(expr, Expr))
	{
		/* We should never see a subplan node here, since this is the
		 * routine that makes 'em in the first place.  No need to check.
		 */
440 441
		((Expr *) expr)->args = (List *)
			SS_process_sublinks((Node *) ((Expr *) expr)->args);
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474
	}
	else if (IsA(expr, Aggref))
		((Aggref *) expr)->target = SS_process_sublinks(((Aggref *) expr)->target);
	else if (IsA(expr, Iter))
		((Iter *) expr)->iterexpr = SS_process_sublinks(((Iter *) expr)->iterexpr);
	else if (IsA(expr, ArrayRef))
	{
		((ArrayRef *) expr)->refupperindexpr = (List *)
			SS_process_sublinks((Node *) ((ArrayRef *) expr)->refupperindexpr);
		((ArrayRef *) expr)->reflowerindexpr = (List *)
			SS_process_sublinks((Node *) ((ArrayRef *) expr)->reflowerindexpr);
		((ArrayRef *) expr)->refexpr = SS_process_sublinks(((ArrayRef *) expr)->refexpr);
		((ArrayRef *) expr)->refassgnexpr = SS_process_sublinks(((ArrayRef *) expr)->refassgnexpr);
	}
	else if (IsA(expr, CaseExpr))
	{
		CaseExpr   *caseexpr = (CaseExpr *) expr;
		List	   *le;

		foreach(le, caseexpr->args)
		{
			CaseWhen   *when = (CaseWhen *) lfirst(le);
			Assert(IsA(when, CaseWhen));
			when->expr = SS_process_sublinks(when->expr);
			when->result = SS_process_sublinks(when->result);
		}
		/* caseexpr->arg should be null, but we'll check it anyway */
		caseexpr->arg = SS_process_sublinks(caseexpr->arg);
		caseexpr->defresult = SS_process_sublinks(caseexpr->defresult);
	}
	else
		elog(ERROR, "SS_process_sublinks: can't handle node %d",
			 nodeTag(expr));
475

476
	return expr;
477 478
}

479 480
List *
SS_finalize_plan(Plan *plan)
481
{
482 483 484
	List	   *extParam = NIL;
	List	   *locParam = NIL;
	finalize_primnode_results results;
485 486 487
	List	   *lst;

	if (plan == NULL)
488
		return NULL;
489

490 491 492
	/* Find params in targetlist, make sure there are no subplans there */
	finalize_primnode((Node *) plan->targetlist, &results);
	Assert(results.subplans == NIL);
493

494 495 496 497 498
	/* From here on, we invoke finalize_primnode_walker not finalize_primnode,
	 * so that results.paramids lists are automatically merged together and
	 * we don't have to do it the hard way.  But when recursing to self,
	 * we do have to merge the lists.  Oh well.
	 */
499 500 501
	switch (nodeTag(plan))
	{
		case T_Result:
502 503 504
			finalize_primnode_walker(((Result *) plan)->resconstantqual,
									 &results);
			/* results.subplans is NOT necessarily empty here ... */
505 506 507
			break;

		case T_Append:
508
			foreach(lst, ((Append *) plan)->appendplans)
509 510
				results.paramids = set_unioni(results.paramids,
								SS_finalize_plan((Plan *) lfirst(lst)));
511
			break;
512

513
		case T_IndexScan:
514 515 516
			finalize_primnode_walker((Node *) ((IndexScan *) plan)->indxqual,
									 &results);
			Assert(results.subplans == NIL);
517 518 519
			break;

		case T_MergeJoin:
520 521 522
			finalize_primnode_walker((Node *) ((MergeJoin *) plan)->mergeclauses,
									 &results);
			Assert(results.subplans == NIL);
523 524 525
			break;

		case T_HashJoin:
526 527 528
			finalize_primnode_walker((Node *) ((HashJoin *) plan)->hashclauses,
									 &results);
			Assert(results.subplans == NIL);
529
			break;
530

531
		case T_Hash:
532 533 534
			finalize_primnode_walker((Node *) ((Hash *) plan)->hashkey,
									 &results);
			Assert(results.subplans == NIL);
535 536 537
			break;

		case T_Agg:
538
			/* XXX Code used to reject subplans in Aggref args; needed?? */
539
			break;
540

541 542 543 544 545 546 547
		case T_SeqScan:
		case T_NestLoop:
		case T_Material:
		case T_Sort:
		case T_Unique:
		case T_Group:
			break;
548

549
		default:
550 551
			elog(ERROR, "SS_finalize_plan: node %d unsupported",
				 nodeTag(plan));
552
			return NULL;
553
	}
554

555 556 557 558 559 560 561 562 563
	finalize_primnode_walker((Node *) plan->qual, &results);
	/* subplans are OK in the qual... */

	results.paramids = set_unioni(results.paramids,
								  SS_finalize_plan(plan->lefttree));
	results.paramids = set_unioni(results.paramids,
								  SS_finalize_plan(plan->righttree));

	/* Now we have all the paramids and subplans */
564

565
	foreach(lst, results.paramids)
566
	{
567 568
		Var		   *var = nth(lfirsti(lst), PlannerParamVar);

569
		/* note varlevelsup is absolute level number */
570 571 572
		if (var->varlevelsup < PlannerQueryLevel)
			extParam = lappendi(extParam, lfirsti(lst));
		else if (var->varlevelsup > PlannerQueryLevel)
573
			elog(ERROR, "SS_finalize_plan: plan shouldn't reference subplan's variable");
574 575
		else
		{
576 577
			Assert(var->varno == 0 && var->varattno == 0);
			locParam = lappendi(locParam, lfirsti(lst));
578 579
		}
	}
580

581 582
	plan->extParam = extParam;
	plan->locParam = locParam;
583
	plan->subPlan = results.subplans;
584

585
	return results.paramids;
586 587
}

588
/* Construct a list of all subplans found within the given node tree */
589

590 591
static bool SS_pull_subplan_walker(Node *node, List **listptr);

592
List *
593
SS_pull_subplan(Node *expr)
594
{
595
	List	   *result = NIL;
596

597 598 599
	SS_pull_subplan_walker(expr, &result);
	return result;
}
600

601 602 603 604 605 606
static bool
SS_pull_subplan_walker(Node *node, List **listptr)
{
	if (node == NULL)
		return false;
	if (is_subplan(node))
607
	{
608 609 610
		*listptr = lappend(*listptr, ((Expr *) node)->oper);
		/* XXX original code did not examine args to subplan, is this right? */
		return false;
611
	}
612 613
	return expression_tree_walker(node, SS_pull_subplan_walker,
								  (void *) listptr);
614
}