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 + -
显示快捷键?