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

📄 nodeindexscan.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 2 页
字号:
 * old comments *		Creates the run-time state information for the node and *		sets the relation id to contain relevant decriptors. * *		Parameters: *		  node: IndexNode node produced by the planner. *		  estate: the execution state initialized in InitPlan. * ---------------------------------------------------------------- */boolExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent){	IndexScanState *indexstate;	CommonScanState *scanstate;	List	   *indxqual;	List	   *indxid;	int			i;	int			numIndices;	int			indexPtr;	ScanKey    *scanKeys;	int		   *numScanKeys;	RelationPtr relationDescs;	IndexScanDescPtr scanDescs;	Pointer    *runtimeKeyInfo;	bool		have_runtime_keys;	List	   *rangeTable;	RangeTblEntry *rtentry;	Index		relid;	Oid			reloid;	Relation	currentRelation;	HeapScanDesc currentScanDesc;	ScanDirection direction;	int			baseid;	List	   *execParam = NULL;	/* ----------------	 *	assign execution state to node	 * ----------------	 */	node->scan.plan.state = estate;	/* --------------------------------	 *	Part 1)  initialize scan state	 *	 *	create new CommonScanState for node	 * --------------------------------	 */	scanstate = makeNode(CommonScanState);/*	scanstate->ss_ProcOuterFlag = false;	scanstate->ss_OldRelId = 0;*/	node->scan.scanstate = scanstate;	/* ----------------	 *	assign node's base_id .. we don't use AssignNodeBaseid() because	 *	the increment is done later on after we assign the index scan's	 *	scanstate.	see below.	 * ----------------	 */	baseid = estate->es_BaseId;/*	  scanstate->csstate.cstate.bnode.base_id = baseid; */	scanstate->cstate.cs_base_id = baseid;	/* ----------------	 *	create expression context for node	 * ----------------	 */	ExecAssignExprContext(estate, &scanstate->cstate);#define INDEXSCAN_NSLOTS 3	/* ----------------	 *	tuple table initialization	 * ----------------	 */	ExecInitResultTupleSlot(estate, &scanstate->cstate);	ExecInitScanTupleSlot(estate, scanstate);/*	  ExecInitRawTupleSlot(estate, scanstate); */	/* ----------------	 *	initialize projection info.  result type comes from scan desc	 *	below..	 * ----------------	 */	ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate);	/* --------------------------------	  *  Part 2)  initialize index scan state	  *	  *  create new IndexScanState for node	  * --------------------------------	  */	indexstate = makeNode(IndexScanState);	indexstate->iss_NumIndices = 0;	indexstate->iss_IndexPtr = -1;	indexstate->iss_ScanKeys = NULL;	indexstate->iss_NumScanKeys = NULL;	indexstate->iss_RuntimeKeyInfo = NULL;	indexstate->iss_RelationDescs = NULL;	indexstate->iss_ScanDescs = NULL;	node->indxstate = indexstate;	/* ----------------	 *	assign base id to index scan state also	 * ----------------	 */	indexstate->cstate.cs_base_id = baseid;	baseid++;	estate->es_BaseId = baseid;	/* ----------------	 *	get the index node information	 * ----------------	 */	indxid = node->indxid;	indxqual = node->indxqual;	numIndices = length(indxid);	indexPtr = -1;	CXT1_printf("ExecInitIndexScan: context is %d\n", CurrentMemoryContext);	/* ----------------	 *	scanKeys is used to keep track of the ScanKey's. This is needed	 *	because a single scan may use several indices and each index has	 *	its own ScanKey.	 * ----------------	 */	numScanKeys = (int *) palloc(numIndices * sizeof(int));	scanKeys = (ScanKey *) palloc(numIndices * sizeof(ScanKey));	relationDescs = (RelationPtr) palloc(numIndices * sizeof(Relation));	scanDescs = (IndexScanDescPtr) palloc(numIndices * sizeof(IndexScanDesc));	/* ----------------	 *	initialize runtime key info.	 * ----------------	 */	have_runtime_keys = false;	runtimeKeyInfo = (Pointer *)		palloc(numIndices * sizeof(Pointer));	/* ----------------	 *	build the index scan keys from the index qualification	 * ----------------	 */	for (i = 0; i < numIndices; i++)	{		int			j;		List	   *qual;		int			n_keys;		ScanKey		scan_keys;		int		   *run_keys;		qual = nth(i, indxqual);		n_keys = length(qual);		scan_keys = (n_keys <= 0) ? NULL :			(ScanKey) palloc(n_keys * sizeof(ScanKeyData));		run_keys = (n_keys <= 0) ? NULL :			(int *) palloc(n_keys * sizeof(int));		CXT1_printf("ExecInitIndexScan: context is %d\n", CurrentMemoryContext);		/* ----------------		 *	for each opclause in the given qual,		 *	convert each qual's opclause into a single scan key		 * ----------------		 */		for (j = 0; j < n_keys; j++)		{			Expr	   *clause; /* one part of index qual */			Oper	   *op;		/* operator used in scan.. */			Node	   *leftop; /* expr on lhs of operator */			Node	   *rightop;/* expr on rhs ... */			bits16		flags = 0;			int			scanvar;/* which var identifies varattno */			AttrNumber	varattno = 0;	/* att number used in scan */			Oid			opid;	/* operator id used in scan */			Datum		scanvalue = 0;	/* value used in scan (if const) */			/* ----------------			 *	extract clause information from the qualification			 * ----------------			 */			clause = nth(j, qual);			op = (Oper *) clause->oper;			if (!IsA(op, Oper))				elog(ERROR, "ExecInitIndexScan: op not an Oper!");			opid = op->opid;			/* ----------------			 *	Here we figure out the contents of the index qual.			 *	The usual case is (op var const) or (op const var)			 *	which means we form a scan key for the attribute			 *	listed in the var node and use the value of the const.			 *			 *	If we don't have a const node, then it means that			 *	one of the var nodes refers to the "scan" tuple and			 *	is used to determine which attribute to scan, and the			 *	other expression is used to calculate the value used in			 *	scanning the index.			 *			 *	This means our index scan's scan key is a function of			 *	information obtained during the execution of the plan			 *	in which case we need to recalculate the index scan key			 *	at run time.			 *			 *	Hence, we set have_runtime_keys to true and then set			 *	the appropriate flag in run_keys to LEFT_OP or RIGHT_OP.			 *	The corresponding scan keys are recomputed at run time.			 * ----------------			 */			scanvar = NO_OP;			/* ----------------			 *	determine information in leftop			 * ----------------			 */			leftop = (Node *) get_leftop(clause);			if (IsA(leftop, Var) &&var_is_rel((Var *) leftop))			{				/* ----------------				 *	if the leftop is a "rel-var", then it means				 *	that it is a var node which tells us which				 *	attribute to use for our scan key.				 * ----------------				 */				varattno = ((Var *) leftop)->varattno;				scanvar = LEFT_OP;			}			else if (IsA(leftop, Const))			{				/* ----------------				 *	if the leftop is a const node then it means				 *	it identifies the value to place in our scan key.				 * ----------------				 */				run_keys[j] = NO_OP;				scanvalue = ((Const *) leftop)->constvalue;			}			else if (IsA(leftop, Param))			{				bool		isnull;				/* ----------------				 *	if the leftop is a Param node then it means				 *	it identifies the value to place in our scan key.				 * ----------------				 */				/* Life was so easy before ... subselects */				if (((Param *) leftop)->paramkind == PARAM_EXEC)				{					have_runtime_keys = true;					run_keys[j] = LEFT_OP;					execParam = lappendi(execParam, ((Param *) leftop)->paramid);				}				else				{					scanvalue = ExecEvalParam((Param *) leftop,										scanstate->cstate.cs_ExprContext,											  &isnull);					if (isnull)						flags |= SK_ISNULL;					run_keys[j] = NO_OP;				}			}			else if (leftop != NULL &&					 is_funcclause(leftop) &&					 var_is_rel(lfirst(((Expr *) leftop)->args)))			{				/* ----------------				 *	if the leftop is a func node then it means				 *	it identifies the value to place in our scan key.				 *	Since functional indices have only one attribute				 *	the attno must always be set to 1.				 * ----------------				 */				varattno = 1;				scanvar = LEFT_OP;			}			else			{				/* ----------------				 *	otherwise, the leftop contains information usable				 *	at runtime to figure out the value to place in our				 *	scan key.				 * ----------------				 */				have_runtime_keys = true;				run_keys[j] = LEFT_OP;				scanvalue = Int32GetDatum((int32) true);			}			/* ----------------			 *	now determine information in rightop			 * ----------------			 */			rightop = (Node *) get_rightop(clause);			if (IsA(rightop, Var) &&var_is_rel((Var *) rightop))			{				/* ----------------				 *	here we make sure only one op identifies the				 *	scan-attribute...				 * ----------------				 */				if (scanvar == LEFT_OP)					elog(ERROR, "ExecInitIndexScan: %s",						 "both left and right op's are rel-vars");				/* ----------------				 *	if the rightop is a "rel-var", then it means				 *	that it is a var node which tells us which				 *	attribute to use for our scan key.				 * ----------------				 */				varattno = ((Var *) rightop)->varattno;				scanvar = RIGHT_OP;			}			else if (IsA(rightop, Const))			{				/* ----------------				 *	if the leftop is a const node then it means				 *	it identifies the value to place in our scan key.				 * ----------------				 */				run_keys[j] = NO_OP;				scanvalue = ((Const *) rightop)->constvalue;			}			else if (IsA(rightop, Param))			{				bool		isnull;				/* ----------------				 *	if the rightop is a Param node then it means				 *	it identifies the value to place in our scan key.				 * ----------------				 */				/* Life was so easy before ... subselects */				if (((Param *) rightop)->paramkind == PARAM_EXEC)				{					have_runtime_keys = true;					run_keys[j] = RIGHT_OP;					execParam = lappendi(execParam, ((Param *) rightop)->paramid);				}				else				{					scanvalue = ExecEvalParam((Param *) rightop,										scanstate->cstate.cs_ExprContext,											  &isnull);					if (isnull)						flags |= SK_ISNULL;					run_keys[j] = NO_OP;				}			}			else if (rightop != NULL &&					 is_funcclause(rightop) &&					 var_is_rel(lfirst(((Expr *) rightop)->args)))			{				/* ----------------				 *	if the rightop is a func node then it means				 *	it identifies the value to place in our scan key.				 *	Since functional indices have only one attribute				 *	the attno must always be set to 1.				 * ----------------				 */				if (scanvar == LEFT_OP)					elog(ERROR, "ExecInitIndexScan: %s",						 "both left and right ops are rel-vars");				varattno = 1;				scanvar = RIGHT_OP;			}			else			{				/* ----------------				 *	otherwise, the leftop contains information usable				 *	at runtime to figure out the value to place in our				 *	scan key.				 * ----------------				 */				have_runtime_keys = true;				run_keys[j] = RIGHT_OP;				scanvalue = Int32GetDatum((int32) true);			}			/* ----------------			 *	now check that at least one op tells us the scan			 *	attribute...			 * ----------------			 */			if (scanvar == NO_OP)				elog(ERROR, "ExecInitIndexScan: %s",					 "neither leftop nor rightop refer to scan relation");			/* ----------------			 *	initialize the scan key's fields appropriately			 * ----------------			 */			ScanKeyEntryInitialize(&scan_keys[j],								   flags,								   varattno,	/* attribute number to												 * scan */								   (RegProcedure) opid, /* reg proc to use */								   (Datum) scanvalue);	/* constant */		}		/* ----------------		 *	store the key information into our array.		 * ----------------		 */		numScanKeys[i] = n_keys;		scanKeys[i] = scan_keys;		runtimeKeyInfo[i] = (Pointer) run_keys;	}	indexstate->iss_NumIndices = numIndices;	indexstate->iss_IndexPtr = indexPtr;	indexstate->iss_ScanKeys = scanKeys;	indexstate->iss_NumScanKeys = numScanKeys;	/* ----------------	 *	If all of our keys have the form (op var const) , then we have no	 *	runtime keys so we store NULL in the runtime key info.	 *	Otherwise runtime key info contains an array of pointers	 *	(one for each index) to arrays of flags (one for each key)	 *	which indicate that the qual needs to be evaluated at runtime.	 *	-cim 10/24/89	 * ----------------	 */	if (have_runtime_keys)		indexstate->iss_RuntimeKeyInfo = (Pointer) runtimeKeyInfo;	else		indexstate->iss_RuntimeKeyInfo = NULL;	/* ----------------	 *	get the range table and direction information	 *	from the execution state (these are needed to	 *	open the relations).	 * ----------------	 */	rangeTable = estate->es_range_table;	direction = estate->es_direction;	/* ----------------	 *	open the base relation	 * ----------------	 */	relid = node->scan.scanrelid;	rtentry = rt_fetch(relid, rangeTable);	reloid = rtentry->relid;	ExecOpenScanR(reloid,		/* relation */				  0,			/* nkeys */				  (ScanKey) NULL,		/* scan key */				  0,			/* is index */				  direction,	/* scan direction */				  estate->es_snapshot,	/* */				  &currentRelation,		/* return: rel desc */				  (Pointer *) &currentScanDesc);		/* return: scan desc */	scanstate->css_currentRelation = currentRelation;	scanstate->css_currentScanDesc = currentScanDesc;	/* ----------------	 *	get the scan type from the relation descriptor.	 * ----------------	 */	ExecAssignScanType(scanstate, RelationGetDescr(currentRelation));	ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate);	/* ----------------	 *	index scans don't have subtrees..	 * ----------------	 *//*	  scanstate->ss_ProcOuterFlag = false; */	/* ----------------	 *	open the index relations and initialize	 *	relation and scan descriptors.	 * ----------------	 */	for (i = 0; i < numIndices; i++)	{		Oid			indexOid;		indexOid = (Oid) nthi(i, indxid);		if (indexOid != 0)		{			ExecOpenScanR(indexOid,		/* relation */						  numScanKeys[i],		/* nkeys */						  scanKeys[i],	/* scan key */						  true, /* is index */						  direction,	/* scan direction */						  estate->es_snapshot,						  &(relationDescs[i]),	/* return: rel desc */						  (Pointer *) &(scanDescs[i]));			/* return: scan desc */		}	}	indexstate->iss_RelationDescs = relationDescs;	indexstate->iss_ScanDescs = scanDescs;	indexstate->cstate.cs_TupFromTlist = false;	/*	 * if there are some PARAM_EXEC in skankeys then force index rescan on	 * first scan.	 */	((Plan *) node)->chgParam = execParam;	/* ----------------	 *	all done.	 * ----------------	 */	return TRUE;}intExecCountSlotsIndexScan(IndexScan *node){	return ExecCountSlotsNode(outerPlan((Plan *) node)) +	ExecCountSlotsNode(innerPlan((Plan *) node)) + INDEXSCAN_NSLOTS;}

⌨️ 快捷键说明

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