From b5b79dffb96760b47632cc9d325a034f5cc020e9 Mon Sep 17 00:00:00 2001 From: Yugo Nagata Date: Mon, 31 Mar 2025 20:17:07 +0900 Subject: [PATCH v2 2/2] Prevent internal error at concurrent ALTER FUNCTION --- src/backend/commands/functioncmds.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index b9fd7683abb..a41eec9d48e 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -61,6 +61,7 @@ #include "parser/parse_func.h" #include "parser/parse_type.h" #include "pgstat.h" +#include "storage/lmgr.h" #include "tcop/pquery.h" #include "tcop/utility.h" #include "utils/acl.h" @@ -1380,9 +1381,21 @@ AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt) ObjectAddressSet(address, ProcedureRelationId, funcOid); + /* Lock the function so nobody else can do anything with it. */ + LockDatabaseObject(ProcedureRelationId, funcOid, 0, AccessExclusiveLock); + + /* + * It is possible that by the time we acquire the lock on function, + * concurrent DDL has removed it. We can test this by checking the + * existence of function. We get the tuple again to avoid the risk + * of function definition getting changed. + */ tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid)); - if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "cache lookup failed for function %u", funcOid); + if (!HeapTupleIsValid(tup)) + ereport(ERROR, + errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("function \"%s\" does not exist", + NameListToString(stmt->func->objname))); procForm = (Form_pg_proc) GETSTRUCT(tup); -- 2.43.0