Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f97a454

Browse files
yugo-nCommitfest Bot
authored and
Commitfest Bot
committed
Prevent internal error at concurrent CREATE OR REPLACE FUNCTION
1 parent b006bcd commit f97a454

File tree

1 file changed

+30
-8
lines changed

1 file changed

+30
-8
lines changed

src/backend/catalog/pg_proc.c

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "parser/parse_coerce.h"
3535
#include "pgstat.h"
3636
#include "rewrite/rewriteHandler.h"
37+
#include "storage/lmgr.h"
3738
#include "tcop/pquery.h"
3839
#include "tcop/tcopprot.h"
3940
#include "utils/acl.h"
@@ -383,24 +384,45 @@ ProcedureCreate(const char *procedureName,
383384
tupDesc = RelationGetDescr(rel);
384385

385386
/* Check for pre-existing definition */
386-
oldtup = SearchSysCache3(PROCNAMEARGSNSP,
387-
PointerGetDatum(procedureName),
388-
PointerGetDatum(parameterTypes),
389-
ObjectIdGetDatum(procNamespace));
387+
oldtup = SearchSysCacheCopy3(PROCNAMEARGSNSP,
388+
PointerGetDatum(procedureName),
389+
PointerGetDatum(parameterTypes),
390+
ObjectIdGetDatum(procNamespace));
390391

391392
if (HeapTupleIsValid(oldtup))
392393
{
393394
/* There is one; okay to replace it? */
394395
Form_pg_proc oldproc = (Form_pg_proc) GETSTRUCT(oldtup);
395-
Datum proargnames;
396-
bool isnull;
397-
const char *dropcmd;
398396

399397
if (!replace)
400398
ereport(ERROR,
401399
(errcode(ERRCODE_DUPLICATE_FUNCTION),
402400
errmsg("function \"%s\" already exists with same argument types",
403401
procedureName)));
402+
403+
/* Lock the function so nobody else can do anything with it. */
404+
LockDatabaseObject(ProcedureRelationId, oldproc->oid, 0, AccessExclusiveLock);
405+
406+
/*
407+
* It is possible that by the time we acquire the lock on function,
408+
* concurrent DDL has removed it. We can test this by checking the
409+
* existence of function. We get the tuple again to avoid the risk
410+
* of function definition getting changed.
411+
*/
412+
oldtup = SearchSysCacheCopy3(PROCNAMEARGSNSP,
413+
PointerGetDatum(procedureName),
414+
PointerGetDatum(parameterTypes),
415+
ObjectIdGetDatum(procNamespace));
416+
}
417+
418+
if (HeapTupleIsValid(oldtup))
419+
{
420+
421+
Form_pg_proc oldproc = (Form_pg_proc) GETSTRUCT(oldtup);
422+
Datum proargnames;
423+
bool isnull;
424+
const char *dropcmd;
425+
404426
if (!object_ownercheck(ProcedureRelationId, oldproc->oid, proowner))
405427
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FUNCTION,
406428
procedureName);
@@ -585,7 +607,7 @@ ProcedureCreate(const char *procedureName,
585607
tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces);
586608
CatalogTupleUpdate(rel, &tup->t_self, tup);
587609

588-
ReleaseSysCache(oldtup);
610+
heap_freetuple(oldtup);
589611
is_update = true;
590612
}
591613
else

0 commit comments

Comments
 (0)