+ Oid funcoid = PG_GETARG_OID(0);
+ HeapTuple tuple;
+ Form_pg_proc proc;
+ char functyptype;
+ int numargs;
+ Oid *argtypes;
+ char **argnames;
+ char *argmodes;
+ bool is_dml_trigger = false;
+ bool is_event_trigger = false;
+ int i;
+
+ /* Get the new function's pg_proc entry */
+ tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for function %u", funcoid);
+ proc = (Form_pg_proc) GETSTRUCT(tuple);
+
+ functyptype = get_typtype(proc->prorettype);
+
+ /* Disallow pseudotype result */
+ /* except for TRIGGER, RECORD, VOID, or polymorphic */
+ if (functyptype == TYPTYPE_PSEUDO)
+ {
+ /* we assume OPAQUE with no arguments means a trigger */
+ if (proc->prorettype == TRIGGEROID ||
+ (proc->prorettype == OPAQUEOID && proc->pronargs == 0))
+ is_dml_trigger = true;
+ else if (proc->prorettype == EVTTRIGGEROID)
+ is_event_trigger = true;
+ else if (proc->prorettype != RECORDOID &&
+ proc->prorettype != VOIDOID &&
+ !IsPolymorphicType(proc->prorettype))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("PL/pgSQL functions cannot return type %s",
+ format_type_be(proc->prorettype))));
+ }
+
+ /* Disallow pseudotypes in arguments (either IN or OUT) */
+ /* except for polymorphic */
+ numargs = get_func_arg_info(tuple,
+ &argtypes, &argnames, &argmodes);
+ for (i = 0; i < numargs; i++)
+ {
+ if (get_typtype(argtypes[i]) == TYPTYPE_PSEUDO)
+ {
+ if (!IsPolymorphicType(argtypes[i]))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("PL/pgSQL functions cannot accept type %s",
+ format_type_be(argtypes[i]))));
+ }
+ }
+
+ /* Postpone body checks if !check_function_bodies */
+ if (check_function_bodies)
+ {
+ FunctionCallInfoData fake_fcinfo;
+ FmgrInfo flinfo;
+ int rc;
+ TriggerData trigdata;
+ EventTriggerData etrigdata;