fmgr.c
来自「PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统」· C语言 代码 · 共 1,918 行 · 第 1/4 页
C
1,918 行
HASH_FIND, NULL); if (entry == NULL) return NULL; /* no such entry */ if (entry->fn_xmin == HeapTupleHeaderGetXmin(procedureTuple->t_data) && entry->fn_cmin == HeapTupleHeaderGetCmin(procedureTuple->t_data)) return entry; /* OK */ return NULL; /* entry is out of date */}/* * record_C_func: enter (or update) info about a C function in the hash table */static voidrecord_C_func(HeapTuple procedureTuple, PGFunction user_fn, Pg_finfo_record *inforec){ Oid fn_oid = HeapTupleGetOid(procedureTuple); CFuncHashTabEntry *entry; bool found; /* Create the hash table if it doesn't exist yet */ if (CFuncHash == NULL) { HASHCTL hash_ctl; MemSet(&hash_ctl, 0, sizeof(hash_ctl)); hash_ctl.keysize = sizeof(Oid); hash_ctl.entrysize = sizeof(CFuncHashTabEntry); hash_ctl.hash = oid_hash; CFuncHash = hash_create("CFuncHash", 100, &hash_ctl, HASH_ELEM | HASH_FUNCTION); } entry = (CFuncHashTabEntry *) hash_search(CFuncHash, &fn_oid, HASH_ENTER, &found); /* OID is already filled in */ entry->fn_xmin = HeapTupleHeaderGetXmin(procedureTuple->t_data); entry->fn_cmin = HeapTupleHeaderGetCmin(procedureTuple->t_data); entry->user_fn = user_fn; entry->inforec = inforec;}/* * clear_external_function_hash: remove entries for a library being closed * * Presently we just zap the entire hash table, but later it might be worth * the effort to remove only the entries associated with the given handle. */voidclear_external_function_hash(void *filehandle){ if (CFuncHash) hash_destroy(CFuncHash); CFuncHash = NULL;}/* * Copy an FmgrInfo struct * * This is inherently somewhat bogus since we can't reliably duplicate * language-dependent subsidiary info. We cheat by zeroing fn_extra, * instead, meaning that subsidiary info will have to be recomputed. */voidfmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, MemoryContext destcxt){ memcpy(dstinfo, srcinfo, sizeof(FmgrInfo)); dstinfo->fn_mcxt = destcxt; if (dstinfo->fn_addr == fmgr_oldstyle) { /* For oldstyle functions we must copy fn_extra */ Oldstyle_fnextra *fnextra; fnextra = (Oldstyle_fnextra *) MemoryContextAlloc(destcxt, sizeof(Oldstyle_fnextra)); memcpy(fnextra, srcinfo->fn_extra, sizeof(Oldstyle_fnextra)); dstinfo->fn_extra = (void *) fnextra; } else dstinfo->fn_extra = NULL;}/* * Specialized lookup routine for fmgr_internal_validator: given the alleged * name of an internal function, return the OID of the function. * If the name is not recognized, return InvalidOid. */Oidfmgr_internal_function(const char *proname){ const FmgrBuiltin *fbp = fmgr_lookupByName(proname); if (fbp == NULL) return InvalidOid; return fbp->foid;}/* * Handler for old-style "C" language functions */static Datumfmgr_oldstyle(PG_FUNCTION_ARGS){ Oldstyle_fnextra *fnextra; int n_arguments = fcinfo->nargs; int i; bool isnull; func_ptr user_fn; char *returnValue; if (fcinfo->flinfo == NULL || fcinfo->flinfo->fn_extra == NULL) elog(ERROR, "fmgr_oldstyle received NULL pointer"); fnextra = (Oldstyle_fnextra *) fcinfo->flinfo->fn_extra; /* * Result is NULL if any argument is NULL, but we still call the function * (peculiar, but that's the way it worked before, and after all this is a * backwards-compatibility wrapper). Note, however, that we'll never get * here with NULL arguments if the function is marked strict. * * We also need to detoast any TOAST-ed inputs, since it's unlikely that * an old-style function knows about TOASTing. */ isnull = false; for (i = 0; i < n_arguments; i++) { if (PG_ARGISNULL(i)) isnull = true; else if (fnextra->arg_toastable[i]) fcinfo->arg[i] = PointerGetDatum(PG_DETOAST_DATUM(fcinfo->arg[i])); } fcinfo->isnull = isnull; user_fn = fnextra->func; switch (n_arguments) { case 0: returnValue = (*user_fn) (); break; case 1: /* * nullvalue() used to use isNull to check if arg is NULL; perhaps * there are other functions still out there that also rely on * this undocumented hack? */ returnValue = (*user_fn) (fcinfo->arg[0], &fcinfo->isnull); break; case 2: returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1]); break; case 3: returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1], fcinfo->arg[2]); break; case 4: returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1], fcinfo->arg[2], fcinfo->arg[3]); break; case 5: returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1], fcinfo->arg[2], fcinfo->arg[3], fcinfo->arg[4]); break; case 6: returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1], fcinfo->arg[2], fcinfo->arg[3], fcinfo->arg[4], fcinfo->arg[5]); break; case 7: returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1], fcinfo->arg[2], fcinfo->arg[3], fcinfo->arg[4], fcinfo->arg[5], fcinfo->arg[6]); break; case 8: returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1], fcinfo->arg[2], fcinfo->arg[3], fcinfo->arg[4], fcinfo->arg[5], fcinfo->arg[6], fcinfo->arg[7]); break; case 9: returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1], fcinfo->arg[2], fcinfo->arg[3], fcinfo->arg[4], fcinfo->arg[5], fcinfo->arg[6], fcinfo->arg[7], fcinfo->arg[8]); break; case 10: returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1], fcinfo->arg[2], fcinfo->arg[3], fcinfo->arg[4], fcinfo->arg[5], fcinfo->arg[6], fcinfo->arg[7], fcinfo->arg[8], fcinfo->arg[9]); break; case 11: returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1], fcinfo->arg[2], fcinfo->arg[3], fcinfo->arg[4], fcinfo->arg[5], fcinfo->arg[6], fcinfo->arg[7], fcinfo->arg[8], fcinfo->arg[9], fcinfo->arg[10]); break; case 12: returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1], fcinfo->arg[2], fcinfo->arg[3], fcinfo->arg[4], fcinfo->arg[5], fcinfo->arg[6], fcinfo->arg[7], fcinfo->arg[8], fcinfo->arg[9], fcinfo->arg[10], fcinfo->arg[11]); break; case 13: returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1], fcinfo->arg[2], fcinfo->arg[3], fcinfo->arg[4], fcinfo->arg[5], fcinfo->arg[6], fcinfo->arg[7], fcinfo->arg[8], fcinfo->arg[9], fcinfo->arg[10], fcinfo->arg[11], fcinfo->arg[12]); break; case 14: returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1], fcinfo->arg[2], fcinfo->arg[3], fcinfo->arg[4], fcinfo->arg[5], fcinfo->arg[6], fcinfo->arg[7], fcinfo->arg[8], fcinfo->arg[9], fcinfo->arg[10], fcinfo->arg[11], fcinfo->arg[12], fcinfo->arg[13]); break; case 15: returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1], fcinfo->arg[2], fcinfo->arg[3], fcinfo->arg[4], fcinfo->arg[5], fcinfo->arg[6], fcinfo->arg[7], fcinfo->arg[8], fcinfo->arg[9], fcinfo->arg[10], fcinfo->arg[11], fcinfo->arg[12], fcinfo->arg[13], fcinfo->arg[14]); break; case 16: returnValue = (*user_fn) (fcinfo->arg[0], fcinfo->arg[1], fcinfo->arg[2], fcinfo->arg[3], fcinfo->arg[4], fcinfo->arg[5], fcinfo->arg[6], fcinfo->arg[7], fcinfo->arg[8], fcinfo->arg[9], fcinfo->arg[10], fcinfo->arg[11], fcinfo->arg[12], fcinfo->arg[13], fcinfo->arg[14], fcinfo->arg[15]); break; default: /* * Increasing FUNC_MAX_ARGS doesn't automatically add cases to the * above code, so mention the actual value in this error not * FUNC_MAX_ARGS. You could add cases to the above if you needed * to support old-style functions with many arguments, but making * 'em be new-style is probably a better idea. */ ereport(ERROR, (errcode(ERRCODE_TOO_MANY_ARGUMENTS), errmsg("function %u has too many arguments (%d, maximum is %d)", fcinfo->flinfo->fn_oid, n_arguments, 16))); returnValue = NULL; /* keep compiler quiet */ break; } return (Datum) returnValue;}/* * Support for security definer functions */struct fmgr_security_definer_cache{ FmgrInfo flinfo; Oid userid;};/* * Function handler for security definer functions. We extract the * OID of the actual function and do a fmgr lookup again. Then we * look up the owner of the function and cache both the fmgr info and * the owner ID. During the call we temporarily replace the flinfo * with the cached/looked-up one, while keeping the outer fcinfo * (which contains all the actual arguments, etc.) intact. */static Datumfmgr_security_definer(PG_FUNCTION_ARGS){ Datum result; FmgrInfo *save_flinfo; struct fmgr_security_definer_cache *volatile fcache; Oid save_userid; HeapTuple tuple; if (!fcinfo->flinfo->fn_extra) { fcache = MemoryContextAllocZero(fcinfo->flinfo->fn_mcxt, sizeof(*fcache)); fmgr_info_cxt_security(fcinfo->flinfo->fn_oid, &fcache->flinfo, fcinfo->flinfo->fn_mcxt, true); tuple = SearchSysCache(PROCOID, ObjectIdGetDatum(fcinfo->flinfo->fn_oid), 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for function %u", fcinfo->flinfo->fn_oid); fcache->userid = ((Form_pg_proc) GETSTRUCT(tuple))->proowner; ReleaseSysCache(tuple); fcinfo->flinfo->fn_extra = fcache; } else fcache = fcinfo->flinfo->fn_extra; save_flinfo = fcinfo->flinfo; save_userid = GetUserId(); PG_TRY(); { fcinfo->flinfo = &fcache->flinfo; SetUserId(fcache->userid); result = FunctionCallInvoke(fcinfo); } PG_CATCH(); { fcinfo->flinfo = save_flinfo; SetUserId(save_userid); PG_RE_THROW(); } PG_END_TRY(); fcinfo->flinfo = save_flinfo; SetUserId(save_userid); return result;}/*------------------------------------------------------------------------- * Support routines for callers of fmgr-compatible functions *------------------------------------------------------------------------- *//* * These are for invocation of a specifically named function with a * directly-computed parameter list. Note that neither arguments nor result * are allowed to be NULL. Also, the function cannot be one that needs to * look at FmgrInfo, since there won't be any. */DatumDirectFunctionCall1(PGFunction func, Datum arg1){ FunctionCallInfoData fcinfo; Datum result; InitFunctionCallInfoData(fcinfo, NULL, 1, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.argnull[0] = false; result = (*func) (&fcinfo); /* Check for null result, since caller is clearly not expecting one */ if (fcinfo.isnull) elog(ERROR, "function %p returned NULL", (void *) func); return result;}DatumDirectFunctionCall2(PGFunction func, Datum arg1, Datum arg2){ FunctionCallInfoData fcinfo; Datum result; InitFunctionCallInfoData(fcinfo, NULL, 2, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; fcinfo.argnull[0] = false; fcinfo.argnull[1] = false; result = (*func) (&fcinfo); /* Check for null result, since caller is clearly not expecting one */ if (fcinfo.isnull) elog(ERROR, "function %p returned NULL", (void *) func); return result;}DatumDirectFunctionCall3(PGFunction func, Datum arg1, Datum arg2, Datum arg3){ FunctionCallInfoData fcinfo; Datum result; InitFunctionCallInfoData(fcinfo, NULL, 3, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; fcinfo.arg[2] = arg3; fcinfo.argnull[0] = false; fcinfo.argnull[1] = false; fcinfo.argnull[2] = false; result = (*func) (&fcinfo); /* Check for null result, since caller is clearly not expecting one */ if (fcinfo.isnull) elog(ERROR, "function %p returned NULL", (void *) func); return result;}DatumDirectFunctionCall4(PGFunction func, Datum arg1, Datum arg2, Datum arg3, Datum arg4){ FunctionCallInfoData fcinfo; Datum result; InitFunctionCallInfoData(fcinfo, NULL, 4, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; fcinfo.arg[2] = arg3; fcinfo.arg[3] = arg4; fcinfo.argnull[0] = false; fcinfo.argnull[1] = false; fcinfo.argnull[2] = false; fcinfo.argnull[3] = false; result = (*func) (&fcinfo); /* Check for null result, since caller is clearly not expecting one */ if (fcinfo.isnull) elog(ERROR, "function %p returned NULL", (void *) func); return result;}DatumDirectFunctionCall5(PGFunction func, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5){ FunctionCallInfoData fcinfo; Datum result; InitFunctionCallInfoData(fcinfo, NULL, 5, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; fcinfo.arg[2] = arg3; fcinfo.arg[3] = arg4; fcinfo.arg[4] = arg5; fcinfo.argnull[0] = false; fcinfo.argnull[1] = false; fcinfo.argnull[2] = false; fcinfo.argnull[3] = false; fcinfo.argnull[4] = false;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?