20
20
#include "catalog/namespace.h"
21
21
#include "catalog/objectaddress.h"
22
22
#include "catalog/pg_class.h"
23
+ #include "catalog/pg_proc.h"
23
24
#include "commands/defrem.h"
24
25
#include "miscadmin.h"
25
26
#include "nodes/makefuncs.h"
26
27
#include "parser/parse_type.h"
27
28
#include "utils/acl.h"
29
+ #include "utils/builtins.h"
30
+ #include "utils/syscache.h"
28
31
29
- static void does_not_exist_skipping (ObjectType objtype , List * objname );
32
+ static void does_not_exist_skipping (ObjectType objtype ,
33
+ List * objname , List * objargs );
30
34
31
35
/*
32
36
* Drop one or more objects.
@@ -44,36 +48,68 @@ RemoveObjects(DropStmt *stmt)
44
48
{
45
49
ObjectAddresses * objects ;
46
50
ListCell * cell1 ;
51
+ ListCell * cell2 = NULL ;
47
52
48
53
objects = new_object_addresses ();
49
54
50
55
foreach (cell1 , stmt -> objects )
51
56
{
52
57
ObjectAddress address ;
53
58
List * objname = lfirst (cell1 );
59
+ List * objargs = NIL ;
54
60
Relation relation = NULL ;
55
61
Oid namespaceId ;
56
62
63
+ if (stmt -> arguments )
64
+ {
65
+ cell2 = (!cell2 ? list_head (stmt -> arguments ) : lnext (cell2 ));
66
+ objargs = lfirst (cell2 );
67
+ }
68
+
57
69
/* Get an ObjectAddress for the object. */
58
70
address = get_object_address (stmt -> removeType ,
59
- objname , NIL ,
71
+ objname , objargs ,
60
72
& relation ,
61
73
AccessExclusiveLock ,
62
74
stmt -> missing_ok );
63
75
64
76
/* Issue NOTICE if supplied object was not found. */
65
77
if (!OidIsValid (address .objectId ))
66
78
{
67
- does_not_exist_skipping (stmt -> removeType , objname );
79
+ does_not_exist_skipping (stmt -> removeType , objname , objargs );
68
80
continue ;
69
81
}
70
82
83
+ /*
84
+ * Although COMMENT ON FUNCTION, SECURITY LABEL ON FUNCTION, etc. are
85
+ * happy to operate on an aggregate as on any other function, we have
86
+ * historically not allowed this for DROP FUNCTION.
87
+ */
88
+ if (stmt -> removeType == OBJECT_FUNCTION )
89
+ {
90
+ Oid funcOid = address .objectId ;
91
+ HeapTuple tup ;
92
+
93
+ tup = SearchSysCache1 (PROCOID , ObjectIdGetDatum (funcOid ));
94
+ if (!HeapTupleIsValid (tup )) /* should not happen */
95
+ elog (ERROR , "cache lookup failed for function %u" , funcOid );
96
+
97
+ if (((Form_pg_proc ) GETSTRUCT (tup ))-> proisagg )
98
+ ereport (ERROR ,
99
+ (errcode (ERRCODE_WRONG_OBJECT_TYPE ),
100
+ errmsg ("\"%s\" is an aggregate function" ,
101
+ NameListToString (objname )),
102
+ errhint ("Use DROP AGGREGATE to drop aggregate functions." )));
103
+
104
+ ReleaseSysCache (tup );
105
+ }
106
+
71
107
/* Check permissions. */
72
108
namespaceId = get_object_namespace (& address );
73
109
if (!OidIsValid (namespaceId ) ||
74
110
!pg_namespace_ownercheck (namespaceId , GetUserId ()))
75
111
check_object_ownership (GetUserId (), stmt -> removeType , address ,
76
- objname , NIL , relation );
112
+ objname , objargs , relation );
77
113
78
114
/* Release any relcache reference count, but keep lock until commit. */
79
115
if (relation )
@@ -94,10 +130,11 @@ RemoveObjects(DropStmt *stmt)
94
130
* get_object_address() will throw an ERROR.
95
131
*/
96
132
static void
97
- does_not_exist_skipping (ObjectType objtype , List * objname )
133
+ does_not_exist_skipping (ObjectType objtype , List * objname , List * objargs )
98
134
{
99
135
const char * msg = NULL ;
100
136
char * name = NULL ;
137
+ char * args = NULL ;
101
138
102
139
switch (objtype )
103
140
{
@@ -138,10 +175,68 @@ does_not_exist_skipping(ObjectType objtype, List *objname)
138
175
msg = gettext_noop ("extension \"%s\" does not exist, skipping" );
139
176
name = NameListToString (objname );
140
177
break ;
178
+ case OBJECT_FUNCTION :
179
+ msg = gettext_noop ("function %s(%s) does not exist, skipping" );
180
+ name = NameListToString (objname );
181
+ args = TypeNameListToString (objargs );
182
+ break ;
183
+ case OBJECT_AGGREGATE :
184
+ msg = gettext_noop ("aggregate %s(%s) does not exist, skipping" );
185
+ name = NameListToString (objname );
186
+ args = TypeNameListToString (objargs );
187
+ break ;
188
+ case OBJECT_OPERATOR :
189
+ msg = gettext_noop ("operator %s does not exist, skipping" );
190
+ name = NameListToString (objname );
191
+ break ;
192
+ case OBJECT_LANGUAGE :
193
+ msg = gettext_noop ("language \"%s\" does not exist, skipping" );
194
+ name = NameListToString (objname );
195
+ break ;
196
+ case OBJECT_CAST :
197
+ msg = gettext_noop ("cast from type %s to type %s does not exist, skipping" );
198
+ name = format_type_be (typenameTypeId (NULL ,
199
+ (TypeName * ) linitial (objname )));
200
+ args = format_type_be (typenameTypeId (NULL ,
201
+ (TypeName * ) linitial (objargs )));
202
+ break ;
203
+ case OBJECT_TRIGGER :
204
+ msg = gettext_noop ("trigger \"%s\" for table \"%s\" does not exist, skipping" );
205
+ name = strVal (llast (objname ));
206
+ args = NameListToString (list_truncate (objname ,
207
+ list_length (objname ) - 1 ));
208
+ break ;
209
+ case OBJECT_RULE :
210
+ msg = gettext_noop ("rule \"%s\" for relation \"%s\" does not exist, skipping" );
211
+ name = strVal (llast (objname ));
212
+ args = NameListToString (list_truncate (objname ,
213
+ list_length (objname ) - 1 ));
214
+ break ;
215
+ case OBJECT_FDW :
216
+ msg = gettext_noop ("foreign-data wrapper \"%s\" does not exist, skipping" );
217
+ name = NameListToString (objname );
218
+ break ;
219
+ case OBJECT_FOREIGN_SERVER :
220
+ msg = gettext_noop ("server \"%s\" does not exist, skipping" );
221
+ name = NameListToString (objname );
222
+ break ;
223
+ case OBJECT_OPCLASS :
224
+ msg = gettext_noop ("operator class \"%s\" does not exist for access method \"%s\", skipping" );
225
+ name = NameListToString (objname );
226
+ args = strVal (linitial (objargs ));
227
+ break ;
228
+ case OBJECT_OPFAMILY :
229
+ msg = gettext_noop ("operator family \"%s\" does not exist for access method \"%s\", skipping" );
230
+ name = NameListToString (objname );
231
+ args = strVal (linitial (objargs ));
232
+ break ;
141
233
default :
142
234
elog (ERROR , "unexpected object type (%d)" , (int )objtype );
143
235
break ;
144
236
}
145
237
146
- ereport (NOTICE , (errmsg (msg , name )));
238
+ if (!args )
239
+ ereport (NOTICE , (errmsg (msg , name )));
240
+ else
241
+ ereport (NOTICE , (errmsg (msg , name , args )));
147
242
}
0 commit comments