Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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

+29-16
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

+34-12
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)