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

#include "postgres.h"

33 34
#include "executor/executor.h"
#include "storage/smgr.h"
35
#include "utils/mcxt.h"
36 37 38 39
#include "executor/nodeSeqscan.h"
#include "executor/nodeIndexscan.h"
#include "executor/nodeSort.h"
#include "executor/nodeTee.h"
M
Marc G. Fournier 已提交
40
#include "executor/execdebug.h"
41
#include "optimizer/internal.h" /* for _TEMP_RELATION_ID_ */
M
Marc G. Fournier 已提交
42 43 44
#include "access/genam.h"
#include "access/heapam.h"
#include "catalog/heap.h"
45

46 47
static Pointer
ExecBeginScan(Relation relation, int nkeys, ScanKey skeys,
48
			  bool isindex, ScanDirection dir);
49 50
static Relation ExecOpenR(Oid relationOid, bool isindex);

51
/* ----------------------------------------------------------------
52
 *		ExecOpenScanR
53 54
 *
 * old comments:
55 56 57 58 59 60 61 62 63 64
 *		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.
65 66 67 68
 * ----------------------------------------------------------------
 */
void
ExecOpenScanR(Oid relOid,
69 70 71 72
			  int nkeys,
			  ScanKey skeys,
			  bool isindex,
			  ScanDirection dir,
73 74
			  Relation *returnRelation, /* return */
			  Pointer *returnScanDesc)	/* return */
75
{
76 77
	Relation	relation;
	Pointer		scanDesc;
78 79 80 81 82 83 84 85 86 87 88 89 90

	/* ----------------
	 *	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,
91
							 dir);
92 93 94 95 96

	if (returnRelation != NULL)
		*returnRelation = relation;
	if (scanDesc != NULL)
		*returnScanDesc = scanDesc;
97
}
98

99
/* ----------------------------------------------------------------
100
 *		ExecOpenR
101
 *
102
 *		returns a relation descriptor given an object id.
103 104
 * ----------------------------------------------------------------
 */
105
static Relation
106 107
ExecOpenR(Oid relationOid, bool isindex)
{
108
	Relation	relation;
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127

	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;
128
}
129

130
/* ----------------------------------------------------------------
131
 *		ExecBeginScan
132
 *
133
 *		beginscans a relation in current direction.
134
 *
135 136 137 138 139
 *		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
140 141
 * ----------------------------------------------------------------
 */
142
static Pointer
143
ExecBeginScan(Relation relation,
144 145 146
			  int nkeys,
			  ScanKey skeys,
			  bool isindex,
147
			  ScanDirection dir)
148
{
149
	Pointer		scanDesc;
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171

	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),
172
											false,
173 174 175 176 177 178 179 180 181
											nkeys,
											skeys);
	}

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


	return scanDesc;
182
}
183

184
/* ----------------------------------------------------------------
185
 *		ExecCloseR
186
 *
187 188
 *		closes the relation and scan descriptor for a scan or sort
 *		node.  Also closes index relations and scans for index scans.
189 190
 *
 * old comments
191
 *		closes the relation indicated in 'relID'
192 193 194
 * ----------------------------------------------------------------
 */
void
195
ExecCloseR(Plan *node)
196
{
197
	CommonScanState *state;
198 199
	Relation	relation;
	HeapScanDesc scanDesc;
200 201 202 203 204 205 206 207

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

208 209 210
		case T_SeqScan:
			state = ((SeqScan *) node)->scanstate;
			break;
211

212 213 214
		case T_IndexScan:
			state = ((IndexScan *) node)->scan.scanstate;
			break;
215

216 217 218
		case T_Material:
			state = &(((Material *) node)->matstate->csstate);
			break;
219

220 221 222
		case T_Sort:
			state = &(((Sort *) node)->sortstate->csstate);
			break;
223

224 225 226
		case T_Agg:
			state = &(((Agg *) node)->aggstate->csstate);
			break;
227

228 229 230
		default:
			elog(DEBUG, "ExecCloseR: not a scan, material, or sort node!");
			return;
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
	}

	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)
	{
249
		IndexScan  *iscan = (IndexScan *) node;
250
		IndexScanState *indexstate;
251 252
		int			numIndices;
		RelationPtr indexRelationDescs;
253
		IndexScanDescPtr indexScanDescs;
254
		int			i;
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273

		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]);
		}
274 275
	}
}
276

277
/* ----------------------------------------------------------------
278
 *		ExecReScan
279
 *
280
 *		XXX this should be extended to cope with all the node types..
281
 *
282 283 284
 *		takes the new expression context as an argument, so that
 *		index scans needn't have their scan keys updated separately
 *		- marcel 09/20/94
285 286 287
 * ----------------------------------------------------------------
 */
void
288
ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
289
{
290 291
	switch (nodeTag(node))
	{
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
			case T_SeqScan:
			ExecSeqReScan((SeqScan *) node, exprCtxt, parent);
			return;

		case T_IndexScan:
			ExecIndexReScan((IndexScan *) node, exprCtxt, parent);
			return;

		case T_Material:

			/*
			 * the first call to ExecReScan should have no effect because
			 * everything is initialized properly already.	the following
			 * calls will be handled by ExecSeqReScan() because the nodes
			 * below the Material node have already been materialized into
			 * a temp relation.
			 */
			return;

		case T_Tee:
			ExecTeeReScan((Tee *) node, exprCtxt, parent);
			break;

		default:
			elog(WARN, "ExecReScan: not a seqscan or indexscan node.");
			return;
318
	}
319
}
320

321
/* ----------------------------------------------------------------
322
 *		ExecReScanR
323
 *
324
 *		XXX this does not do the right thing with indices yet.
325 326 327
 * ----------------------------------------------------------------
 */
HeapScanDesc
328
ExecReScanR(Relation relDesc,	/* LLL relDesc unused  */
329 330 331 332
			HeapScanDesc scanDesc,
			ScanDirection direction,
			int nkeys,			/* LLL nkeys unused  */
			ScanKey skeys)
333
{
334 335 336 337 338 339
	if (scanDesc != NULL)
		heap_rescan(scanDesc,	/* scan desc */
					ScanDirectionIsBackward(direction), /* backward flag */
					skeys);		/* scan keys */

	return scanDesc;
340
}
341

342
/* ----------------------------------------------------------------
343
 *		ExecMarkPos
344
 *
345
 *		Marks the current scan position.
346
 *
347
 *		XXX Needs to be extended to include all the node types.
348 349 350
 * ----------------------------------------------------------------
 */
void
351
ExecMarkPos(Plan *node)
352
{
353 354
	switch (nodeTag(node))
	{
355 356 357
			case T_SeqScan:
			ExecSeqMarkPos((SeqScan *) node);
			break;
358

359 360 361
		case T_IndexScan:
			ExecIndexMarkPos((IndexScan *) node);
			break;
362

363 364 365
		case T_Sort:
			ExecSortMarkPos((Sort *) node);
			break;
366

367 368 369
		default:
			/* elog(DEBUG, "ExecMarkPos: unsupported node type"); */
			break;
370 371
	}
	return;
372
}
373

374
/* ----------------------------------------------------------------
375
 *		ExecRestrPos
376
 *
377
 *		restores the scan position previously saved with ExecMarkPos()
378 379 380
 * ----------------------------------------------------------------
 */
void
381
ExecRestrPos(Plan *node)
382
{
383 384
	switch (nodeTag(node))
	{
385 386 387
			case T_SeqScan:
			ExecSeqRestrPos((SeqScan *) node);
			return;
388

389 390 391
		case T_IndexScan:
			ExecIndexRestrPos((IndexScan *) node);
			return;
392

393 394 395
		case T_Sort:
			ExecSortRestrPos((Sort *) node);
			return;
396

397 398 399
		default:
			/* elog(DEBUG, "ExecRestrPos: node type not supported"); */
			return;
400
	}
401
}
402

403
/* ----------------------------------------------------------------
404
 *		ExecCreatR
405 406
 *
 * old comments
407
 *		Creates a relation.
408
 *
409 410 411 412 413
 *		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 已提交
414
 *					   A temporary relation is assume if this field is absent.
415 416 417 418 419
 * ----------------------------------------------------------------
 */

Relation
ExecCreatR(TupleDesc tupType,
420
		   Oid relationOid)
421
{
422
	Relation	relDesc;
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439

	EU3_printf("ExecCreatR: %s type=%d oid=%d\n",
			   "entering: ", tupType, relationOid);
	CXT1_printf("ExecCreatR: context is %d\n", CurrentMemoryContext);

	relDesc = NULL;

	if (relationOid == _TEMP_RELATION_ID_)
	{
		/* ----------------
		 *	 create a temporary relation
		 *	 (currently the planner always puts a _TEMP_RELATION_ID
		 *	 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)
		 * ----------------
		 */
440
/*
441 442
		sprintf(tempname, "temp_%d.%d", getpid(), tmpcnt++);
		EU1_printf("ExecCreatR: attempting to create %s\n", tempname);
443
*/
444 445 446 447 448

		/*
		 * heap_creatr creates a name if the argument to heap_creatr is
		 * '\0 '
		 */
B
Bruce Momjian 已提交
449 450
		relDesc = heap_creatr("", tupType);
  	}
451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466
	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;
467
}