Re: Prevent internal error at concurrent CREATE OR REPLACE FUNCTION

From: jian he <jian(dot)universality(at)gmail(dot)com>
To: Yugo Nagata <nagata(at)sraoss(dot)co(dot)jp>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: Prevent internal error at concurrent CREATE OR REPLACE FUNCTION
Date: 2025-05-27 02:03:58
Message-ID: CACJufxHrVuQhdLhzkcB_4ofo5AP256LLg10ptxxGe9YoJeQY2A@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Tue, May 27, 2025 at 1:35 AM Yugo Nagata <nagata(at)sraoss(dot)co(dot)jp> wrote:
>
> > + /* Lock the function so nobody else can do anything with it. */
> > + LockDatabaseObject(ProcedureRelationId, oldproc->oid, 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.
> > + */
> > + oldtup = SearchSysCacheCopy3(PROCNAMEARGSNSP,
> > + PointerGetDatum(procedureName),
> > + PointerGetDatum(parameterTypes),
> > + ObjectIdGetDatum(procNamespace));
> >
> > we already called LockDatabaseObject, concurrent DDL can
> > not do DROP FUNCTION or ALTER FUNCTION.
> > so no need to call SearchSysCacheCopy3 again?
>
> The function may be dropped *before* we call LockDatabaseObject.
> SearchSysCacheCopy3 is called for check this.
> Plese see AlterPublication() as a similar code example.
>

I am wondering, can we do it the following way for v2-0001?

/* Check for pre-existing definition */
oldtup = SearchSysCacheCopy3(PROCNAMEARGSNSP,
PointerGetDatum(procedureName),
PointerGetDatum(parameterTypes),
ObjectIdGetDatum(procNamespace));
if (HeapTupleIsValid(oldtup))
{
/* There is one; okay to replace it? */
Form_pg_proc oldproc = (Form_pg_proc) GETSTRUCT(oldtup);
if (!replace)
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_FUNCTION),
errmsg("function \"%s\" already exists with same
argument types",
procedureName)));
/*
* 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.
*/
if (!ConditionalLockDatabaseObject(ProcedureRelationId,
oldproc->oid, 0, AccessExclusiveLock))
oldtup = SearchSysCacheCopy3(PROCNAMEARGSNSP,
PointerGetDatum(procedureName),
PointerGetDatum(parameterTypes),
ObjectIdGetDatum(procNamespace));
}

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Quan Zongliang 2025-05-27 03:06:46 Standardize the definition of the subtype field of AlterDomainStmt
Previous Message Michael Paquier 2025-05-27 00:58:34 Re: queryId constant squashing does not support prepared statements