/* * op_volatile * * Get the provolatile flag for the operator's underlying function. */ char op_volatile(Oid opno) { RegProcedure funcid = get_opcode(opno); if (funcid == (RegProcedure) InvalidOid) elog(ERROR, "operator %u does not exist", opno); return func_volatile((Oid) funcid); }
/* * ValidateProtocolFunction -- common code for finding readfn, writefn or validatorfn */ static Oid ValidateProtocolFunction(List *fnName, ExtPtcFuncType fntype) { Oid fnOid; bool retset; bool retstrict; bool retordered; Oid *true_oid_array; Oid actual_rettype; Oid desired_rettype; FuncDetailCode fdresult; AclResult aclresult; Oid inputTypes[1] = {InvalidOid}; /* dummy */ int nargs = 0; /* true for all 3 function types at the moment */ int nvargs; if (fntype == EXTPTC_FUNC_VALIDATOR) desired_rettype = VOIDOID; else desired_rettype = INT4OID; /* * func_get_detail looks up the function in the catalogs, does * disambiguation for polymorphic functions, handles inheritance, and * returns the funcid and type and set or singleton status of the * function's return value. it also returns the true argument types to * the function. */ fdresult = func_get_detail(fnName, NIL, nargs, inputTypes, false, false, &fnOid, &actual_rettype, &retset, &retstrict, &retordered, &nvargs, &true_oid_array, NULL); /* only valid case is a normal function not returning a set */ if (fdresult != FUNCDETAIL_NORMAL || !OidIsValid(fnOid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("function %s does not exist", func_signature_string(fnName, nargs, inputTypes)))); if (retset) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("Invalid protocol function"), errdetail("Protocol functions cannot return sets."))); if (actual_rettype != desired_rettype) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("%s protocol function %s must return %s", func_type_to_name(fntype), func_signature_string(fnName, nargs, inputTypes), (fntype == EXTPTC_FUNC_VALIDATOR ? "void" : "an integer")))); if (func_volatile(fnOid) == PROVOLATILE_IMMUTABLE) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("%s protocol function %s is declared IMMUTABLE", func_type_to_name(fntype), func_signature_string(fnName, nargs, inputTypes)), errhint("PROTOCOL functions must be declared STABLE or VOLATILE"))); /* Check protocol creator has permission to call the function */ aclresult = pg_proc_aclcheck(fnOid, GetUserId(), ACL_EXECUTE); if (aclresult != ACLCHECK_OK) aclcheck_error(aclresult, ACL_KIND_PROC, get_func_name(fnOid)); return fnOid; }
/* * Checks if the results of a function can be cached. * Only IMMUTABLE functions can be cached. * * Returns true if function results can be cached, false otherwise. */ static bool isFuncCacheable(Oid fn_oid) { char fn_provolatile = func_volatile(fn_oid); return (fn_provolatile == PROVOLATILE_IMMUTABLE); }