OSDN Git Service

Rename several destroy* functions/tags to drop*.
[pg-rex/syncrep.git] / src / backend / commands / remove.c
1 /*-------------------------------------------------------------------------
2  *
3  * remove.c
4  *        POSTGRES remove (function | type | operator ) utilty code.
5  *
6  * Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.41 1999/12/10 03:55:49 momjian Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15
16 #include "access/heapam.h"
17 #include "catalog/catname.h"
18 #include "catalog/pg_language.h"
19 #include "catalog/pg_proc.h"
20 #include "catalog/pg_type.h"
21 #include "commands/comment.h"
22 #include "commands/defrem.h"
23 #include "miscadmin.h"
24 #include "parser/parse_func.h"
25 #include "utils/acl.h"
26 #include "utils/syscache.h"
27
28
29 /*
30  * RemoveOperator
31  *              Deletes an operator.
32  *
33  * Exceptions:
34  *              BadArg if name is invalid.
35  *              BadArg if type1 is invalid.
36  *              "WARN" if operator nonexistent.
37  *              ...
38  */
39 void
40 RemoveOperator(char *operatorName,              /* operator name */
41                            char *typeName1, /* first type name */
42                            char *typeName2) /* optional second type name */
43 {
44         Relation        relation;
45         HeapTuple       tup;
46         Oid                     typeId1 = InvalidOid;
47         Oid                     typeId2 = InvalidOid;
48         bool            defined;
49         char       *userName;
50         char            oprtype;
51
52         if (typeName1)
53         {
54                 typeId1 = TypeGet(typeName1, &defined);
55                 if (!OidIsValid(typeId1))
56                 {
57                         elog(ERROR, "RemoveOperator: type '%s' does not exist", typeName1);
58                         return;
59                 }
60         }
61
62         if (typeName2)
63         {
64                 typeId2 = TypeGet(typeName2, &defined);
65                 if (!OidIsValid(typeId2))
66                 {
67                         elog(ERROR, "RemoveOperator: type '%s' does not exist", typeName2);
68                         return;
69                 }
70         }
71
72         if (OidIsValid(typeId1) && OidIsValid(typeId2))
73                 oprtype = 'b';
74         else if (OidIsValid(typeId1))
75                 oprtype = 'l';
76         else
77                 oprtype = 'r';
78
79         relation = heap_openr(OperatorRelationName, RowExclusiveLock);
80
81         tup = SearchSysCacheTupleCopy(OPERNAME,
82                                                                   PointerGetDatum(operatorName),
83                                                                   ObjectIdGetDatum(typeId1),
84                                                                   ObjectIdGetDatum(typeId2),
85                                                                   CharGetDatum(oprtype));
86
87         if (HeapTupleIsValid(tup))
88         {
89 #ifndef NO_SECURITY
90                 userName = GetPgUserName();
91                 if (!pg_ownercheck(userName,
92                                                    (char *) ObjectIdGetDatum(tup->t_data->t_oid),
93                                                    OPEROID))
94                         elog(ERROR, "RemoveOperator: operator '%s': permission denied",
95                                  operatorName);
96 #endif
97
98
99                 /*** Delete any comments associated with this operator ***/
100
101                 DeleteComments(tup->t_data->t_oid);
102
103                 heap_delete(relation, &tup->t_self, NULL);
104
105         }
106         else
107         {
108                 if (OidIsValid(typeId1) && OidIsValid(typeId2))
109                 {
110                         elog(ERROR, "RemoveOperator: binary operator '%s' taking '%s' and '%s' does not exist",
111                                  operatorName,
112                                  typeName1,
113                                  typeName2);
114                 }
115                 else if (OidIsValid(typeId1))
116                 {
117                         elog(ERROR, "RemoveOperator: right unary operator '%s' taking '%s' does not exist",
118                                  operatorName,
119                                  typeName1);
120                 }
121                 else
122                 {
123                         elog(ERROR, "RemoveOperator: left unary operator '%s' taking '%s' does not exist",
124                                  operatorName,
125                                  typeName2);
126                 }
127         }
128         pfree(tup);
129         heap_close(relation, RowExclusiveLock);
130 }
131
132 #ifdef NOTYET
133 /*
134  * this stuff is to support removing all reference to a type
135  * don't use it  - pma 2/1/94
136  */
137 /*
138  *      SingleOpOperatorRemove
139  *              Removes all operators that have operands or a result of type 'typeOid'.
140  */
141 static void
142 SingleOpOperatorRemove(Oid typeOid)
143 {
144         Relation        rel;
145         ScanKeyData key[3];
146         HeapScanDesc scan;
147         HeapTuple       tup;
148         static          attnums[3] = {7, 8, 9}; /* left, right, return */
149         int                     i;
150
151         ScanKeyEntryInitialize(&key[0],
152                                                    0, 0, F_OIDEQ, (Datum) typeOid);
153         rel = heap_openr(OperatorRelationName, RowExclusiveLock);
154         for (i = 0; i < 3; ++i)
155         {
156                 key[0].sk_attno = attnums[i];
157                 scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
158                 while (HeapTupleIsValid(tup = heap_getnext(scan, 0))) {
159
160                   /*** This is apparently a routine not in use, but remove ***/
161                   /*** any comments anyways ***/
162
163                   DeleteComments(tup->t_data->t_oid);
164
165                   heap_delete(rel, &tup->t_self, NULL);
166                   
167                 }
168
169                 heap_endscan(scan);
170         }
171         heap_close(rel, RowExclusiveLock);
172 }
173
174 /*
175  *      AttributeAndRelationRemove
176  *              Removes all entries in the attribute and relation relations
177  *              that contain entries of type 'typeOid'.
178  *              Currently nothing calls this code, it is untested.
179  */
180 static void
181 AttributeAndRelationRemove(Oid typeOid)
182 {
183         struct oidlist
184         {
185                 Oid                     reloid;
186                 struct oidlist *next;
187         };
188         struct oidlist *oidptr,
189                            *optr;
190         Relation        rel;
191         ScanKeyData key[1];
192         HeapScanDesc scan;
193         HeapTuple       tup;
194
195         /*
196          * Get the oid's of the relations to be removed by scanning the entire
197          * attribute relation. We don't need to remove the attributes here,
198          * because amdestroy will remove all attributes of the relation. XXX
199          * should check for duplicate relations
200          */
201
202         ScanKeyEntryInitialize(&key[0],
203                                                    0, 3, F_OIDEQ, (Datum) typeOid);
204
205         oidptr = (struct oidlist *) palloc(sizeof(*oidptr));
206         oidptr->next = NULL;
207         optr = oidptr;
208         rel = heap_openr(AttributeRelationName, AccessShareLock);
209         scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
210         while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
211         {
212                 optr->reloid = ((Form_pg_attribute) GETSTRUCT(tup))->attrelid;
213                 optr->next = (struct oidlist *) palloc(sizeof(*oidptr));
214                 optr = optr->next;
215         }
216         optr->next = NULL;
217         heap_endscan(scan);
218         heap_close(rel, AccessShareLock);
219
220         optr = oidptr;
221
222         ScanKeyEntryInitialize(&key[0], 0,
223                                                    ObjectIdAttributeNumber,
224                                                    F_OIDEQ, (Datum) 0);
225         /* get RowExclusiveLock because heap_destroy will need it */
226         rel = heap_openr(RelationRelationName, RowExclusiveLock);
227         while (PointerIsValid((char *) optr->next))
228         {
229                 key[0].sk_argument = (Datum) (optr++)->reloid;
230                 scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
231                 tup = heap_getnext(scan, 0);
232                 if (HeapTupleIsValid(tup))
233                 {
234                         char       *name;
235
236                         name = NameStr(((Form_pg_class) GETSTRUCT(tup))->relname);
237                         heap_drop_with_catalog(name);
238                 }
239                 heap_endscan(scan);
240         }
241         heap_close(rel, RowExclusiveLock);
242 }
243
244 #endif   /* NOTYET */
245
246 /*
247  *      TypeRemove
248  *              Removes the type 'typeName' and all attributes and relations that
249  *              use it.
250  */
251 void
252 RemoveType(char *typeName)              /* type name to be removed */
253 {
254         Relation        relation;
255         HeapTuple       tup;
256         Oid                     typeOid;
257         char       *shadow_type;
258         char       *userName;
259
260 #ifndef NO_SECURITY
261         userName = GetPgUserName();
262         if (!pg_ownercheck(userName, typeName, TYPENAME))
263                 elog(ERROR, "RemoveType: type '%s': permission denied",
264                          typeName);
265 #endif
266
267         relation = heap_openr(TypeRelationName, RowExclusiveLock);
268
269         tup = SearchSysCacheTuple(TYPENAME,
270                                                           PointerGetDatum(typeName),
271                                                           0, 0, 0);
272         if (!HeapTupleIsValid(tup))
273         {
274                 heap_close(relation, RowExclusiveLock);
275                 elog(ERROR, "RemoveType: type '%s' does not exist", typeName);
276         }
277
278         typeOid = tup->t_data->t_oid;
279
280         /*** Delete any comments associated with this type ***/
281
282         DeleteComments(typeOid);
283
284         heap_delete(relation, &tup->t_self, NULL);
285
286         /* Now, Delete the "array of" that type */
287         shadow_type = makeArrayTypeName(typeName);
288         tup = SearchSysCacheTuple(TYPENAME,
289                                                           PointerGetDatum(shadow_type),
290                                                           0, 0, 0);
291         if (!HeapTupleIsValid(tup))
292         {
293                 heap_close(relation, RowExclusiveLock);
294                 elog(ERROR, "RemoveType: type '%s' does not exist", shadow_type);
295         }
296
297         heap_delete(relation, &tup->t_self, NULL);
298
299         heap_close(relation, RowExclusiveLock);
300 }
301
302 /*
303  * RemoveFunction
304  *              Deletes a function.
305  *
306  * Exceptions:
307  *              BadArg if name is invalid.
308  *              "WARN" if function nonexistent.
309  *              ...
310  */
311 void
312 RemoveFunction(char *functionName,              /* function name to be removed */
313                            int nargs,
314                            List *argNameList /* list of TypeNames */ )
315 {
316         Relation        relation;
317         HeapTuple       tup;
318         Oid                     argList[8];
319         char       *userName;
320         char       *typename;
321         int                     i;
322
323
324         MemSet(argList, 0, 8 * sizeof(Oid));
325         for (i = 0; i < nargs; i++)
326         {
327                 typename = strVal(lfirst(argNameList));
328                 argNameList = lnext(argNameList);
329
330                 if (strcmp(typename, "opaque") == 0)
331                         argList[i] = 0;
332                 else
333                 {
334                         tup = SearchSysCacheTuple(TYPENAME,
335                                                                           PointerGetDatum(typename),
336                                                                           0, 0, 0);
337
338                         if (!HeapTupleIsValid(tup))
339                                 elog(ERROR, "RemoveFunction: type '%s' not found", typename);
340                         argList[i] = tup->t_data->t_oid;
341                 }
342         }
343
344 #ifndef NO_SECURITY
345         userName = GetPgUserName();
346         if (!pg_func_ownercheck(userName, functionName, nargs, argList))
347         {
348                 elog(ERROR, "RemoveFunction: function '%s': permission denied",
349                          functionName);
350         }
351 #endif
352
353         relation = heap_openr(ProcedureRelationName, RowExclusiveLock);
354         tup = SearchSysCacheTuple(PROCNAME,
355                                                           PointerGetDatum(functionName),
356                                                           Int32GetDatum(nargs),
357                                                           PointerGetDatum(argList),
358                                                           0);
359
360         if (!HeapTupleIsValid(tup))
361         {
362                 heap_close(relation, RowExclusiveLock);
363                 func_error("RemoveFunction", functionName, nargs, argList, NULL);
364         }
365
366         if ((((Form_pg_proc) GETSTRUCT(tup))->prolang) == INTERNALlanguageId)
367         {
368                 heap_close(relation, RowExclusiveLock);
369                 elog(ERROR, "RemoveFunction: function \"%s\" is built-in", functionName);
370         }
371
372         /*** Delete any comments associated with this function ***/
373
374         DeleteComments(tup->t_data->t_oid);
375
376         heap_delete(relation, &tup->t_self, NULL);
377
378         heap_close(relation, RowExclusiveLock);
379 }
380
381 void
382 RemoveAggregate(char *aggName, char *aggType)
383 {
384         Relation        relation;
385         HeapTuple       tup;
386         char       *userName;
387         Oid                     basetypeID = InvalidOid;
388         bool            defined;
389
390
391         /*
392          * if a basetype is passed in, then attempt to find an aggregate for
393          * that specific type.
394          *
395          * else if the basetype is blank, then attempt to find an aggregate with
396          * a basetype of zero.  This is valid. It means that the aggregate is
397          * to apply to all basetypes.  ie, a counter of some sort.
398          *
399          */
400
401         if (aggType)
402         {
403                 basetypeID = TypeGet(aggType, &defined);
404                 if (!OidIsValid(basetypeID))
405                         elog(ERROR, "RemoveAggregate: type '%s' does not exist", aggType);
406         }
407         else
408                 basetypeID = 0;
409
410 #ifndef NO_SECURITY
411         userName = GetPgUserName();
412         if (!pg_aggr_ownercheck(userName, aggName, basetypeID))
413         {
414                 if (aggType)
415                 {
416                         elog(ERROR, "RemoveAggregate: aggregate '%s' on type '%s': permission denied",
417                                  aggName, aggType);
418                 }
419                 else
420                 {
421                         elog(ERROR, "RemoveAggregate: aggregate '%s': permission denied",
422                                  aggName);
423                 }
424         }
425 #endif
426
427         relation = heap_openr(AggregateRelationName, RowExclusiveLock);
428         tup = SearchSysCacheTuple(AGGNAME,
429                                                           PointerGetDatum(aggName),
430                                                           ObjectIdGetDatum(basetypeID),
431                                                           0, 0);
432
433         if (!HeapTupleIsValid(tup))
434         {
435                 heap_close(relation, RowExclusiveLock);
436                 if (aggType)
437                 {
438                         elog(ERROR, "RemoveAggregate: aggregate '%s' for '%s' does not exist",
439                                  aggName, aggType);
440                 }
441                 else
442                 {
443                         elog(ERROR, "RemoveAggregate: aggregate '%s' for all types does not exist",
444                                  aggName);
445                 }
446         }
447         
448         /*** Remove any comments related to this aggregate ***/
449
450         DeleteComments(tup->t_data->t_oid);
451
452         heap_delete(relation, &tup->t_self, NULL);
453
454         heap_close(relation, RowExclusiveLock);
455 }