Skip to content

Commit b152c6c

Browse files
committed
Make DROP IF EXISTS more consistently not fail
Some cases were still reporting errors and aborting, instead of a NOTICE that the object was being skipped. This makes it more difficult to cleanly handle pg_dump --clean, so change that to instead skip missing objects properly. Per bug #7873 reported by Dave Rolsky; apparently this affects a large number of users. Authors: Pavel Stehule and Dean Rasheed. Some tweaks by Álvaro Herrera
1 parent 9f80f48 commit b152c6c

File tree

17 files changed

+523
-145
lines changed

17 files changed

+523
-145
lines changed

src/backend/catalog/namespace.c

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -906,10 +906,15 @@ TypeIsVisible(Oid typid)
906906
* with oid = 0 that represents a set of such conflicting candidates.
907907
* The caller might end up discarding such an entry anyway, but if it selects
908908
* such an entry it should react as though the call were ambiguous.
909+
*
910+
* If missing_ok is true, an empty list (NULL) is returned if the name was
911+
* schema- qualified with a schema that does not exist. Likewise if no
912+
* candidate is found for other reasons.
909913
*/
910914
FuncCandidateList
911915
FuncnameGetCandidates(List *names, int nargs, List *argnames,
912-
bool expand_variadic, bool expand_defaults)
916+
bool expand_variadic, bool expand_defaults,
917+
bool missing_ok)
913918
{
914919
FuncCandidateList resultList = NULL;
915920
bool any_special = false;
@@ -928,7 +933,9 @@ FuncnameGetCandidates(List *names, int nargs, List *argnames,
928933
if (schemaname)
929934
{
930935
/* use exact schema given */
931-
namespaceId = LookupExplicitNamespace(schemaname, false);
936+
namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
937+
if (!OidIsValid(namespaceId))
938+
return NULL;
932939
}
933940
else
934941
{
@@ -1414,7 +1421,7 @@ FunctionIsVisible(Oid funcid)
14141421
visible = false;
14151422

14161423
clist = FuncnameGetCandidates(list_make1(makeString(proname)),
1417-
nargs, NIL, false, false);
1424+
nargs, NIL, false, false, false);
14181425

14191426
for (; clist; clist = clist->next)
14201427
{
@@ -1443,7 +1450,8 @@ FunctionIsVisible(Oid funcid)
14431450
* a postfix op.
14441451
*
14451452
* If the operator name is not schema-qualified, it is sought in the current
1446-
* namespace search path.
1453+
* namespace search path. If the name is schema-qualified and the given
1454+
* schema does not exist, InvalidOid is returned.
14471455
*/
14481456
Oid
14491457
OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
@@ -1460,21 +1468,26 @@ OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
14601468
{
14611469
/* search only in exact schema given */
14621470
Oid namespaceId;
1463-
HeapTuple opertup;
14641471

1465-
namespaceId = LookupExplicitNamespace(schemaname, false);
1466-
opertup = SearchSysCache4(OPERNAMENSP,
1467-
CStringGetDatum(opername),
1468-
ObjectIdGetDatum(oprleft),
1469-
ObjectIdGetDatum(oprright),
1470-
ObjectIdGetDatum(namespaceId));
1471-
if (HeapTupleIsValid(opertup))
1472+
namespaceId = LookupExplicitNamespace(schemaname, true);
1473+
if (OidIsValid(namespaceId))
14721474
{
1473-
Oid result = HeapTupleGetOid(opertup);
1475+
HeapTuple opertup;
1476+
1477+
opertup = SearchSysCache4(OPERNAMENSP,
1478+
CStringGetDatum(opername),
1479+
ObjectIdGetDatum(oprleft),
1480+
ObjectIdGetDatum(oprright),
1481+
ObjectIdGetDatum(namespaceId));
1482+
if (HeapTupleIsValid(opertup))
1483+
{
1484+
Oid result = HeapTupleGetOid(opertup);
14741485

1475-
ReleaseSysCache(opertup);
1476-
return result;
1486+
ReleaseSysCache(opertup);
1487+
return result;
1488+
}
14771489
}
1490+
14781491
return InvalidOid;
14791492
}
14801493

@@ -1729,7 +1742,7 @@ OperatorIsVisible(Oid oprid)
17291742
* If it is in the path, it might still not be visible; it could be
17301743
* hidden by another operator of the same name and arguments earlier
17311744
* in the path. So we must do a slow check to see if this is the same
1732-
* operator that would be found by OpernameGetOprId.
1745+
* operator that would be found by OpernameGetOprid.
17331746
*/
17341747
char *oprname = NameStr(oprform->oprname);
17351748

src/backend/catalog/objectaddress.c

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -450,17 +450,28 @@ static void getRelationIdentity(StringInfo buffer, Oid relid);
450450
* sub-object is looked up, the parent object will be locked instead.
451451
*
452452
* If the object is a relation or a child object of a relation (e.g. an
453-
* attribute or contraint), the relation is also opened and *relp receives
453+
* attribute or constraint), the relation is also opened and *relp receives
454454
* the open relcache entry pointer; otherwise, *relp is set to NULL. This
455455
* is a bit grotty but it makes life simpler, since the caller will
456456
* typically need the relcache entry too. Caller must close the relcache
457457
* entry when done with it. The relation is locked with the specified lockmode
458458
* if the target object is the relation itself or an attribute, but for other
459459
* child objects, only AccessShareLock is acquired on the relation.
460460
*
461+
* If the object is not found, an error is thrown, unless missing_ok is
462+
* true. In this case, no lock is acquired, relp is set to NULL, and the
463+
* returned address has objectId set to InvalidOid.
464+
*
461465
* We don't currently provide a function to release the locks acquired here;
462466
* typically, the lock must be held until commit to guard against a concurrent
463467
* drop operation.
468+
*
469+
* Note: If the object is not found, we don't give any indication of the
470+
* reason. (It might have been a missing schema if the name was qualified, or
471+
* an inexistant type name in case of a cast, function or operator; etc).
472+
* Currently there is only one caller that might be interested in such info, so
473+
* we don't spend much effort here. If more callers start to care, it might be
474+
* better to add some support for that in this function.
464475
*/
465476
ObjectAddress
466477
get_object_address(ObjectType objtype, List *objname, List *objargs,
@@ -580,9 +591,11 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
580591
{
581592
TypeName *sourcetype = (TypeName *) linitial(objname);
582593
TypeName *targettype = (TypeName *) linitial(objargs);
583-
Oid sourcetypeid = typenameTypeId(NULL, sourcetype);
584-
Oid targettypeid = typenameTypeId(NULL, targettype);
594+
Oid sourcetypeid;
595+
Oid targettypeid;
585596

597+
sourcetypeid = LookupTypeNameOid(NULL, sourcetype, missing_ok);
598+
targettypeid = LookupTypeNameOid(NULL, targettype, missing_ok);
586599
address.classId = CastRelationId;
587600
address.objectId =
588601
get_cast_oid(sourcetypeid, targettypeid, missing_ok);
@@ -942,26 +955,31 @@ get_object_address_relobject(ObjectType objtype, List *objname,
942955

943956
/* Extract relation name and open relation. */
944957
relname = list_truncate(list_copy(objname), nnames - 1);
945-
relation = heap_openrv(makeRangeVarFromNameList(relname),
946-
AccessShareLock);
947-
reloid = RelationGetRelid(relation);
958+
relation = heap_openrv_extended(makeRangeVarFromNameList(relname),
959+
AccessShareLock,
960+
missing_ok);
961+
962+
reloid = relation ? RelationGetRelid(relation) : InvalidOid;
948963

949964
switch (objtype)
950965
{
951966
case OBJECT_RULE:
952967
address.classId = RewriteRelationId;
953-
address.objectId = get_rewrite_oid(reloid, depname, missing_ok);
968+
address.objectId = relation ?
969+
get_rewrite_oid(reloid, depname, missing_ok) : InvalidOid;
954970
address.objectSubId = 0;
955971
break;
956972
case OBJECT_TRIGGER:
957973
address.classId = TriggerRelationId;
958-
address.objectId = get_trigger_oid(reloid, depname, missing_ok);
974+
address.objectId = relation ?
975+
get_trigger_oid(reloid, depname, missing_ok) : InvalidOid;
959976
address.objectSubId = 0;
960977
break;
961978
case OBJECT_CONSTRAINT:
962979
address.classId = ConstraintRelationId;
963-
address.objectId =
964-
get_relation_constraint_oid(reloid, depname, missing_ok);
980+
address.objectId = relation ?
981+
get_relation_constraint_oid(reloid, depname, missing_ok) :
982+
InvalidOid;
965983
address.objectSubId = 0;
966984
break;
967985
default:
@@ -975,7 +993,9 @@ get_object_address_relobject(ObjectType objtype, List *objname,
975993
/* Avoid relcache leak when object not found. */
976994
if (!OidIsValid(address.objectId))
977995
{
978-
heap_close(relation, AccessShareLock);
996+
if (relation != NULL)
997+
heap_close(relation, AccessShareLock);
998+
979999
relation = NULL; /* department of accident prevention */
9801000
return address;
9811001
}
@@ -1008,6 +1028,7 @@ get_object_address_attribute(ObjectType objtype, List *objname,
10081028
errmsg("column name must be qualified")));
10091029
attname = strVal(lfirst(list_tail(objname)));
10101030
relname = list_truncate(list_copy(objname), list_length(objname) - 1);
1031+
/* XXX no missing_ok support here */
10111032
relation = relation_openrv(makeRangeVarFromNameList(relname), lockmode);
10121033
reloid = RelationGetRelid(relation);
10131034

@@ -1053,7 +1074,7 @@ get_object_address_type(ObjectType objtype,
10531074
address.objectId = InvalidOid;
10541075
address.objectSubId = 0;
10551076

1056-
tup = LookupTypeName(NULL, typename, NULL);
1077+
tup = LookupTypeName(NULL, typename, NULL, missing_ok);
10571078
if (!HeapTupleIsValid(tup))
10581079
{
10591080
if (!missing_ok)
@@ -1090,6 +1111,7 @@ get_object_address_opcf(ObjectType objtype,
10901111
ObjectAddress address;
10911112

10921113
Assert(list_length(objargs) == 1);
1114+
/* XXX no missing_ok support here */
10931115
amoid = get_am_oid(strVal(linitial(objargs)), false);
10941116

10951117
switch (objtype)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy