parameterCount = parameterTypes->dim1; if (parameterCount < 0 || parameterCount > FUNC_MAX_ARGS)
ereport(ERROR,
(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
errmsg_plural("functions cannot have more than %d argument", "functions cannot have more than %d arguments",
FUNC_MAX_ARGS,
FUNC_MAX_ARGS))); /* note: the above is correct, we do NOT count output arguments */
if (ARR_NDIM(modesArray) != 1 ||
ARR_DIMS(modesArray)[0] != allParamCount ||
ARR_HASNULL(modesArray) ||
ARR_ELEMTYPE(modesArray) != CHAROID)
elog(ERROR, "parameterModes is not a 1-D char array");
paramModes = (char *) ARR_DATA_PTR(modesArray);
}
/* *Donotallowpolymorphicreturntypeunlessthereisapolymorphic *inputargumentthatwecanusetodeducetheactualreturntype.
*/
detailmsg = check_valid_polymorphic_signature(returnType,
parameterTypes->values,
parameterCount); if (detailmsg)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("cannot determine result data type"),
errdetail_internal("%s", detailmsg)));
/* *Also,donotallowreturntypeINTERNALunlessatleastoneinput *argumentisINTERNAL.
*/
detailmsg = check_valid_internal_signature(returnType,
parameterTypes->values,
parameterCount); if (detailmsg)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("unsafe use of pseudo-type \"internal\""),
errdetail_internal("%s", detailmsg)));
/* *ApplythesameteststoanyOUTarguments.
*/ if (allParameterTypes != PointerGetDatum(NULL))
{ for (i = 0; i < allParamCount; i++)
{ if (paramModes == NULL ||
paramModes[i] == PROARGMODE_IN ||
paramModes[i] == PROARGMODE_VARIADIC) continue; /* ignore input-only params */
detailmsg = check_valid_polymorphic_signature(allParams[i],
parameterTypes->values,
parameterCount); if (detailmsg)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("cannot determine result data type"),
errdetail_internal("%s", detailmsg)));
detailmsg = check_valid_internal_signature(allParams[i],
parameterTypes->values,
parameterCount); if (detailmsg)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("unsafe use of pseudo-type \"internal\""),
errdetail_internal("%s", detailmsg)));
}
}
/* Identify variadic argument type, if any */ if (paramModes != NULL)
{ /* *Onlythelastinputparametercanbevariadic;ifitis,saveits *elementtype.Errorsherearejustelogsincecallershouldhave *checkedthisalready.
*/ for (i = 0; i < allParamCount; i++)
{ switch (paramModes[i])
{ case PROARGMODE_IN: case PROARGMODE_INOUT: if (OidIsValid(variadicType))
elog(ERROR, "variadic parameter must be last"); break; case PROARGMODE_OUT: if (OidIsValid(variadicType) && prokind == PROKIND_PROCEDURE)
elog(ERROR, "variadic parameter must be last"); break; case PROARGMODE_TABLE: /* okay */ break; case PROARGMODE_VARIADIC: if (OidIsValid(variadicType))
elog(ERROR, "variadic parameter must be last"); switch (allParams[i])
{ case ANYOID:
variadicType = ANYOID; break; case ANYARRAYOID:
variadicType = ANYELEMENTOID; break; case ANYCOMPATIBLEARRAYOID:
variadicType = ANYCOMPATIBLEOID; break; default:
variadicType = get_element_type(allParams[i]); if (!OidIsValid(variadicType))
elog(ERROR, "variadic parameter is not an array"); break;
} break; default:
elog(ERROR, "invalid parameter mode '%c'", paramModes[i]); break;
}
}
}
if (HeapTupleIsValid(oldtup))
{ /* There is one; okay to replace it? */
Form_pg_proc oldproc = (Form_pg_proc) GETSTRUCT(oldtup);
Datum proargnames; bool isnull; constchar *dropcmd;
if (!replace)
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_FUNCTION),
errmsg("function \"%s\" already exists with same argument types",
procedureName))); if (!object_ownercheck(ProcedureRelationId, oldproc->oid, proowner))
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FUNCTION,
procedureName);
/* Not okay to change routine kind */ if (oldproc->prokind != prokind)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("cannot change routine kind"),
(oldproc->prokind == PROKIND_AGGREGATE ?
errdetail("\"%s\" is an aggregate function.", procedureName) :
oldproc->prokind == PROKIND_FUNCTION ?
errdetail("\"%s\" is a function.", procedureName) :
oldproc->prokind == PROKIND_PROCEDURE ?
errdetail("\"%s\" is a procedure.", procedureName) :
oldproc->prokind == PROKIND_WINDOW ?
errdetail("\"%s\" is a window function.", procedureName) : 0)));
olddesc = build_function_result_tupdesc_t(oldtup);
newdesc = build_function_result_tupdesc_d(prokind,
allParameterTypes,
parameterModes,
parameterNames); if (olddesc == NULL && newdesc == NULL) /* ok, both are runtime-defined RECORDs */ ; elseif (olddesc == NULL || newdesc == NULL ||
!equalRowTypes(olddesc, newdesc))
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("cannot change return type of existing function"),
errdetail("Row type defined by OUT parameters is different."), /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
errhint("Use %s %s first.",
dropcmd,
format_procedure(oldproc->oid))));
}
/* *Iftherewereanynamedinputparameters,checktomakesurethe *nameshavenotbeenchanged,asthiscouldbreakexistingcalls.We *allowaddingnamestoformerlyunnamedparameters,though.
*/
proargnames = SysCacheGetAttr(PROCNAMEARGSNSP, oldtup,
Anum_pg_proc_proargnames,
&isnull); if (!isnull)
{
Datum proargmodes; char **old_arg_names; char **new_arg_names; int n_old_arg_names; int n_new_arg_names; int j;
proargmodes = SysCacheGetAttr(PROCNAMEARGSNSP, oldtup,
Anum_pg_proc_proargmodes,
&isnull); if (isnull)
proargmodes = PointerGetDatum(NULL); /* just to be sure */
n_old_arg_names = get_func_input_arg_names(proargnames,
proargmodes,
&old_arg_names);
n_new_arg_names = get_func_input_arg_names(parameterNames,
parameterModes,
&new_arg_names); for (j = 0; j < n_old_arg_names; j++)
{ if (old_arg_names[j] == NULL) continue; if (j >= n_new_arg_names || new_arg_names[j] == NULL ||
strcmp(old_arg_names[j], new_arg_names[j]) != 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("cannot change name of input parameter \"%s\"",
old_arg_names[j]), /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
errhint("Use %s %s first.",
dropcmd,
format_procedure(oldproc->oid))));
}
}
/* *Ifthereareexistingdefaults,checkcompatibility:redefinition *mustnotremoveanydefaultsnorchangetheirtypes.(Removinga *defaultmightcauseafunctiontofailtosatisfyanexistingcall. *Changingtypewouldonlybepossibleiftheassociatedparameteris *polymorphic,andinsuchcasesachangeofdefaulttypemightalter *theresolvedoutputtypeofexistingcalls.)
*/ if (oldproc->pronargdefaults != 0)
{
Datum proargdefaults;
List *oldDefaults;
ListCell *oldlc;
ListCell *newlc;
if (list_length(parameterDefaults) < oldproc->pronargdefaults)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("cannot remove parameter defaults from existing function"), /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
errhint("Use %s %s first.",
dropcmd,
format_procedure(oldproc->oid))));
/* new list can have more defaults than old, advance over 'em */
newlc = list_nth_cell(parameterDefaults,
list_length(parameterDefaults) -
oldproc->pronargdefaults);
if (exprType(oldDef) != exprType(newDef))
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("cannot change data type of existing parameter default value"), /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
errhint("Use %s %s first.",
dropcmd,
format_procedure(oldproc->oid))));
newlc = lnext(parameterDefaults, newlc);
}
}
/* dependency on namespace */
ObjectAddressSet(referenced, NamespaceRelationId, procNamespace);
add_exact_object_address(&referenced, addrs);
/* dependency on implementation language */
ObjectAddressSet(referenced, LanguageRelationId, languageObjectId);
add_exact_object_address(&referenced, addrs);
/* dependency on return type */
ObjectAddressSet(referenced, TypeRelationId, returnType);
add_exact_object_address(&referenced, addrs);
/* dependency on parameter types */ for (i = 0; i < allParamCount; i++)
{
ObjectAddressSet(referenced, TypeRelationId, allParams[i]);
add_exact_object_address(&referenced, addrs);
}
/* dependency on transforms, if any */
foreach_oid(transformid, trfoids)
{
ObjectAddressSet(referenced, TransformRelationId, transformid);
add_exact_object_address(&referenced, addrs);
}
/* dependency on support function, if any */ if (OidIsValid(prosupport))
{
ObjectAddressSet(referenced, ProcedureRelationId, prosupport);
add_exact_object_address(&referenced, addrs);
}
tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid)); if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for function %u", funcoid);
if (fmgr_internal_function(prosrc) == InvalidOid)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("there is no built-in function named \"%s\"",
prosrc)));
ReleaseSysCache(tuple);
PG_RETURN_VOID();
}
/* *ValidatorforClanguagefunctions * *Makesurethatthelibraryfileexists,isloadable,andcontains *thespecifiedlinksymbol.Alsocheckforavalidfunction *informationrecord.
*/
Datum
fmgr_c_validator(PG_FUNCTION_ARGS)
{
Oid funcoid = PG_GETARG_OID(0); void *libraryhandle;
HeapTuple tuple;
Datum tmp; char *prosrc; char *probin;
if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
PG_RETURN_VOID();
tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid)); if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for function %u", funcoid);
/* *ValidatorforSQLlanguagefunctions * *Parseithereinordertobesurethatitcontainsnosyntaxerrors.
*/
Datum
fmgr_sql_validator(PG_FUNCTION_ARGS)
{
Oid funcoid = PG_GETARG_OID(0);
HeapTuple tuple;
Form_pg_proc proc;
List *raw_parsetree_list;
List *querytree_list;
ListCell *lc; bool isnull;
Datum tmp; char *prosrc;
parse_error_callback_arg callback_arg;
ErrorContextCallback sqlerrcontext; bool haspolyarg; int i;
if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
PG_RETURN_VOID();
tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid)); if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for function %u", funcoid);
proc = (Form_pg_proc) GETSTRUCT(tuple);
/* Disallow pseudotype result */ /* except for RECORD, VOID, or polymorphic */ if (get_typtype(proc->prorettype) == TYPTYPE_PSEUDO &&
proc->prorettype != RECORDOID &&
proc->prorettype != VOIDOID &&
!IsPolymorphicType(proc->prorettype))
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("SQL functions cannot return type %s",
format_type_be(proc->prorettype))));
/* Disallow pseudotypes in arguments */ /* except for polymorphic */
haspolyarg = false; for (i = 0; i < proc->pronargs; i++)
{ if (get_typtype(proc->proargtypes.values[i]) == TYPTYPE_PSEUDO)
{ if (IsPolymorphicType(proc->proargtypes.values[i]))
haspolyarg = true; else
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("SQL functions cannot have arguments of type %s",
format_type_be(proc->proargtypes.values[i]))));
}
}
/* Postpone body checks if !check_function_bodies */ if (check_function_bodies)
{
tmp = SysCacheGetAttrNotNull(PROCOID, tuple, Anum_pg_proc_prosrc);
prosrc = TextDatumGetCString(tmp);
/* If we have prosqlbody, pay attention to that not prosrc */
tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosqlbody, &isnull); if (!isnull)
{
Node *n;
List *stored_query_list;
n = stringToNode(TextDatumGetCString(tmp)); if (IsA(n, List))
stored_query_list = linitial(castNode(List, n)); else
stored_query_list = list_make1(n);
/* See if it's a syntax error; if so, transpose to CREATE FUNCTION */ if (!function_parse_error_transpose(callback_arg->prosrc))
{ /* If it's not a syntax error, push info onto context stack */
errcontext("SQL function \"%s\"", callback_arg->proname);
}
}
/* *AdjustasyntaxerroroccurringinsidethefunctionbodyofaCREATE *FUNCTIONorDOcommand.Thiscanbeusedbyanyfunctionvalidatoror *anonymous-blockhandler,notonlyforSQL-languagefunctions. *Itisassumedthatthesyntaxerrorpositionisinitiallyrelativetothe *functionbodystring(aspassedin).Ifpossible,weadjusttheposition *toreferencetheoriginalcommandtext;ifwecan'tmanagethat,weset *upan"internalquery"syntaxerrorinstead. * *Returnstrueifasyntaxerrorwasprocessed,falseifnot.
*/ bool
function_parse_error_transpose(constchar *prosrc)
{ int origerrposition; int newerrposition;
/* We can get the original query text from the active portal (hack...) */ if (ActivePortal && ActivePortal->status == PORTAL_ACTIVE)
{ constchar *queryText = ActivePortal->sourceText;
/* Try to locate the prosrc in the original text */
newerrposition = match_prosrc_to_query(prosrc, queryText,
origerrposition);
} else
{ /* *QuietlygiveupifnoActivePortal.Thisisanunusualsituation *butitcanhappenin,e.g.,logicalreplicationworkers.
*/
newerrposition = -1;
}
if (newerrposition > 0)
{ /* Successful, so fix error position to reference original query */
errposition(newerrposition); /* Get rid of any report of the error as an "internal query" */
internalerrposition(0);
internalerrquery(NULL);
} else
{ /* *Ifunsuccessful,convertthepositiontoaninternalposition *markerandgivethefunctiontextastheinternalquery.
*/
errposition(0);
internalerrposition(origerrposition);
internalerrquery(prosrc);
}
returntrue;
}
/* *Trytolocatethestringliteralcontainingthefunctionbodyinthe *giventextoftheCREATEFUNCTIONorDOcommand.Ifsuccessful,return *thecharacter(notbyte)indexwithinthecommandcorrespondingtothe *givencharacterindexwithintheliteral.Ifnotsuccessful,return0.
*/ staticint
match_prosrc_to_query(constchar *prosrc, constchar *queryText, int cursorpos)
{ /* *Ratherthanfullyparsingtheoriginalcommand,wejustscanthe *commandlookingfor$prosrc$or'prosrc'.Thiscouldbefooled(though *notinanyveryprobablescenarios),sofailifwefindmorethanone *match.
*/ int prosrclen = strlen(prosrc); int querylen = strlen(queryText); int matchpos = 0; int curpos; int newcursorpos;
fail: /* Must set *newcursorpos to suppress compiler warning */
*newcursorpos = newcp; returnfalse;
}
List *
oid_array_to_list(Datum datum)
{
ArrayType *array = DatumGetArrayTypeP(datum);
Datum *values; int nelems; int i;
List *result = NIL;
deconstruct_array_builtin(array, OIDOID, &values, NULL, &nelems); for (i = 0; i < nelems; i++)
result = lappend_oid(result, values[i]); return result;
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.24 Sekunden
(vorverarbeitet am 2026-08-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.