execAmi.c 13.0 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * execAmi.c
4
 *	  miscellanious executor access method routines
5 6 7
 *
 * Copyright (c) 1994, Regents of the University of California
 *
8
 *	$Id: execAmi.c,v 1.36 1999/07/13 21:17:31 momjian Exp $
9 10 11 12
 *
 *-------------------------------------------------------------------------
 */
/*
13
 *	 INTERFACE ROUTINES
14
 *
15 16 17 18 19 20 21 22
 *		ExecOpenScanR	\							  / amopen
 *		ExecBeginScan	 \							 /	ambeginscan
 *		ExecCloseR		  \							/	amclose
 *		ExecInsert		   \  executor interface   /	aminsert
 *		ExecReScanNode	   /  to access methods    \	amrescan
 *		ExecReScanR		  /							\	amrescan
 *		ExecMarkPos		 /							 \	ammarkpos
 *		ExecRestrPos	/							  \ amrestpos
23
 *
24
 *		ExecCreatR		function to create temporary relations
25 26
 *
 */
B
Bruce Momjian 已提交
27
#include <stdio.h>
28 29 30

#include "postgres.h"

31 32
#include "executor/executor.h"
#include "storage/smgr.h"
33
#include "utils/mcxt.h"
34 35 36
#include "executor/nodeSeqscan.h"
#include "executor/nodeIndexscan.h"
#include "executor/nodeSort.h"
V
Vadim B. Mikheev 已提交
37 38 39 40
#include "executor/nodeMaterial.h"
#include "executor/nodeNestloop.h"
#include "executor/nodeHashjoin.h"
#include "executor/nodeHash.h"
B
Hi!  
Bruce Momjian 已提交
41 42
#include "executor/nodeGroup.h"

V
Vadim B. Mikheev 已提交
43
#include "executor/nodeAgg.h"
B
Bruce Momjian 已提交
44
#include "executor/nodeGroup.h"
V
Vadim B. Mikheev 已提交
45
#include "executor/nodeResult.h"
46
#include "executor/nodeUnique.h"
V
Vadim B. Mikheev 已提交
47
#include "executor/nodeMergejoin.h"
B
Bruce Momjian 已提交
48
#include "executor/nodeAppend.h"
V
Vadim B. Mikheev 已提交
49
#include "executor/nodeSubplan.h"
M
Marc G. Fournier 已提交
50
#include "executor/execdebug.h"
51
#include "optimizer/internal.h" /* for _NONAME_RELATION_ID_ */
M
Marc G. Fournier 已提交
52 53 54
#include "access/genam.h"
#include "access/heapam.h"
#include "catalog/heap.h"
55

56
static Pointer ExecBeginScan(Relation relation, int nkeys, ScanKey skeys,
57
			  bool isindex, ScanDirection dir, Snapshot snapshot);
58 59
static Relation ExecOpenR(Oid relationOid, bool isindex);

60
/* ----------------------------------------------------------------
61
 *		ExecOpenScanR
62 63
 *
 * old comments:
64 65 66 67 68 69 70 71 72 73
 *		Parameters:
 *		  relation -- relation to be opened and scanned.
 *		  nkeys    -- number of keys
 *		  skeys    -- keys to restrict scanning
 *			 isindex  -- if this is true, the relation is the relid of
 *						 an index relation, else it is an index into the
 *						 range table.
 *		Returns the relation as(relDesc scanDesc)
 *		   If this structure is changed, need to modify the access macros
 *		defined in execInt.h.
74 75 76 77
 * ----------------------------------------------------------------
 */
void
ExecOpenScanR(Oid relOid,
78 79 80 81
			  int nkeys,
			  ScanKey skeys,
			  bool isindex,
			  ScanDirection dir,
82
			  Snapshot snapshot,
83 84
			  Relation *returnRelation, /* return */
			  Pointer *returnScanDesc)	/* return */
85
{
86 87
	Relation	relation;
	Pointer		scanDesc;
88 89 90 91 92 93 94 95 96 97 98 99 100

	/* ----------------
	 *	note: scanDesc returned by ExecBeginScan can be either
	 *		  a HeapScanDesc or an IndexScanDesc so for now we
	 *		  make it a Pointer.  There should be a better scan
	 *		  abstraction someday -cim 9/9/89
	 * ----------------
	 */
	relation = ExecOpenR(relOid, isindex);
	scanDesc = ExecBeginScan(relation,
							 nkeys,
							 skeys,
							 isindex,
101 102
							 dir,
							 snapshot);
103 104 105 106 107

	if (returnRelation != NULL)
		*returnRelation = relation;
	if (scanDesc != NULL)
		*returnScanDesc = scanDesc;
108
}
109

110
/* ----------------------------------------------------------------
111
 *		ExecOpenR
112
 *
113
 *		returns a relation descriptor given an object id.
114 115
 * ----------------------------------------------------------------
 */
116
static Relation
117 118
ExecOpenR(Oid relationOid, bool isindex)
{
119
	Relation	relation;
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136

	relation = (Relation) NULL;

	/* ----------------
	 *	open the relation with the correct call depending
	 *	on whether this is a heap relation or an index relation.
	 * ----------------
	 */
	if (isindex)
		relation = index_open(relationOid);
	else
		relation = heap_open(relationOid);

	if (relation == NULL)
		elog(DEBUG, "ExecOpenR: relation == NULL, heap_open failed.");

	return relation;
137
}
138

139
/* ----------------------------------------------------------------
140
 *		ExecBeginScan
141
 *
142
 *		beginscans a relation in current direction.
143
 *
144 145 146 147 148
 *		XXX fix parameters to AMbeginscan (and btbeginscan)
 *				currently we need to pass a flag stating whether
 *				or not the scan should begin at an endpoint of
 *				the relation.. Right now we always pass false
 *				-cim 9/14/89
149 150
 * ----------------------------------------------------------------
 */
151
static Pointer
152
ExecBeginScan(Relation relation,
153 154 155
			  int nkeys,
			  ScanKey skeys,
			  bool isindex,
156 157
			  ScanDirection dir,
			  Snapshot snapshot)
158
{
159
	Pointer		scanDesc;
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181

	scanDesc = NULL;

	/* ----------------
	 *	open the appropriate type of scan.
	 *
	 *	Note: ambeginscan()'s second arg is a boolean indicating
	 *		  that the scan should be done in reverse..  That is,
	 *		  if you pass it true, then the scan is backward.
	 * ----------------
	 */
	if (isindex)
	{
		scanDesc = (Pointer) index_beginscan(relation,
											 false,		/* see above comment */
											 nkeys,
											 skeys);
	}
	else
	{
		scanDesc = (Pointer) heap_beginscan(relation,
											ScanDirectionIsBackward(dir),
182
											snapshot,
183 184 185 186 187 188 189 190 191
											nkeys,
											skeys);
	}

	if (scanDesc == NULL)
		elog(DEBUG, "ExecBeginScan: scanDesc = NULL, heap_beginscan failed.");


	return scanDesc;
192
}
193

194
/* ----------------------------------------------------------------
195
 *		ExecCloseR
196
 *
197 198
 *		closes the relation and scan descriptor for a scan or sort
 *		node.  Also closes index relations and scans for index scans.
199 200
 *
 * old comments
201
 *		closes the relation indicated in 'relID'
202 203 204
 * ----------------------------------------------------------------
 */
void
205
ExecCloseR(Plan *node)
206
{
207
	CommonScanState *state;
208 209
	Relation	relation;
	HeapScanDesc scanDesc;
210 211 212 213 214 215 216 217

	/* ----------------
	 *	shut down the heap scan and close the heap relation
	 * ----------------
	 */
	switch (nodeTag(node))
	{

218 219 220
		case T_SeqScan:
			state = ((SeqScan *) node)->scanstate;
			break;
221

222 223 224
		case T_IndexScan:
			state = ((IndexScan *) node)->scan.scanstate;
			break;
225

226 227 228
		case T_Material:
			state = &(((Material *) node)->matstate->csstate);
			break;
229

230 231 232
		case T_Sort:
			state = &(((Sort *) node)->sortstate->csstate);
			break;
233

234 235 236
		case T_Agg:
			state = &(((Agg *) node)->aggstate->csstate);
			break;
237

238 239 240
		default:
			elog(DEBUG, "ExecCloseR: not a scan, material, or sort node!");
			return;
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
	}

	relation = state->css_currentRelation;
	scanDesc = state->css_currentScanDesc;

	if (scanDesc != NULL)
		heap_endscan(scanDesc);

	if (relation != NULL)
		heap_close(relation);

	/* ----------------
	 *	if this is an index scan then we have to take care
	 *	of the index relations as well..
	 * ----------------
	 */
	if (nodeTag(node) == T_IndexScan)
	{
259
		IndexScan  *iscan = (IndexScan *) node;
260
		IndexScanState *indexstate;
261 262
		int			numIndices;
		RelationPtr indexRelationDescs;
263
		IndexScanDescPtr indexScanDescs;
264
		int			i;
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283

		indexstate = iscan->indxstate;
		numIndices = indexstate->iss_NumIndices;
		indexRelationDescs = indexstate->iss_RelationDescs;
		indexScanDescs = indexstate->iss_ScanDescs;

		for (i = 0; i < numIndices; i++)
		{
			/* ----------------
			 *	shut down each of the scans and
			 *	close each of the index relations
			 * ----------------
			 */
			if (indexScanDescs[i] != NULL)
				index_endscan(indexScanDescs[i]);

			if (indexRelationDescs[i] != NULL)
				index_close(indexRelationDescs[i]);
		}
284 285
	}
}
286

287
/* ----------------------------------------------------------------
288
 *		ExecReScan
289
 *
290
 *		XXX this should be extended to cope with all the node types..
291
 *
292 293 294
 *		takes the new expression context as an argument, so that
 *		index scans needn't have their scan keys updated separately
 *		- marcel 09/20/94
295 296 297
 * ----------------------------------------------------------------
 */
void
298
ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
299
{
V
Vadim B. Mikheev 已提交
300

301
	if (node->chgParam != NULL) /* Wow! */
V
Vadim B. Mikheev 已提交
302
	{
303 304 305
		List	   *lst;

		foreach(lst, node->initPlan)
V
Vadim B. Mikheev 已提交
306
		{
307 308 309 310 311 312 313
			Plan	   *splan = ((SubPlan *) lfirst(lst))->plan;

			if (splan->extParam != NULL)		/* don't care about child
												 * locParam */
				SetChangedParamList(splan, node->chgParam);
			if (splan->chgParam != NULL)
				ExecReScanSetParamPlan((SubPlan *) lfirst(lst), node);
V
Vadim B. Mikheev 已提交
314
		}
315
		foreach(lst, node->subPlan)
V
Vadim B. Mikheev 已提交
316
		{
317 318 319 320
			Plan	   *splan = ((SubPlan *) lfirst(lst))->plan;

			if (splan->extParam != NULL)
				SetChangedParamList(splan, node->chgParam);
V
Vadim B. Mikheev 已提交
321 322
		}
		/* Well. Now set chgParam for left/right trees. */
323 324 325 326
		if (node->lefttree != NULL)
			SetChangedParamList(node->lefttree, node->chgParam);
		if (node->righttree != NULL)
			SetChangedParamList(node->righttree, node->chgParam);
V
Vadim B. Mikheev 已提交
327 328
	}

329 330
	switch (nodeTag(node))
	{
V
Vadim B. Mikheev 已提交
331
		case T_SeqScan:
332
			ExecSeqReScan((SeqScan *) node, exprCtxt, parent);
V
Vadim B. Mikheev 已提交
333
			break;
334 335 336

		case T_IndexScan:
			ExecIndexReScan((IndexScan *) node, exprCtxt, parent);
V
Vadim B. Mikheev 已提交
337
			break;
338 339

		case T_Material:
340
			ExecMaterialReScan((Material *) node, exprCtxt, parent);
V
Vadim B. Mikheev 已提交
341
			break;
342

V
Vadim B. Mikheev 已提交
343
		case T_NestLoop:
344
			ExecReScanNestLoop((NestLoop *) node, exprCtxt, parent);
V
Vadim B. Mikheev 已提交
345 346 347
			break;

		case T_HashJoin:
348
			ExecReScanHashJoin((HashJoin *) node, exprCtxt, parent);
V
Vadim B. Mikheev 已提交
349 350 351
			break;

		case T_Hash:
352
			ExecReScanHash((Hash *) node, exprCtxt, parent);
V
Vadim B. Mikheev 已提交
353 354 355
			break;

		case T_Agg:
356
			ExecReScanAgg((Agg *) node, exprCtxt, parent);
V
Vadim B. Mikheev 已提交
357
			break;
358

B
Bruce Momjian 已提交
359 360 361 362
		case T_Group:
			ExecReScanGroup((Group *) node, exprCtxt, parent);
			break;

V
Vadim B. Mikheev 已提交
363
		case T_Result:
364
			ExecReScanResult((Result *) node, exprCtxt, parent);
V
Vadim B. Mikheev 已提交
365 366
			break;

367
		case T_Unique:
368
			ExecReScanUnique((Unique *) node, exprCtxt, parent);
369 370 371
			break;

		case T_Sort:
372
			ExecReScanSort((Sort *) node, exprCtxt, parent);
373 374
			break;

V
Vadim B. Mikheev 已提交
375 376 377 378
		case T_MergeJoin:
			ExecReScanMergeJoin((MergeJoin *) node, exprCtxt, parent);
			break;

379 380 381 382
		case T_Append:
			ExecReScanAppend((Append *) node, exprCtxt, parent);
			break;

383
		default:
V
Vadim B. Mikheev 已提交
384
			elog(ERROR, "ExecReScan: node type %u not supported", nodeTag(node));
385
			return;
386
	}
387 388

	if (node->chgParam != NULL)
V
Vadim B. Mikheev 已提交
389
	{
390
		freeList(node->chgParam);
V
Vadim B. Mikheev 已提交
391 392
		node->chgParam = NULL;
	}
393
}
394

395
/* ----------------------------------------------------------------
396
 *		ExecReScanR
397
 *
398
 *		XXX this does not do the right thing with indices yet.
399 400 401
 * ----------------------------------------------------------------
 */
HeapScanDesc
402
ExecReScanR(Relation relDesc,	/* LLL relDesc unused  */
403 404 405 406
			HeapScanDesc scanDesc,
			ScanDirection direction,
			int nkeys,			/* LLL nkeys unused  */
			ScanKey skeys)
407
{
408 409 410 411 412 413
	if (scanDesc != NULL)
		heap_rescan(scanDesc,	/* scan desc */
					ScanDirectionIsBackward(direction), /* backward flag */
					skeys);		/* scan keys */

	return scanDesc;
414
}
415

416
/* ----------------------------------------------------------------
417
 *		ExecMarkPos
418
 *
419
 *		Marks the current scan position.
420
 *
421
 *		XXX Needs to be extended to include all the node types.
422 423 424
 * ----------------------------------------------------------------
 */
void
425
ExecMarkPos(Plan *node)
426
{
427 428
	switch (nodeTag(node))
	{
429
			case T_SeqScan:
430 431
			ExecSeqMarkPos((SeqScan *) node);
			break;
432

433 434 435
		case T_IndexScan:
			ExecIndexMarkPos((IndexScan *) node);
			break;
436

437 438 439
		case T_Sort:
			ExecSortMarkPos((Sort *) node);
			break;
440

441
		default:
V
Vadim B. Mikheev 已提交
442
			elog(DEBUG, "ExecMarkPos: node type %u not supported", nodeTag(node));
443
			break;
444 445
	}
	return;
446
}
447

448
/* ----------------------------------------------------------------
449
 *		ExecRestrPos
450
 *
451
 *		restores the scan position previously saved with ExecMarkPos()
452 453 454
 * ----------------------------------------------------------------
 */
void
455
ExecRestrPos(Plan *node)
456
{
457 458
	switch (nodeTag(node))
	{
459
			case T_SeqScan:
460 461
			ExecSeqRestrPos((SeqScan *) node);
			return;
462

463 464 465
		case T_IndexScan:
			ExecIndexRestrPos((IndexScan *) node);
			return;
466

467 468 469
		case T_Sort:
			ExecSortRestrPos((Sort *) node);
			return;
470

471
		default:
V
Vadim B. Mikheev 已提交
472
			elog(DEBUG, "ExecRestrPos: node type %u not supported", nodeTag(node));
473
			return;
474
	}
475
}
476

477
/* ----------------------------------------------------------------
478
 *		ExecCreatR
479 480
 *
 * old comments
481
 *		Creates a relation.
482
 *
483 484 485 486 487
 *		Parameters:
 *		  attrType	-- type information on the attributes.
 *		  accessMtd -- access methods used to access the created relation.
 *		  relation	-- optional. Either an index to the range table or
 *					   negative number indicating a temporary relation.
B
Bruce Momjian 已提交
488
 *					   A temporary relation is assume if this field is absent.
489 490 491 492 493
 * ----------------------------------------------------------------
 */

Relation
ExecCreatR(TupleDesc tupType,
494
		   Oid relationOid)
495
{
496
	Relation	relDesc;
497

498
	EU3_printf("ExecCreatR: %s type=%d oid=%u\n",
499 500 501 502 503
			   "entering: ", tupType, relationOid);
	CXT1_printf("ExecCreatR: context is %d\n", CurrentMemoryContext);

	relDesc = NULL;

504
	if (relationOid == _NONAME_RELATION_ID_)
505 506 507
	{
		/* ----------------
		 *	 create a temporary relation
508
		 *	 (currently the planner always puts a _NONAME_RELATION_ID
509 510 511 512 513 514 515
		 *	 in the relation argument so we expect this to be the case although
		 *	 it's possible that someday we'll get the name from
		 *	 from the range table.. -cim 10/12/89)
		 * ----------------
		 */

		/*
516
		 * heap_create creates a name if the argument to heap_create is
517 518
		 * '\0 '
		 */
519
		relDesc = heap_create(NULL, tupType, true, false);
520
	}
521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536
	else
	{
		/* ----------------
		 *		use a relation from the range table
		 * ----------------
		 */
		elog(DEBUG, "ExecCreatR: %s",
			 "stuff using range table id's is not functional");
	}

	if (relDesc == NULL)
		elog(DEBUG, "ExecCreatR: failed to create relation.");

	EU1_printf("ExecCreatR: returning relDesc=%d\n", relDesc);

	return relDesc;
537
}