fmgr.c

来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 2,224 行 · 第 1/4 页

C
2,224
字号
	fcinfo.arg[0] = arg1;	fcinfo.arg[1] = arg2;	fcinfo.arg[2] = arg3;	fcinfo.arg[3] = arg4;	fcinfo.arg[4] = arg5;	fcinfo.arg[5] = arg6;	fcinfo.argnull[0] = false;	fcinfo.argnull[1] = false;	fcinfo.argnull[2] = false;	fcinfo.argnull[3] = false;	fcinfo.argnull[4] = false;	fcinfo.argnull[5] = false;	result = FunctionCallInvoke(&fcinfo);	/* Check for null result, since caller is clearly not expecting one */	if (fcinfo.isnull)		elog(ERROR, "function %u returned NULL", flinfo.fn_oid);	return result;}DatumOidFunctionCall7(Oid functionId, Datum arg1, Datum arg2,				 Datum arg3, Datum arg4, Datum arg5,				 Datum arg6, Datum arg7){	FmgrInfo	flinfo;	FunctionCallInfoData fcinfo;	Datum		result;	fmgr_info(functionId, &flinfo);	InitFunctionCallInfoData(fcinfo, &flinfo, 7, NULL, NULL);	fcinfo.arg[0] = arg1;	fcinfo.arg[1] = arg2;	fcinfo.arg[2] = arg3;	fcinfo.arg[3] = arg4;	fcinfo.arg[4] = arg5;	fcinfo.arg[5] = arg6;	fcinfo.arg[6] = arg7;	fcinfo.argnull[0] = false;	fcinfo.argnull[1] = false;	fcinfo.argnull[2] = false;	fcinfo.argnull[3] = false;	fcinfo.argnull[4] = false;	fcinfo.argnull[5] = false;	fcinfo.argnull[6] = false;	result = FunctionCallInvoke(&fcinfo);	/* Check for null result, since caller is clearly not expecting one */	if (fcinfo.isnull)		elog(ERROR, "function %u returned NULL", flinfo.fn_oid);	return result;}DatumOidFunctionCall8(Oid functionId, Datum arg1, Datum arg2,				 Datum arg3, Datum arg4, Datum arg5,				 Datum arg6, Datum arg7, Datum arg8){	FmgrInfo	flinfo;	FunctionCallInfoData fcinfo;	Datum		result;	fmgr_info(functionId, &flinfo);	InitFunctionCallInfoData(fcinfo, &flinfo, 8, NULL, NULL);	fcinfo.arg[0] = arg1;	fcinfo.arg[1] = arg2;	fcinfo.arg[2] = arg3;	fcinfo.arg[3] = arg4;	fcinfo.arg[4] = arg5;	fcinfo.arg[5] = arg6;	fcinfo.arg[6] = arg7;	fcinfo.arg[7] = arg8;	fcinfo.argnull[0] = false;	fcinfo.argnull[1] = false;	fcinfo.argnull[2] = false;	fcinfo.argnull[3] = false;	fcinfo.argnull[4] = false;	fcinfo.argnull[5] = false;	fcinfo.argnull[6] = false;	fcinfo.argnull[7] = false;	result = FunctionCallInvoke(&fcinfo);	/* Check for null result, since caller is clearly not expecting one */	if (fcinfo.isnull)		elog(ERROR, "function %u returned NULL", flinfo.fn_oid);	return result;}DatumOidFunctionCall9(Oid functionId, Datum arg1, Datum arg2,				 Datum arg3, Datum arg4, Datum arg5,				 Datum arg6, Datum arg7, Datum arg8,				 Datum arg9){	FmgrInfo	flinfo;	FunctionCallInfoData fcinfo;	Datum		result;	fmgr_info(functionId, &flinfo);	InitFunctionCallInfoData(fcinfo, &flinfo, 9, NULL, NULL);	fcinfo.arg[0] = arg1;	fcinfo.arg[1] = arg2;	fcinfo.arg[2] = arg3;	fcinfo.arg[3] = arg4;	fcinfo.arg[4] = arg5;	fcinfo.arg[5] = arg6;	fcinfo.arg[6] = arg7;	fcinfo.arg[7] = arg8;	fcinfo.arg[8] = arg9;	fcinfo.argnull[0] = false;	fcinfo.argnull[1] = false;	fcinfo.argnull[2] = false;	fcinfo.argnull[3] = false;	fcinfo.argnull[4] = false;	fcinfo.argnull[5] = false;	fcinfo.argnull[6] = false;	fcinfo.argnull[7] = false;	fcinfo.argnull[8] = false;	result = FunctionCallInvoke(&fcinfo);	/* Check for null result, since caller is clearly not expecting one */	if (fcinfo.isnull)		elog(ERROR, "function %u returned NULL", flinfo.fn_oid);	return result;}/* * Special cases for convenient invocation of datatype I/O functions. *//* * Call a previously-looked-up datatype input function. * * "str" may be NULL to indicate we are reading a NULL.  In this case * the caller should assume the result is NULL, but we'll call the input * function anyway if it's not strict.  So this is almost but not quite * the same as FunctionCall3. */DatumInputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod){	FunctionCallInfoData fcinfo;	Datum		result;	if (str == NULL && flinfo->fn_strict)		return (Datum) 0;		/* just return null result */	InitFunctionCallInfoData(fcinfo, flinfo, 3, NULL, NULL);	fcinfo.arg[0] = CStringGetDatum(str);	fcinfo.arg[1] = ObjectIdGetDatum(typioparam);	fcinfo.arg[2] = Int32GetDatum(typmod);	fcinfo.argnull[0] = (str == NULL);	fcinfo.argnull[1] = false;	fcinfo.argnull[2] = false;	result = FunctionCallInvoke(&fcinfo);	/* Should get null result if and only if str is NULL */	if (str == NULL)	{		if (!fcinfo.isnull)			elog(ERROR, "input function %u returned non-NULL",				 fcinfo.flinfo->fn_oid);	}	else	{		if (fcinfo.isnull)			elog(ERROR, "input function %u returned NULL",				 fcinfo.flinfo->fn_oid);	}	return result;}/* * Call a previously-looked-up datatype output function. * * Do not call this on NULL datums. * * This is mere window dressing for FunctionCall1, but its use is recommended * anyway so that code invoking output functions can be identified easily. */char *OutputFunctionCall(FmgrInfo *flinfo, Datum val){	return DatumGetCString(FunctionCall1(flinfo, val));}/* * Call a previously-looked-up datatype binary-input function. * * "buf" may be NULL to indicate we are reading a NULL.  In this case * the caller should assume the result is NULL, but we'll call the receive * function anyway if it's not strict.  So this is almost but not quite * the same as FunctionCall3. */DatumReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf,					Oid typioparam, int32 typmod){	FunctionCallInfoData fcinfo;	Datum		result;	if (buf == NULL && flinfo->fn_strict)		return (Datum) 0;		/* just return null result */	InitFunctionCallInfoData(fcinfo, flinfo, 3, NULL, NULL);	fcinfo.arg[0] = PointerGetDatum(buf);	fcinfo.arg[1] = ObjectIdGetDatum(typioparam);	fcinfo.arg[2] = Int32GetDatum(typmod);	fcinfo.argnull[0] = (buf == NULL);	fcinfo.argnull[1] = false;	fcinfo.argnull[2] = false;	result = FunctionCallInvoke(&fcinfo);	/* Should get null result if and only if buf is NULL */	if (buf == NULL)	{		if (!fcinfo.isnull)			elog(ERROR, "receive function %u returned non-NULL",				 fcinfo.flinfo->fn_oid);	}	else	{		if (fcinfo.isnull)			elog(ERROR, "receive function %u returned NULL",				 fcinfo.flinfo->fn_oid);	}	return result;}/* * Call a previously-looked-up datatype binary-output function. * * Do not call this on NULL datums. * * This is little more than window dressing for FunctionCall1, but its use is * recommended anyway so that code invoking output functions can be identified * easily.	Note however that it does guarantee a non-toasted result. */bytea *SendFunctionCall(FmgrInfo *flinfo, Datum val){	return DatumGetByteaP(FunctionCall1(flinfo, val));}/* * As above, for I/O functions identified by OID.  These are only to be used * in seldom-executed code paths.  They are not only slow but leak memory. */DatumOidInputFunctionCall(Oid functionId, char *str, Oid typioparam, int32 typmod){	FmgrInfo	flinfo;	fmgr_info(functionId, &flinfo);	return InputFunctionCall(&flinfo, str, typioparam, typmod);}char *OidOutputFunctionCall(Oid functionId, Datum val){	FmgrInfo	flinfo;	fmgr_info(functionId, &flinfo);	return OutputFunctionCall(&flinfo, val);}DatumOidReceiveFunctionCall(Oid functionId, StringInfo buf,					   Oid typioparam, int32 typmod){	FmgrInfo	flinfo;	fmgr_info(functionId, &flinfo);	return ReceiveFunctionCall(&flinfo, buf, typioparam, typmod);}bytea *OidSendFunctionCall(Oid functionId, Datum val){	FmgrInfo	flinfo;	fmgr_info(functionId, &flinfo);	return SendFunctionCall(&flinfo, val);}/* * !!! OLD INTERFACE !!! * * fmgr() is the only remaining vestige of the old-style caller support * functions.  It's no longer used anywhere in the Postgres distribution, * but we should leave it around for a release or two to ease the transition * for user-supplied C functions.  OidFunctionCallN() replaces it for new * code. * * DEPRECATED, DO NOT USE IN NEW CODE */char *fmgr(Oid procedureId,...){	FmgrInfo	flinfo;	FunctionCallInfoData fcinfo;	int			n_arguments;	Datum		result;	fmgr_info(procedureId, &flinfo);	MemSet(&fcinfo, 0, sizeof(fcinfo));	fcinfo.flinfo = &flinfo;	fcinfo.nargs = flinfo.fn_nargs;	n_arguments = fcinfo.nargs;	if (n_arguments > 0)	{		va_list		pvar;		int			i;		if (n_arguments > FUNC_MAX_ARGS)			ereport(ERROR,					(errcode(ERRCODE_TOO_MANY_ARGUMENTS),			 errmsg("function %u has too many arguments (%d, maximum is %d)",					flinfo.fn_oid, n_arguments, FUNC_MAX_ARGS)));		va_start(pvar, procedureId);		for (i = 0; i < n_arguments; i++)			fcinfo.arg[i] = (Datum) va_arg(pvar, char *);		va_end(pvar);	}	result = FunctionCallInvoke(&fcinfo);	/* Check for null result, since caller is clearly not expecting one */	if (fcinfo.isnull)		elog(ERROR, "function %u returned NULL", flinfo.fn_oid);	return (char *) result;}/*------------------------------------------------------------------------- *		Support routines for standard pass-by-reference datatypes * * Note: at some point, at least on some platforms, these might become * pass-by-value types.  Obviously Datum must be >= 8 bytes to allow * int64 or float8 to be pass-by-value.  I think that Float4GetDatum * and Float8GetDatum will need to be out-of-line routines anyway, * since just casting from float to Datum will not do the right thing; * some kind of trick with pointer-casting or a union will be needed. *------------------------------------------------------------------------- */DatumInt64GetDatum(int64 X){#ifndef INT64_IS_BUSTED	int64	   *retval = (int64 *) palloc(sizeof(int64));	*retval = X;	return PointerGetDatum(retval);#else							/* INT64_IS_BUSTED */	/*	 * On a machine with no 64-bit-int C datatype, sizeof(int64) will not be	 * 8, but we want Int64GetDatum to return an 8-byte object anyway, with	 * zeroes in the unused bits.  This is needed so that, for example, hash	 * join of int8 will behave properly.	 */	int64	   *retval = (int64 *) palloc0(Max(sizeof(int64), 8));	*retval = X;	return PointerGetDatum(retval);#endif   /* INT64_IS_BUSTED */}DatumFloat4GetDatum(float4 X){	float4	   *retval = (float4 *) palloc(sizeof(float4));	*retval = X;	return PointerGetDatum(retval);}DatumFloat8GetDatum(float8 X){	float8	   *retval = (float8 *) palloc(sizeof(float8));	*retval = X;	return PointerGetDatum(retval);}/*------------------------------------------------------------------------- *		Support routines for toastable datatypes *------------------------------------------------------------------------- */struct varlena *pg_detoast_datum(struct varlena * datum){	if (VARATT_IS_EXTENDED(datum))		return heap_tuple_untoast_attr(datum);	else		return datum;}struct varlena *pg_detoast_datum_copy(struct varlena * datum){	if (VARATT_IS_EXTENDED(datum))		return heap_tuple_untoast_attr(datum);	else	{		/* Make a modifiable copy of the varlena object */		Size		len = VARSIZE(datum);		struct varlena *result = (struct varlena *) palloc(len);		memcpy(result, datum, len);		return result;	}}struct varlena *pg_detoast_datum_slice(struct varlena * datum, int32 first, int32 count){	/* Only get the specified portion from the toast rel */	return heap_tuple_untoast_attr_slice(datum, first, count);}struct varlena *pg_detoast_datum_packed(struct varlena * datum){	if (VARATT_IS_COMPRESSED(datum) || VARATT_IS_EXTERNAL(datum))		return heap_tuple_untoast_attr(datum);	else		return datum;}/*------------------------------------------------------------------------- *		Support routines for extracting info from fn_expr parse tree * * These are needed by polymorphic functions, which accept multiple possible * input types and need help from the parser to know what they've got. *------------------------------------------------------------------------- *//* * Get the actual type OID of the function return type * * Returns InvalidOid if information is not available */Oidget_fn_expr_rettype(FmgrInfo *flinfo){	Node	   *expr;	/*	 * can't return anything useful if we have no FmgrInfo or if its fn_expr	 * node has not been initialized	 */	if (!flinfo || !flinfo->fn_expr)		return InvalidOid;	expr = flinfo->fn_expr;	return exprType(expr);}/* * Get the actual type OID of a specific function argument (counting from 0) * * Returns InvalidOid if information is not available */Oidget_fn_expr_argtype(FmgrInfo *flinfo, int argnum){	/*	 * can't return anything useful if we have no FmgrInfo or if its fn_expr	 * node has not been initialized	 */	if (!flinfo || !flinfo->fn_expr)		return InvalidOid;	return get_call_expr_argtype(flinfo->fn_expr, argnum);}/* * Get the actual type OID of a specific function argument (counting from 0), * but working from the calling expression tree instead of FmgrInfo * * Returns InvalidOid if information is not available */Oidget_call_expr_argtype(Node *expr, int argnum){	List	   *args;	Oid			argtype;	if (expr == NULL)		return InvalidOid;	if (IsA(expr, FuncExpr))		args = ((FuncExpr *) expr)->args;	else if (IsA(expr, OpExpr))		args = ((OpExpr *) expr)->args;	else if (IsA(expr, DistinctExpr))		args = ((DistinctExpr *) expr)->args;	else if (IsA(expr, ScalarArrayOpExpr))		args = ((ScalarArrayOpExpr *) expr)->args;	else if (IsA(expr, ArrayCoerceExpr))		args = list_make1(((ArrayCoerceExpr *) expr)->arg);	else if (IsA(expr, NullIfExpr))		args = ((NullIfExpr *) expr)->args;	else		return InvalidOid;	if (argnum < 0 || argnum >= list_length(args))		return InvalidOid;	argtype = exprType((Node *) list_nth(args, argnum));	/*	 * special hack for ScalarArrayOpExpr and ArrayCoerceExpr: what the	 * underlying function will actually get passed is the element type of the	 * array.	 */	if (IsA(expr, ScalarArrayOpExpr) &&		argnum == 1)		argtype = get_element_type(argtype);	else if (IsA(expr, ArrayCoerceExpr) &&			 argnum == 0)		argtype = get_element_type(argtype);	return argtype;}

⌨️ 快捷键说明

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