Skip to content

Commit f169f61

Browse files
yugo-nCommitfest Bot
authored andcommitted
Prevent internal error caused by concurrent ALTER FUNCTION
Previously, concurrent ALTER FUNCTION commands could fail with an internal error "tuple concurrently updated". This occurred because multiple sessions attempted to modify the same catalog tuple simultaneously. To prevent this, ensure that an exclusive lock on the function object is acquired earlier in the process. Additionally, if the target function is dropped by another session while waiting for the lock, an appropriate error is raised to indicate the object no longer exists.
1 parent 35d4e42 commit f169f61

File tree

1 file changed

+15
-2
lines changed

1 file changed

+15
-2
lines changed

src/backend/commands/functioncmds.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
#include "parser/parse_func.h"
6262
#include "parser/parse_type.h"
6363
#include "pgstat.h"
64+
#include "storage/lmgr.h"
6465
#include "tcop/pquery.h"
6566
#include "tcop/utility.h"
6667
#include "utils/acl.h"
@@ -1383,9 +1384,21 @@ AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt)
13831384

13841385
ObjectAddressSet(address, ProcedureRelationId, funcOid);
13851386

1387+
/* Lock the function so nobody else can do anything with it. */
1388+
LockDatabaseObject(ProcedureRelationId, funcOid, 0, AccessExclusiveLock);
1389+
1390+
/*
1391+
* It is possible that by the time we acquire the lock on function,
1392+
* concurrent DDL has removed it. We can test this by checking the
1393+
* existence of function. We get the tuple again to avoid the risk
1394+
* of function definition getting changed.
1395+
*/
13861396
tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1387-
if (!HeapTupleIsValid(tup)) /* should not happen */
1388-
elog(ERROR, "cache lookup failed for function %u", funcOid);
1397+
if (!HeapTupleIsValid(tup))
1398+
ereport(ERROR,
1399+
errcode(ERRCODE_UNDEFINED_OBJECT),
1400+
errmsg("function \"%s\" does not exist",
1401+
NameListToString(stmt->func->objname)));
13891402

13901403
procForm = (Form_pg_proc) GETSTRUCT(tup);
13911404

0 commit comments

Comments
 (0)