diff options
Diffstat (limited to 'src/backend/catalog/pg_proc.c')
-rw-r--r-- | src/backend/catalog/pg_proc.c | 67 |
1 files changed, 50 insertions, 17 deletions
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index 68309a9af1a..c1547621755 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.59 2001/09/08 01:10:19 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.60 2001/10/02 21:39:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -41,6 +41,7 @@ static void checkretval(Oid rettype, List *queryTreeList); */ Oid ProcedureCreate(char *procedureName, + bool replace, bool returnsSet, char *returnTypeName, char *languageName, @@ -58,10 +59,12 @@ ProcedureCreate(char *procedureName, int i; Relation rel; HeapTuple tup; + HeapTuple oldtup; bool defined; uint16 parameterCount; char nulls[Natts_pg_proc]; Datum values[Natts_pg_proc]; + char replaces[Natts_pg_proc]; Oid languageObjectId; Oid typeObjectId; List *x; @@ -120,15 +123,6 @@ ProcedureCreate(char *procedureName, typev[parameterCount++] = toid; } - /* Check for duplicate definition */ - if (SearchSysCacheExists(PROCNAME, - PointerGetDatum(procedureName), - UInt16GetDatum(parameterCount), - PointerGetDatum(typev), - 0)) - elog(ERROR, "function %s already exists with same argument types", - procedureName); - if (languageObjectId == SQLlanguageId) { @@ -260,13 +254,14 @@ ProcedureCreate(char *procedureName, } /* - * All seems OK; prepare the tuple to be inserted into pg_proc. + * All seems OK; prepare the data to be inserted into pg_proc. */ for (i = 0; i < Natts_pg_proc; ++i) { nulls[i] = ' '; values[i] = (Datum) NULL; + replaces[i] = 'r'; } i = 0; @@ -293,14 +288,49 @@ ProcedureCreate(char *procedureName, CStringGetDatum(probin)); rel = heap_openr(ProcedureRelationName, RowExclusiveLock); - tupDesc = rel->rd_att; - tup = heap_formtuple(tupDesc, - values, - nulls); - heap_insert(rel, tup); + /* Check for pre-existing definition */ + oldtup = SearchSysCache(PROCNAME, + PointerGetDatum(procedureName), + UInt16GetDatum(parameterCount), + PointerGetDatum(typev), + 0); + if (HeapTupleIsValid(oldtup)) + { + /* There is one; okay to replace it? */ + Form_pg_proc oldproc = (Form_pg_proc) GETSTRUCT(oldtup); + + if (!replace) + elog(ERROR, "function %s already exists with same argument types", + procedureName); + if (GetUserId() != oldproc->proowner && !superuser()) + elog(ERROR, "ProcedureCreate: you do not have permission to replace function %s", + procedureName); + /* + * Not okay to change the return type of the existing proc, since + * existing rules, views, etc may depend on the return type. + */ + if (typeObjectId != oldproc->prorettype || + returnsSet != oldproc->proretset) + elog(ERROR, "ProcedureCreate: cannot change return type of existing function." + "\n\tUse DROP FUNCTION first."); + + /* Okay, do it... */ + tup = heap_modifytuple(oldtup, rel, values, nulls, replaces); + simple_heap_update(rel, &tup->t_self, tup); + + ReleaseSysCache(oldtup); + } + else + { + /* Creating a new procedure */ + tup = heap_formtuple(tupDesc, values, nulls); + heap_insert(rel, tup); + } + + /* Need to update indices for either the insert or update case */ if (RelationGetForm(rel)->relhasindex) { Relation idescs[Num_pg_proc_indices]; @@ -309,9 +339,12 @@ ProcedureCreate(char *procedureName, CatalogIndexInsert(idescs, Num_pg_proc_indices, rel, tup); CatalogCloseIndices(Num_pg_proc_indices, idescs); } - heap_close(rel, RowExclusiveLock); + retval = tup->t_data->t_oid; heap_freetuple(tup); + + heap_close(rel, RowExclusiveLock); + return retval; } |