88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.59 2001/09/08 01:10:19 tgl Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.60 2001/10/02 21:39:35 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -41,6 +41,7 @@ static void checkretval(Oid rettype, List *queryTreeList);
4141 */
4242Oid
4343ProcedureCreate (char * procedureName ,
44+ bool replace ,
4445bool returnsSet ,
4546char * returnTypeName ,
4647char * languageName ,
@@ -58,10 +59,12 @@ ProcedureCreate(char *procedureName,
5859int i ;
5960Relation rel ;
6061HeapTuple tup ;
62+ HeapTuple oldtup ;
6163bool defined ;
6264uint16 parameterCount ;
6365char nulls [Natts_pg_proc ];
6466Datum values [Natts_pg_proc ];
67+ char replaces [Natts_pg_proc ];
6568Oid languageObjectId ;
6669Oid typeObjectId ;
6770List * x ;
@@ -120,15 +123,6 @@ ProcedureCreate(char *procedureName,
120123typev [parameterCount ++ ]= toid ;
121124}
122125
123- /* Check for duplicate definition */
124- if (SearchSysCacheExists (PROCNAME ,
125- PointerGetDatum (procedureName ),
126- UInt16GetDatum (parameterCount ),
127- PointerGetDatum (typev ),
128- 0 ))
129- elog (ERROR ,"function %s already exists with same argument types" ,
130- procedureName );
131-
132126if (languageObjectId == SQLlanguageId )
133127{
134128
@@ -260,13 +254,14 @@ ProcedureCreate(char *procedureName,
260254}
261255
262256/*
263- * All seems OK; prepare thetuple to be inserted into pg_proc.
257+ * All seems OK; prepare thedata to be inserted into pg_proc.
264258 */
265259
266260for (i = 0 ;i < Natts_pg_proc ;++ i )
267261{
268262nulls [i ]= ' ' ;
269263values [i ]= (Datum )NULL ;
264+ replaces [i ]= 'r' ;
270265}
271266
272267i = 0 ;
@@ -293,14 +288,49 @@ ProcedureCreate(char *procedureName,
293288CStringGetDatum (probin ));
294289
295290rel = heap_openr (ProcedureRelationName ,RowExclusiveLock );
296-
297291tupDesc = rel -> rd_att ;
298- tup = heap_formtuple (tupDesc ,
299- values ,
300- nulls );
301292
302- heap_insert (rel ,tup );
293+ /* Check for pre-existing definition */
294+ oldtup = SearchSysCache (PROCNAME ,
295+ PointerGetDatum (procedureName ),
296+ UInt16GetDatum (parameterCount ),
297+ PointerGetDatum (typev ),
298+ 0 );
303299
300+ if (HeapTupleIsValid (oldtup ))
301+ {
302+ /* There is one; okay to replace it? */
303+ Form_pg_proc oldproc = (Form_pg_proc )GETSTRUCT (oldtup );
304+
305+ if (!replace )
306+ elog (ERROR ,"function %s already exists with same argument types" ,
307+ procedureName );
308+ if (GetUserId ()!= oldproc -> proowner && !superuser ())
309+ elog (ERROR ,"ProcedureCreate: you do not have permission to replace function %s" ,
310+ procedureName );
311+ /*
312+ * Not okay to change the return type of the existing proc, since
313+ * existing rules, views, etc may depend on the return type.
314+ */
315+ if (typeObjectId != oldproc -> prorettype ||
316+ returnsSet != oldproc -> proretset )
317+ elog (ERROR ,"ProcedureCreate: cannot change return type of existing function."
318+ "\n\tUse DROP FUNCTION first." );
319+
320+ /* Okay, do it... */
321+ tup = heap_modifytuple (oldtup ,rel ,values ,nulls ,replaces );
322+ simple_heap_update (rel ,& tup -> t_self ,tup );
323+
324+ ReleaseSysCache (oldtup );
325+ }
326+ else
327+ {
328+ /* Creating a new procedure */
329+ tup = heap_formtuple (tupDesc ,values ,nulls );
330+ heap_insert (rel ,tup );
331+ }
332+
333+ /* Need to update indices for either the insert or update case */
304334if (RelationGetForm (rel )-> relhasindex )
305335{
306336Relation idescs [Num_pg_proc_indices ];
@@ -309,9 +339,12 @@ ProcedureCreate(char *procedureName,
309339CatalogIndexInsert (idescs ,Num_pg_proc_indices ,rel ,tup );
310340CatalogCloseIndices (Num_pg_proc_indices ,idescs );
311341}
312- heap_close ( rel , RowExclusiveLock );
342+
313343retval = tup -> t_data -> t_oid ;
314344heap_freetuple (tup );
345+
346+ heap_close (rel ,RowExclusiveLock );
347+
315348return retval ;
316349}
317350