⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 execscan.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
字号:
/*------------------------------------------------------------------------- * * execScan.c *	  This code provides support for generalized relation scans. ExecScan *	  is passed a node and a pointer to a function to "do the right thing" *	  and return a tuple from the relation. ExecScan then does the tedious *	  stuff - checking the qualification and projecting the tuple *	  appropriately. * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/executor/execScan.c,v 1.37 2005/10/15 02:49:16 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "executor/executor.h"#include "miscadmin.h"#include "utils/memutils.h"static bool tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc);/* ---------------------------------------------------------------- *		ExecScan * *		Scans the relation using the 'access method' indicated and *		returns the next qualifying tuple in the direction specified *		in the global variable ExecDirection. *		The access method returns the next tuple and execScan() is *		responsible for checking the tuple returned against the qual-clause. * *		Conditions: *		  -- the "cursor" maintained by the AMI is positioned at the tuple *			 returned previously. * *		Initial States: *		  -- the relation indicated is opened for scanning so that the *			 "cursor" is positioned before the first qualifying tuple. * ---------------------------------------------------------------- */TupleTableSlot *ExecScan(ScanState *node,		 ExecScanAccessMtd accessMtd)	/* function returning a tuple */{	ExprContext *econtext;	List	   *qual;	ProjectionInfo *projInfo;	ExprDoneCond isDone;	TupleTableSlot *resultSlot;	/*	 * Fetch data from node	 */	qual = node->ps.qual;	projInfo = node->ps.ps_ProjInfo;	/*	 * If we have neither a qual to check nor a projection to do, just skip	 * all the overhead and return the raw scan tuple.	 */	if (!qual && !projInfo)		return (*accessMtd) (node);	/*	 * Check to see if we're still projecting out tuples from a previous scan	 * tuple (because there is a function-returning-set in the projection	 * expressions).  If so, try to project another one.	 */	if (node->ps.ps_TupFromTlist)	{		Assert(projInfo);		/* can't get here if not projecting */		resultSlot = ExecProject(projInfo, &isDone);		if (isDone == ExprMultipleResult)			return resultSlot;		/* Done with that source tuple... */		node->ps.ps_TupFromTlist = false;	}	/*	 * Reset per-tuple memory context to free any expression evaluation	 * storage allocated in the previous tuple cycle.  Note this can't happen	 * until we're done projecting out tuples from a scan tuple.	 */	econtext = node->ps.ps_ExprContext;	ResetExprContext(econtext);	/*	 * get a tuple from the access method loop until we obtain a tuple which	 * passes the qualification.	 */	for (;;)	{		TupleTableSlot *slot;		CHECK_FOR_INTERRUPTS();		slot = (*accessMtd) (node);		/*		 * if the slot returned by the accessMtd contains NULL, then it means		 * there is nothing more to scan so we just return an empty slot,		 * being careful to use the projection result slot so it has correct		 * tupleDesc.		 */		if (TupIsNull(slot))		{			if (projInfo)				return ExecClearTuple(projInfo->pi_slot);			else				return slot;		}		/*		 * place the current tuple into the expr context		 */		econtext->ecxt_scantuple = slot;		/*		 * check that the current tuple satisfies the qual-clause		 *		 * check for non-nil qual here to avoid a function call to ExecQual()		 * when the qual is nil ... saves only a few cycles, but they add up		 * ...		 */		if (!qual || ExecQual(qual, econtext, false))		{			/*			 * Found a satisfactory scan tuple.			 */			if (projInfo)			{				/*				 * Form a projection tuple, store it in the result tuple slot				 * and return it --- unless we find we can project no tuples				 * from this scan tuple, in which case continue scan.				 */				resultSlot = ExecProject(projInfo, &isDone);				if (isDone != ExprEndResult)				{					node->ps.ps_TupFromTlist = (isDone == ExprMultipleResult);					return resultSlot;				}			}			else			{				/*				 * Here, we aren't projecting, so just return scan tuple.				 */				return slot;			}		}		/*		 * Tuple fails qual, so free per-tuple memory and try again.		 */		ResetExprContext(econtext);	}}/* * ExecAssignScanProjectionInfo *		Set up projection info for a scan node, if necessary. * * We can avoid a projection step if the requested tlist exactly matches * the underlying tuple type.  If so, we just set ps_ProjInfo to NULL. * Note that this case occurs not only for simple "SELECT * FROM ...", but * also in most cases where there are joins or other processing nodes above * the scan node, because the planner will preferentially generate a matching * tlist. * * ExecAssignScanType must have been called already. */voidExecAssignScanProjectionInfo(ScanState *node){	Scan	   *scan = (Scan *) node->ps.plan;	if (tlist_matches_tupdesc(&node->ps,							  scan->plan.targetlist,							  scan->scanrelid,							  node->ss_ScanTupleSlot->tts_tupleDescriptor))		node->ps.ps_ProjInfo = NULL;	else		ExecAssignProjectionInfo(&node->ps);}static booltlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc){	int			numattrs = tupdesc->natts;	int			attrno;	bool		hasoid;	ListCell   *tlist_item = list_head(tlist);	/* Check the tlist attributes */	for (attrno = 1; attrno <= numattrs; attrno++)	{		Form_pg_attribute att_tup = tupdesc->attrs[attrno - 1];		Var		   *var;		if (tlist_item == NULL)			return false;		/* tlist too short */		var = (Var *) ((TargetEntry *) lfirst(tlist_item))->expr;		if (!var || !IsA(var, Var))			return false;		/* tlist item not a Var */		Assert(var->varno == varno);		Assert(var->varlevelsup == 0);		if (var->varattno != attrno)			return false;		/* out of order */		if (att_tup->attisdropped)			return false;		/* table contains dropped columns */		Assert(var->vartype == att_tup->atttypid);		Assert(var->vartypmod == att_tup->atttypmod);		tlist_item = lnext(tlist_item);	}	if (tlist_item)		return false;			/* tlist too long */	/*	 * If the plan context requires a particular hasoid setting, then that has	 * to match, too.	 */	if (ExecContextForcesOids(ps, &hasoid) &&		hasoid != tupdesc->tdhasoid)		return false;	return true;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -