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

📄 execqual.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
	 * original tuple).	 */	attnum = variable->varattno;	switch (variable->varno)	{		case INNER:				/* get the tuple from the inner node */			slot = econtext->ecxt_innertuple;			Assert(attnum > 0);			break;		case OUTER:				/* get the tuple from the outer node */			slot = econtext->ecxt_outertuple;			Assert(attnum > 0);			break;		default:				/* get the tuple from the relation being								 * scanned */			slot = econtext->ecxt_scantuple;			break;	}#ifdef USE_ASSERT_CHECKING	/*	 * Some checks that are only applied for user attribute numbers (bogus	 * system attnums will be caught inside slot_getattr).	 */	if (attnum > 0)	{		TupleDesc	tuple_type = slot->tts_tupleDescriptor;		/*		 * This assert checks that the attnum is valid.		 */		Assert(attnum <= tuple_type->natts);		/*		 * This assert checks that the datatype the plan expects to get (as		 * told by our "variable" argument) is in fact the datatype of the		 * attribute being fetched (as seen in the current context, identified		 * by our "econtext" argument).  Otherwise crashes are likely.		 *		 * Note that we can't check dropped columns, since their atttypid has		 * been zeroed.		 */		Assert(variable->vartype == tuple_type->attrs[attnum - 1]->atttypid ||			   tuple_type->attrs[attnum - 1]->attisdropped);	}#endif   /* USE_ASSERT_CHECKING */	return slot_getattr(slot, attnum, isNull);}/* ---------------------------------------------------------------- *		ExecEvalWholeRowVar * *		Returns a Datum for a whole-row variable. * *		This could be folded into ExecEvalVar, but we make it a separate *		routine so as not to slow down ExecEvalVar with tests for this *		uncommon case. * ---------------------------------------------------------------- */static DatumExecEvalWholeRowVar(ExprState *exprstate, ExprContext *econtext,					bool *isNull, ExprDoneCond *isDone){	Var		   *variable = (Var *) exprstate->expr;	TupleTableSlot *slot;	HeapTuple	tuple;	TupleDesc	tupleDesc;	HeapTupleHeader dtuple;	if (isDone)		*isDone = ExprSingleResult;	*isNull = false;	Assert(variable->varattno == InvalidAttrNumber);	/*	 * Whole-row Vars can only appear at the level of a relation scan, never	 * in a join.	 */	Assert(variable->varno != INNER);	Assert(variable->varno != OUTER);	slot = econtext->ecxt_scantuple;	tuple = ExecFetchSlotTuple(slot);	tupleDesc = slot->tts_tupleDescriptor;	/*	 * We have to make a copy of the tuple so we can safely insert the Datum	 * overhead fields, which are not set in on-disk tuples.	 */	dtuple = (HeapTupleHeader) palloc(tuple->t_len);	memcpy((char *) dtuple, (char *) tuple->t_data, tuple->t_len);	HeapTupleHeaderSetDatumLength(dtuple, tuple->t_len);	/*	 * If the Var identifies a named composite type, label the tuple with that	 * type; otherwise use what is in the tupleDesc.	 *	 * It's likely that the slot's tupleDesc is a record type; if so, make	 * sure it's been "blessed", so that the Datum can be interpreted later.	 */	if (variable->vartype != RECORDOID)	{		HeapTupleHeaderSetTypeId(dtuple, variable->vartype);		HeapTupleHeaderSetTypMod(dtuple, variable->vartypmod);	}	else	{		if (tupleDesc->tdtypeid == RECORDOID &&			tupleDesc->tdtypmod < 0)			assign_record_type_typmod(tupleDesc);		HeapTupleHeaderSetTypeId(dtuple, tupleDesc->tdtypeid);		HeapTupleHeaderSetTypMod(dtuple, tupleDesc->tdtypmod);	}	return PointerGetDatum(dtuple);}/* ---------------------------------------------------------------- *		ExecEvalConst * *		Returns the value of a constant. * *		Note that for pass-by-ref datatypes, we return a pointer to the *		actual constant node.  This is one of the reasons why functions *		must treat their input arguments as read-only. * ---------------------------------------------------------------- */static DatumExecEvalConst(ExprState *exprstate, ExprContext *econtext,			  bool *isNull, ExprDoneCond *isDone){	Const	   *con = (Const *) exprstate->expr;	if (isDone)		*isDone = ExprSingleResult;	*isNull = con->constisnull;	return con->constvalue;}/* ---------------------------------------------------------------- *		ExecEvalParam * *		Returns the value of a parameter.  A param node contains *		something like ($.name) and the expression context contains *		the current parameter bindings (name = "sam") (age = 34)... *		so our job is to find and return the appropriate datum ("sam"). * *		Q: if we have a parameter ($.foo) without a binding, i.e. *		   there is no (foo = xxx) in the parameter list info, *		   is this a fatal error or should this be a "not available" *		   (in which case we could return NULL)?	-cim 10/13/89 * ---------------------------------------------------------------- */static DatumExecEvalParam(ExprState *exprstate, ExprContext *econtext,			  bool *isNull, ExprDoneCond *isDone){	Param	   *expression = (Param *) exprstate->expr;	int			thisParamKind = expression->paramkind;	AttrNumber	thisParamId = expression->paramid;	if (isDone)		*isDone = ExprSingleResult;	if (thisParamKind == PARAM_EXEC)	{		/*		 * PARAM_EXEC params (internal executor parameters) are stored in the		 * ecxt_param_exec_vals array, and can be accessed by array index.		 */		ParamExecData *prm;		prm = &(econtext->ecxt_param_exec_vals[thisParamId]);		if (prm->execPlan != NULL)		{			/* Parameter not evaluated yet, so go do it */			ExecSetParamPlan(prm->execPlan, econtext);			/* ExecSetParamPlan should have processed this param... */			Assert(prm->execPlan == NULL);		}		*isNull = prm->isnull;		return prm->value;	}	else	{		/*		 * All other parameter types must be sought in ecxt_param_list_info.		 */		ParamListInfo paramInfo;		paramInfo = lookupParam(econtext->ecxt_param_list_info,								thisParamKind,								expression->paramname,								thisParamId,								false);		Assert(paramInfo->ptype == expression->paramtype);		*isNull = paramInfo->isnull;		return paramInfo->value;	}}/* ---------------------------------------------------------------- *		ExecEvalOper / ExecEvalFunc support routines * ---------------------------------------------------------------- *//* *		GetAttributeByName *		GetAttributeByNum * *		These functions return the value of the requested attribute *		out of the given tuple Datum. *		C functions which take a tuple as an argument are expected *		to use these.  Ex: overpaid(EMP) might call GetAttributeByNum(). *		Note: these are actually rather slow because they do a typcache *		lookup on each call. */DatumGetAttributeByNum(HeapTupleHeader tuple,				  AttrNumber attrno,				  bool *isNull){	Datum		result;	Oid			tupType;	int32		tupTypmod;	TupleDesc	tupDesc;	HeapTupleData tmptup;	if (!AttributeNumberIsValid(attrno))		elog(ERROR, "invalid attribute number %d", attrno);	if (isNull == NULL)		elog(ERROR, "a NULL isNull pointer was passed");	if (tuple == NULL)	{		/* Kinda bogus but compatible with old behavior... */		*isNull = true;		return (Datum) 0;	}	tupType = HeapTupleHeaderGetTypeId(tuple);	tupTypmod = HeapTupleHeaderGetTypMod(tuple);	tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);	/*	 * heap_getattr needs a HeapTuple not a bare HeapTupleHeader.  We set all	 * the fields in the struct just in case user tries to inspect system	 * columns.	 */	tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);	ItemPointerSetInvalid(&(tmptup.t_self));	tmptup.t_tableOid = InvalidOid;	tmptup.t_data = tuple;	result = heap_getattr(&tmptup,						  attrno,						  tupDesc,						  isNull);	return result;}DatumGetAttributeByName(HeapTupleHeader tuple, const char *attname, bool *isNull){	AttrNumber	attrno;	Datum		result;	Oid			tupType;	int32		tupTypmod;	TupleDesc	tupDesc;	HeapTupleData tmptup;	int			i;	if (attname == NULL)		elog(ERROR, "invalid attribute name");	if (isNull == NULL)		elog(ERROR, "a NULL isNull pointer was passed");	if (tuple == NULL)	{		/* Kinda bogus but compatible with old behavior... */		*isNull = true;		return (Datum) 0;	}	tupType = HeapTupleHeaderGetTypeId(tuple);	tupTypmod = HeapTupleHeaderGetTypMod(tuple);	tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);	attrno = InvalidAttrNumber;	for (i = 0; i < tupDesc->natts; i++)	{		if (namestrcmp(&(tupDesc->attrs[i]->attname), attname) == 0)		{			attrno = tupDesc->attrs[i]->attnum;			break;		}	}	if (attrno == InvalidAttrNumber)		elog(ERROR, "attribute \"%s\" does not exist", attname);	/*	 * heap_getattr needs a HeapTuple not a bare HeapTupleHeader.  We set all	 * the fields in the struct just in case user tries to inspect system	 * columns.	 */	tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);	ItemPointerSetInvalid(&(tmptup.t_self));	tmptup.t_tableOid = InvalidOid;	tmptup.t_data = tuple;	result = heap_getattr(&tmptup,						  attrno,						  tupDesc,						  isNull);	return result;}/* * init_fcache - initialize a FuncExprState node during first use */voidinit_fcache(Oid foid, FuncExprState *fcache, MemoryContext fcacheCxt){	AclResult	aclresult;	/* Check permission to call function */	aclresult = pg_proc_aclcheck(foid, GetUserId(), ACL_EXECUTE);	if (aclresult != ACLCHECK_OK)		aclcheck_error(aclresult, ACL_KIND_PROC, get_func_name(foid));	/*	 * Safety check on nargs.  Under normal circumstances this should never	 * fail, as parser should check sooner.  But possibly it might fail if	 * server has been compiled with FUNC_MAX_ARGS smaller than some functions	 * declared in pg_proc?	 */	if (list_length(fcache->args) > FUNC_MAX_ARGS)		ereport(ERROR,				(errcode(ERRCODE_TOO_MANY_ARGUMENTS),				 errmsg("cannot pass more than %d arguments to a function",						FUNC_MAX_ARGS)));	/* Set up the primary fmgr lookup information */	fmgr_info_cxt(foid, &(fcache->func), fcacheCxt);	/* Initialize additional info */	fcache->setArgsValid = false;	fcache->shutdown_reg = false;	fcache->func.fn_expr = (Node *) fcache->xprstate.expr;}/* * callback function in case a FuncExpr returning a set needs to be shut down * before it has been run to completion */static voidShutdownFuncExpr(Datum arg){	FuncExprState *fcache = (FuncExprState *) DatumGetPointer(arg);	/* Clear any active set-argument state */	fcache->setArgsValid = false;	/* execUtils will deregister the callback... */	fcache->shutdown_reg = false;}/* * Evaluate arguments for a function. */static ExprDoneCondExecEvalFuncArgs(FunctionCallInfo fcinfo,				 List *argList,				 ExprContext *econtext){	ExprDoneCond argIsDone;	int			i;	ListCell   *arg;	argIsDone = ExprSingleResult;		/* default assumption */	i = 0;	foreach(arg, argList)	{		ExprState  *argstate = (ExprState *) lfirst(arg);		ExprDoneCond thisArgIsDone;		fcinfo->arg[i] = ExecEvalExpr(argstate,									  econtext,									  &fcinfo->argnull[i],									  &thisArgIsDone);		if (thisArgIsDone != ExprSingleResult)		{			/*			 * We allow only one argument to have a set value; we'd need much			 * more complexity to keep track of multiple set arguments (cf.			 * ExecTargetList) and it doesn't seem worth it.			 */			if (argIsDone != ExprSingleResult)				ereport(ERROR,						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),						 errmsg("functions and operators can take at most one set argument")));			argIsDone = thisArgIsDone;		}		i++;	}	fcinfo->nargs = i;	return argIsDone;}/* *		ExecMakeFunctionResult * * Evaluate the arguments to a function and then the function itself. */DatumExecMakeFunctionResult(FuncExprState *fcache,					   ExprContext *econtext,					   bool *isNull,					   ExprDoneCond *isDone){	List	   *arguments = fcache->args;	Datum		result;	FunctionCallInfoData fcinfo;	ReturnSetInfo rsinfo;		/* for functions returning sets */	ExprDoneCond argDone;	bool		hasSetArg;	int			i;	/* Guard against stack overflow due to overly complex expressions */	check_stack_depth();	/*	 * arguments is a list of expressions to evaluate before passing to the	 * function manager.  We skip the evaluation if it was already done in the	 * previous call (ie, we are continuing the evaluation of a set-valued	 * function).  Otherwise, collect the current argument values into fcinfo.	 */	if (!fcache->setArgsValid)	{

⌨️ 快捷键说明

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