PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
dropcmds.c File Reference
#include "postgres.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "catalog/dependency.h"
#include "catalog/namespace.h"
#include "catalog/objectaddress.h"
#include "catalog/pg_class.h"
#include "catalog/pg_proc.h"
#include "commands/defrem.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "parser/parse_type.h"
#include "utils/builtins.h"
#include "utils/syscache.h"
Include dependency graph for dropcmds.c:

Go to the source code of this file.

Functions

static void does_not_exist_skipping (ObjectType objtype, List *objname, List *objargs)
 
static bool owningrel_does_not_exist_skipping (List *objname, const char **msg, char **name)
 
static bool schema_does_not_exist_skipping (List *objname, const char **msg, char **name)
 
static bool type_in_list_does_not_exist_skipping (List *typenames, const char **msg, char **name)
 
void RemoveObjects (DropStmt *stmt)
 

Function Documentation

static void does_not_exist_skipping ( ObjectType  objtype,
List objname,
List objargs 
)
static

Definition at line 255 of file dropcmds.c.

References generate_unaccent_rules::args, elog, ereport, errmsg(), ERROR, gettext_noop, linitial, list_copy(), list_copy_tail(), list_length(), list_truncate(), llast, name, NameListToString(), TypeName::names, NOTICE, NULL, OBJECT_ACCESS_METHOD, OBJECT_AGGREGATE, OBJECT_CAST, OBJECT_COLLATION, OBJECT_CONVERSION, OBJECT_DOMAIN, OBJECT_EVENT_TRIGGER, OBJECT_EXTENSION, OBJECT_FDW, OBJECT_FOREIGN_SERVER, OBJECT_FUNCTION, OBJECT_LANGUAGE, OBJECT_OPCLASS, OBJECT_OPERATOR, OBJECT_OPFAMILY, OBJECT_POLICY, OBJECT_PUBLICATION, OBJECT_RULE, OBJECT_SCHEMA, OBJECT_TRANSFORM, OBJECT_TRIGGER, OBJECT_TSCONFIGURATION, OBJECT_TSDICTIONARY, OBJECT_TSPARSER, OBJECT_TSTEMPLATE, OBJECT_TYPE, owningrel_does_not_exist_skipping(), schema_does_not_exist_skipping(), strVal, type_in_list_does_not_exist_skipping(), TypeNameListToString(), and TypeNameToString().

Referenced by RemoveObjects().

256 {
257  const char *msg = NULL;
258  char *name = NULL;
259  char *args = NULL;
260 
261  switch (objtype)
262  {
264  msg = gettext_noop("access method \"%s\" does not exist, skipping");
265  name = NameListToString(objname);
266  break;
267  case OBJECT_TYPE:
268  case OBJECT_DOMAIN:
269  {
270  TypeName *typ = linitial(objname);
271 
272  if (!schema_does_not_exist_skipping(typ->names, &msg, &name))
273  {
274  msg = gettext_noop("type \"%s\" does not exist, skipping");
275  name = TypeNameToString(typ);
276  }
277  }
278  break;
279  case OBJECT_COLLATION:
280  if (!schema_does_not_exist_skipping(objname, &msg, &name))
281  {
282  msg = gettext_noop("collation \"%s\" does not exist, skipping");
283  name = NameListToString(objname);
284  }
285  break;
286  case OBJECT_CONVERSION:
287  if (!schema_does_not_exist_skipping(objname, &msg, &name))
288  {
289  msg = gettext_noop("conversion \"%s\" does not exist, skipping");
290  name = NameListToString(objname);
291  }
292  break;
293  case OBJECT_SCHEMA:
294  msg = gettext_noop("schema \"%s\" does not exist, skipping");
295  name = NameListToString(objname);
296  break;
297  case OBJECT_TSPARSER:
298  if (!schema_does_not_exist_skipping(objname, &msg, &name))
299  {
300  msg = gettext_noop("text search parser \"%s\" does not exist, skipping");
301  name = NameListToString(objname);
302  }
303  break;
304  case OBJECT_TSDICTIONARY:
305  if (!schema_does_not_exist_skipping(objname, &msg, &name))
306  {
307  msg = gettext_noop("text search dictionary \"%s\" does not exist, skipping");
308  name = NameListToString(objname);
309  }
310  break;
311  case OBJECT_TSTEMPLATE:
312  if (!schema_does_not_exist_skipping(objname, &msg, &name))
313  {
314  msg = gettext_noop("text search template \"%s\" does not exist, skipping");
315  name = NameListToString(objname);
316  }
317  break;
319  if (!schema_does_not_exist_skipping(objname, &msg, &name))
320  {
321  msg = gettext_noop("text search configuration \"%s\" does not exist, skipping");
322  name = NameListToString(objname);
323  }
324  break;
325  case OBJECT_EXTENSION:
326  msg = gettext_noop("extension \"%s\" does not exist, skipping");
327  name = NameListToString(objname);
328  break;
329  case OBJECT_FUNCTION:
330  if (!schema_does_not_exist_skipping(objname, &msg, &name) &&
331  !type_in_list_does_not_exist_skipping(objargs, &msg, &name))
332  {
333  msg = gettext_noop("function %s(%s) does not exist, skipping");
334  name = NameListToString(objname);
335  args = TypeNameListToString(objargs);
336  }
337  break;
338  case OBJECT_AGGREGATE:
339  if (!schema_does_not_exist_skipping(objname, &msg, &name) &&
340  !type_in_list_does_not_exist_skipping(objargs, &msg, &name))
341  {
342  msg = gettext_noop("aggregate %s(%s) does not exist, skipping");
343  name = NameListToString(objname);
344  args = TypeNameListToString(objargs);
345  }
346  break;
347  case OBJECT_OPERATOR:
348  if (!schema_does_not_exist_skipping(objname, &msg, &name) &&
349  !type_in_list_does_not_exist_skipping(objargs, &msg, &name))
350  {
351  msg = gettext_noop("operator %s does not exist, skipping");
352  name = NameListToString(objname);
353  }
354  break;
355  case OBJECT_LANGUAGE:
356  msg = gettext_noop("language \"%s\" does not exist, skipping");
357  name = NameListToString(objname);
358  break;
359  case OBJECT_CAST:
360  {
361  if (!type_in_list_does_not_exist_skipping(objname, &msg, &name) &&
362  !type_in_list_does_not_exist_skipping(objargs, &msg, &name))
363  {
364  /* XXX quote or no quote? */
365  msg = gettext_noop("cast from type %s to type %s does not exist, skipping");
366  name = TypeNameToString((TypeName *) linitial(objname));
367  args = TypeNameToString((TypeName *) linitial(objargs));
368  }
369  }
370  break;
371  case OBJECT_TRANSFORM:
372  if (!type_in_list_does_not_exist_skipping(objname, &msg, &name))
373  {
374  msg = gettext_noop("transform for type %s language \"%s\" does not exist, skipping");
375  name = TypeNameToString((TypeName *) linitial(objname));
376  args = strVal(linitial(objargs));
377  }
378  break;
379  case OBJECT_TRIGGER:
380  if (!owningrel_does_not_exist_skipping(objname, &msg, &name))
381  {
382  msg = gettext_noop("trigger \"%s\" for relation \"%s\" does not exist, skipping");
383  name = strVal(llast(objname));
384  args = NameListToString(list_truncate(list_copy(objname),
385  list_length(objname) - 1));
386  }
387  break;
388  case OBJECT_POLICY:
389  if (!owningrel_does_not_exist_skipping(objname, &msg, &name))
390  {
391  msg = gettext_noop("policy \"%s\" for relation \"%s\" does not exist, skipping");
392  name = strVal(llast(objname));
393  args = NameListToString(list_truncate(list_copy(objname),
394  list_length(objname) - 1));
395  }
396  break;
398  msg = gettext_noop("event trigger \"%s\" does not exist, skipping");
399  name = NameListToString(objname);
400  break;
401  case OBJECT_RULE:
402  if (!owningrel_does_not_exist_skipping(objname, &msg, &name))
403  {
404  msg = gettext_noop("rule \"%s\" for relation \"%s\" does not exist, skipping");
405  name = strVal(llast(objname));
406  args = NameListToString(list_truncate(list_copy(objname),
407  list_length(objname) - 1));
408  }
409  break;
410  case OBJECT_FDW:
411  msg = gettext_noop("foreign-data wrapper \"%s\" does not exist, skipping");
412  name = NameListToString(objname);
413  break;
415  msg = gettext_noop("server \"%s\" does not exist, skipping");
416  name = NameListToString(objname);
417  break;
418  case OBJECT_OPCLASS:
419  {
420  List *opcname = list_copy_tail(objname, 1);
421 
422  if (!schema_does_not_exist_skipping(opcname, &msg, &name))
423  {
424  msg = gettext_noop("operator class \"%s\" does not exist for access method \"%s\", skipping");
425  name = NameListToString(opcname);
426  args = strVal(linitial(objname));
427  }
428  }
429  break;
430  case OBJECT_OPFAMILY:
431  {
432  List *opfname = list_copy_tail(objname, 1);
433 
434  if (!schema_does_not_exist_skipping(opfname, &msg, &name))
435  {
436  msg = gettext_noop("operator family \"%s\" does not exist for access method \"%s\", skipping");
437  name = NameListToString(opfname);
438  args = strVal(linitial(objname));
439  }
440  }
441  break;
442  case OBJECT_PUBLICATION:
443  msg = gettext_noop("publication \"%s\" does not exist, skipping");
444  name = NameListToString(objname);
445  break;
446  default:
447  elog(ERROR, "unrecognized object type: %d", (int) objtype);
448  break;
449  }
450 
451  if (!args)
452  ereport(NOTICE, (errmsg(msg, name)));
453  else
454  ereport(NOTICE, (errmsg(msg, name, args)));
455 }
List * names
Definition: parsenodes.h:200
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:459
#define llast(l)
Definition: pg_list.h:126
List * list_truncate(List *list, int new_size)
Definition: list.c:350
#define gettext_noop(x)
Definition: c.h:139
List * list_copy(const List *oldlist)
Definition: list.c:1160
#define strVal(v)
Definition: value.h:54
char * TypeNameListToString(List *typenames)
Definition: parse_type.c:473
List * list_copy_tail(const List *oldlist, int nskip)
Definition: list.c:1203
#define linitial(l)
Definition: pg_list.h:110
#define ERROR
Definition: elog.h:43
static bool owningrel_does_not_exist_skipping(List *objname, const char **msg, char **name)
Definition: dropcmds.c:150
static bool schema_does_not_exist_skipping(List *objname, const char **msg, char **name)
Definition: dropcmds.c:186
#define ereport(elevel, rest)
Definition: elog.h:122
char * NameListToString(List *names)
Definition: namespace.c:2897
static bool type_in_list_does_not_exist_skipping(List *typenames, const char **msg, char **name)
Definition: dropcmds.c:218
#define NOTICE
Definition: elog.h:37
#define NULL
Definition: c.h:226
static int list_length(const List *l)
Definition: pg_list.h:89
const char * name
Definition: encode.c:521
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
static bool owningrel_does_not_exist_skipping ( List objname,
const char **  msg,
char **  name 
)
static

Definition at line 150 of file dropcmds.c.

References gettext_noop, list_copy(), list_length(), list_truncate(), makeRangeVarFromNameList(), NameListToString(), NoLock, OidIsValid, RangeVarGetRelid, and schema_does_not_exist_skipping().

Referenced by does_not_exist_skipping().

151 {
152  List *parent_objname;
153  RangeVar *parent_rel;
154 
155  parent_objname = list_truncate(list_copy(objname),
156  list_length(objname) - 1);
157 
158  if (schema_does_not_exist_skipping(parent_objname, msg, name))
159  return true;
160 
161  parent_rel = makeRangeVarFromNameList(parent_objname);
162 
163  if (!OidIsValid(RangeVarGetRelid(parent_rel, NoLock, true)))
164  {
165  *msg = gettext_noop("relation \"%s\" does not exist, skipping");
166  *name = NameListToString(parent_objname);
167 
168  return true;
169  }
170 
171  return false;
172 }
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:53
List * list_truncate(List *list, int new_size)
Definition: list.c:350
#define gettext_noop(x)
Definition: c.h:139
List * list_copy(const List *oldlist)
Definition: list.c:1160
RangeVar * makeRangeVarFromNameList(List *names)
Definition: namespace.c:2857
#define OidIsValid(objectId)
Definition: c.h:534
#define NoLock
Definition: lockdefs.h:34
static bool schema_does_not_exist_skipping(List *objname, const char **msg, char **name)
Definition: dropcmds.c:186
char * NameListToString(List *names)
Definition: namespace.c:2897
static int list_length(const List *l)
Definition: pg_list.h:89
const char * name
Definition: encode.c:521
Definition: pg_list.h:45
void RemoveObjects ( DropStmt stmt)

Definition at line 54 of file dropcmds.c.

References AccessExclusiveLock, add_exact_object_address(), DropStmt::arguments, Assert, DropStmt::behavior, check_object_ownership(), does_not_exist_skipping(), elog, ereport, errcode(), errhint(), errmsg(), ERROR, free_object_addresses(), get_object_address(), get_object_namespace(), GETSTRUCT, GetUserId(), heap_close, HeapTupleIsValid, lfirst, list_head(), lnext, DropStmt::missing_ok, NameListToString(), new_object_addresses(), NIL, NoLock, NULL, OBJECT_FUNCTION, ObjectAddress::objectId, ObjectIdGetDatum, DropStmt::objects, OidIsValid, performMultipleDeletions(), pg_namespace_ownercheck(), PROCOID, ReleaseSysCache(), DropStmt::removeType, and SearchSysCache1.

Referenced by ExecDropStmt().

55 {
56  ObjectAddresses *objects;
57  ListCell *cell1;
58  ListCell *cell2 = NULL;
59 
60  objects = new_object_addresses();
61 
62  foreach(cell1, stmt->objects)
63  {
64  ObjectAddress address;
65  List *objname = lfirst(cell1);
66  List *objargs = NIL;
67  Relation relation = NULL;
68  Oid namespaceId;
69 
70  if (stmt->arguments)
71  {
72  cell2 = (!cell2 ? list_head(stmt->arguments) : lnext(cell2));
73  objargs = lfirst(cell2);
74  }
75 
76  /* Get an ObjectAddress for the object. */
77  address = get_object_address(stmt->removeType,
78  objname, objargs,
79  &relation,
81  stmt->missing_ok);
82 
83  /*
84  * Issue NOTICE if supplied object was not found. Note this is only
85  * relevant in the missing_ok case, because otherwise
86  * get_object_address would have thrown an error.
87  */
88  if (!OidIsValid(address.objectId))
89  {
90  Assert(stmt->missing_ok);
91  does_not_exist_skipping(stmt->removeType, objname, objargs);
92  continue;
93  }
94 
95  /*
96  * Although COMMENT ON FUNCTION, SECURITY LABEL ON FUNCTION, etc. are
97  * happy to operate on an aggregate as on any other function, we have
98  * historically not allowed this for DROP FUNCTION.
99  */
100  if (stmt->removeType == OBJECT_FUNCTION)
101  {
102  Oid funcOid = address.objectId;
103  HeapTuple tup;
104 
105  tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid));
106  if (!HeapTupleIsValid(tup)) /* should not happen */
107  elog(ERROR, "cache lookup failed for function %u", funcOid);
108 
109  if (((Form_pg_proc) GETSTRUCT(tup))->proisagg)
110  ereport(ERROR,
111  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
112  errmsg("\"%s\" is an aggregate function",
113  NameListToString(objname)),
114  errhint("Use DROP AGGREGATE to drop aggregate functions.")));
115 
116  ReleaseSysCache(tup);
117  }
118 
119  /* Check permissions. */
120  namespaceId = get_object_namespace(&address);
121  if (!OidIsValid(namespaceId) ||
122  !pg_namespace_ownercheck(namespaceId, GetUserId()))
123  check_object_ownership(GetUserId(), stmt->removeType, address,
124  objname, objargs, relation);
125 
126  /* Release any relcache reference count, but keep lock until commit. */
127  if (relation)
128  heap_close(relation, NoLock);
129 
130  add_exact_object_address(&address, objects);
131  }
132 
133  /* Here we really delete them. */
134  performMultipleDeletions(objects, stmt->behavior, 0);
135 
136  free_object_addresses(objects);
137 }
#define NIL
Definition: pg_list.h:69
int errhint(const char *fmt,...)
Definition: elog.c:987
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Oid GetUserId(void)
Definition: miscinit.c:282
List * objects
Definition: parsenodes.h:2464
bool missing_ok
Definition: parsenodes.h:2468
int errcode(int sqlerrcode)
Definition: elog.c:575
void check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address, List *objname, List *objargs, Relation relation)
bool pg_namespace_ownercheck(Oid nsp_oid, Oid roleid)
Definition: aclchk.c:4697
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2081
#define heap_close(r, l)
Definition: heapam.h:97
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2026
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2297
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:534
ObjectType removeType
Definition: parsenodes.h:2466
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
ObjectAddress get_object_address(ObjectType objtype, List *objname, List *objargs, Relation *relp, LOCKMODE lockmode, bool missing_ok)
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
DropBehavior behavior
Definition: parsenodes.h:2467
#define lnext(lc)
Definition: pg_list.h:105
#define ereport(elevel, rest)
Definition: elog.h:122
static void does_not_exist_skipping(ObjectType objtype, List *objname, List *objargs)
Definition: dropcmds.c:255
char * NameListToString(List *names)
Definition: namespace.c:2897
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
Oid get_object_namespace(const ObjectAddress *address)
#define AccessExclusiveLock
Definition: lockdefs.h:46
int errmsg(const char *fmt,...)
Definition: elog.c:797
List * arguments
Definition: parsenodes.h:2465
void performMultipleDeletions(const ObjectAddresses *objects, DropBehavior behavior, int flags)
Definition: dependency.c:360
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
static bool schema_does_not_exist_skipping ( List objname,
const char **  msg,
char **  name 
)
static

Definition at line 186 of file dropcmds.c.

References gettext_noop, LookupNamespaceNoError(), makeRangeVarFromNameList(), NULL, OidIsValid, and RangeVar::schemaname.

Referenced by does_not_exist_skipping(), owningrel_does_not_exist_skipping(), and type_in_list_does_not_exist_skipping().

187 {
188  RangeVar *rel;
189 
190  rel = makeRangeVarFromNameList(objname);
191 
192  if (rel->schemaname != NULL &&
194  {
195  *msg = gettext_noop("schema \"%s\" does not exist, skipping");
196  *name = rel->schemaname;
197 
198  return true;
199  }
200 
201  return false;
202 }
#define gettext_noop(x)
Definition: c.h:139
RangeVar * makeRangeVarFromNameList(List *names)
Definition: namespace.c:2857
#define OidIsValid(objectId)
Definition: c.h:534
char * schemaname
Definition: primnodes.h:66
#define NULL
Definition: c.h:226
const char * name
Definition: encode.c:521
Oid LookupNamespaceNoError(const char *nspname)
Definition: namespace.c:2657
static bool type_in_list_does_not_exist_skipping ( List typenames,
const char **  msg,
char **  name 
)
static

Definition at line 218 of file dropcmds.c.

References castNode, gettext_noop, lfirst, LookupTypeNameOid(), TypeName::names, NULL, OidIsValid, schema_does_not_exist_skipping(), and TypeNameToString().

Referenced by does_not_exist_skipping().

220 {
221  ListCell *l;
222 
223  foreach(l, typenames)
224  {
225  TypeName *typeName = castNode(TypeName, lfirst(l));
226 
227  if (typeName != NULL)
228  {
229  if (!OidIsValid(LookupTypeNameOid(NULL, typeName, true)))
230  {
231  /* type doesn't exist, try to find why */
232  if (schema_does_not_exist_skipping(typeName->names, msg, name))
233  return true;
234 
235  *msg = gettext_noop("type \"%s\" does not exist, skipping");
236  *name = TypeNameToString(typeName);
237 
238  return true;
239  }
240  }
241  }
242 
243  return false;
244 }
List * names
Definition: parsenodes.h:200
#define castNode(_type_, nodeptr)
Definition: nodes.h:577
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:459
#define gettext_noop(x)
Definition: c.h:139
#define OidIsValid(objectId)
Definition: c.h:534
static bool schema_does_not_exist_skipping(List *objname, const char **msg, char **name)
Definition: dropcmds.c:186
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
const char * name
Definition: encode.c:521
Oid LookupTypeNameOid(ParseState *pstate, const TypeName *typeName, bool missing_ok)
Definition: parse_type.c:215