Hello
here is patch with fault tolerant drop trigger and drop rule support
drop trigger [if exists] trgname on [if exists] tablename;
drop rule [if exists] trgname on [if exists] tablename;
Regards
Pavel
2013/11/11 Pavel Stehule <[email protected]>
>
>
>
> 2013/11/11 Tom Lane <[email protected]>
>
>> Andres Freund <[email protected]> writes:
>> > Turns out that's bogus - ALTER TABLE has two levels of NOT EXISTS.
>>
>> > Maybe we should just do the same for DROP TRIGGER?
>>
>> > DROP TRIGGER [ IF EXISTS ] name ON table_name [ IF EXISTS ] [ CASCADE |
>> RESTRICT ]
>>
>> Works for me.
>>
>
> for me too
>
> tomorrow I'll prepare patch
>
> Regards
>
> Pavel
>
>
>>
>> regards, tom lane
>>
>>
>> --
>> Sent via pgsql-hackers mailing list ([email protected])
>> To make changes to your subscription:
>> http://www.postgresql.org/mailpref/pgsql-hackers
>>
>
>
diff --git a/doc/src/sgml/ref/drop_rule.sgml b/doc/src/sgml/ref/drop_rule.sgml
index c845872..585f67b 100644
--- a/doc/src/sgml/ref/drop_rule.sgml
+++ b/doc/src/sgml/ref/drop_rule.sgml
@@ -21,7 +21,7 @@ PostgreSQL documentation
<refsynopsisdiv>
<synopsis>
-DROP RULE [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> ON <replaceable class="PARAMETER">table_name</replaceable> [ CASCADE | RESTRICT ]
+DROP RULE [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> ON [ IF EXISTS ] <replaceable class="PARAMETER">table_name</replaceable> [ CASCADE | RESTRICT ]
</synopsis>
</refsynopsisdiv>
@@ -42,8 +42,8 @@ DROP RULE [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> ON <re
<term><literal>IF EXISTS</literal></term>
<listitem>
<para>
- Do not throw an error if the rule does not exist. A notice is issued
- in this case.
+ Do not throw an error if the rule does not exist (or if a parent table
+ does not exist). A notice is issued in this case.
</para>
</listitem>
</varlistentry>
diff --git a/doc/src/sgml/ref/drop_trigger.sgml b/doc/src/sgml/ref/drop_trigger.sgml
index 3ec6cc7..1f46eff 100644
--- a/doc/src/sgml/ref/drop_trigger.sgml
+++ b/doc/src/sgml/ref/drop_trigger.sgml
@@ -21,7 +21,7 @@ PostgreSQL documentation
<refsynopsisdiv>
<synopsis>
-DROP TRIGGER [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> ON <replaceable class="PARAMETER">table_name</replaceable> [ CASCADE | RESTRICT ]
+DROP TRIGGER [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> ON [ IF EXISTS ] <replaceable class="PARAMETER">table_name</replaceable> [ CASCADE | RESTRICT ]
</synopsis>
</refsynopsisdiv>
@@ -44,8 +44,8 @@ DROP TRIGGER [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> ON
<term><literal>IF EXISTS</literal></term>
<listitem>
<para>
- Do not throw an error if the trigger does not exist. A notice is issued
- in this case.
+ Do not throw an error if the trigger does not exist (or parent table
+ does not exist). A notice is issued in this case.
</para>
</listitem>
</varlistentry>
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index cecddf1..36ef9ae 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -423,7 +423,8 @@ static ObjectAddress get_relation_by_qualified_name(ObjectType objtype,
List *objname, Relation *relp,
LOCKMODE lockmode, bool missing_ok);
static ObjectAddress get_object_address_relobject(ObjectType objtype,
- List *objname, Relation *relp, bool missing_ok);
+ List *objname, Relation *relp,
+ bool missing_ok, bool missing_parent_ok);
static ObjectAddress get_object_address_attribute(ObjectType objtype,
List *objname, Relation *relp,
LOCKMODE lockmode, bool missing_ok);
@@ -464,7 +465,8 @@ static void getRelationIdentity(StringInfo buffer, Oid relid);
*/
ObjectAddress
get_object_address(ObjectType objtype, List *objname, List *objargs,
- Relation *relp, LOCKMODE lockmode, bool missing_ok)
+ Relation *relp, LOCKMODE lockmode,
+ bool missing_ok, bool missing_parent_ok)
{
ObjectAddress address;
ObjectAddress old_address = {InvalidOid, InvalidOid, 0};
@@ -507,7 +509,9 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
case OBJECT_TRIGGER:
case OBJECT_CONSTRAINT:
address = get_object_address_relobject(objtype, objname,
- &relation, missing_ok);
+ &relation,
+ missing_ok,
+ missing_parent_ok);
break;
case OBJECT_DATABASE:
case OBJECT_EXTENSION:
@@ -622,7 +626,7 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
*/
if (!OidIsValid(address.objectId))
{
- Assert(missing_ok);
+ Assert(missing_ok || missing_parent_ok);
return address;
}
@@ -898,7 +902,9 @@ get_relation_by_qualified_name(ObjectType objtype, List *objname,
*/
static ObjectAddress
get_object_address_relobject(ObjectType objtype, List *objname,
- Relation *relp, bool missing_ok)
+ Relation *relp,
+ bool missing_ok,
+ bool missing_parent_ok)
{
ObjectAddress address;
Relation relation = NULL;
@@ -942,42 +948,55 @@ get_object_address_relobject(ObjectType objtype, List *objname,
/* Extract relation name and open relation. */
relname = list_truncate(list_copy(objname), nnames - 1);
- relation = heap_openrv(makeRangeVarFromNameList(relname),
- AccessShareLock);
- reloid = RelationGetRelid(relation);
+ relation = heap_openrv_extended(makeRangeVarFromNameList(relname),
+ AccessShareLock,
+ missing_parent_ok);
- switch (objtype)
+ if (relation != NULL)
{
- case OBJECT_RULE:
- address.classId = RewriteRelationId;
- address.objectId = get_rewrite_oid(reloid, depname, missing_ok);
- address.objectSubId = 0;
- break;
- case OBJECT_TRIGGER:
- address.classId = TriggerRelationId;
- address.objectId = get_trigger_oid(reloid, depname, missing_ok);
- address.objectSubId = 0;
- break;
- case OBJECT_CONSTRAINT:
- address.classId = ConstraintRelationId;
- address.objectId =
- get_relation_constraint_oid(reloid, depname, missing_ok);
- address.objectSubId = 0;
- break;
- default:
- elog(ERROR, "unrecognized objtype: %d", (int) objtype);
- /* placate compiler, which doesn't know elog won't return */
- address.classId = InvalidOid;
- address.objectId = InvalidOid;
- address.objectSubId = 0;
- }
+ reloid = RelationGetRelid(relation);
- /* Avoid relcache leak when object not found. */
- if (!OidIsValid(address.objectId))
+ switch (objtype)
+ {
+ case OBJECT_RULE:
+ address.classId = RewriteRelationId;
+ address.objectId = get_rewrite_oid(reloid, depname, missing_ok);
+ address.objectSubId = 0;
+ break;
+ case OBJECT_TRIGGER:
+ address.classId = TriggerRelationId;
+ address.objectId = get_trigger_oid(reloid, depname, missing_ok);
+ address.objectSubId = 0;
+ break;
+ case OBJECT_CONSTRAINT:
+ address.classId = ConstraintRelationId;
+ address.objectId =
+ get_relation_constraint_oid(reloid, depname, missing_ok);
+ address.objectSubId = 0;
+ break;
+ default:
+ elog(ERROR, "unrecognized objtype: %d", (int) objtype);
+ /* placate compiler, which doesn't know elog won't return */
+ address.classId = InvalidOid;
+ address.objectId = InvalidOid;
+ address.objectSubId = 0;
+ }
+
+ /* Avoid relcache leak when object not found. */
+ if (!OidIsValid(address.objectId))
+ {
+ heap_close(relation, AccessShareLock);
+ relation = NULL; /* department of accident prevention */
+ return address;
+ }
+ }
+ else
{
- heap_close(relation, AccessShareLock);
- relation = NULL; /* department of accident prevention */
- return address;
+ Assert(missing_parent_ok);
+
+ address.classId = InvalidOid;
+ address.objectId = InvalidOid;
+ address.objectSubId = 0;
}
}
diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c
index b62ec70..04e1481 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -364,7 +364,8 @@ ExecRenameStmt(RenameStmt *stmt)
address = get_object_address(stmt->renameType,
stmt->object, stmt->objarg,
&relation,
- AccessExclusiveLock, false);
+ AccessExclusiveLock,
+ false, false);
Assert(relation == NULL);
catalog = heap_open(address.classId, RowExclusiveLock);
@@ -431,6 +432,7 @@ ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
stmt->objarg,
&relation,
AccessExclusiveLock,
+ false,
false);
Assert(relation == NULL);
classId = address.classId;
@@ -725,6 +727,7 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
stmt->objarg,
&relation,
AccessExclusiveLock,
+ false,
false);
Assert(relation == NULL);
classId = address.classId;
diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c
index 5ecc92a..5b77e87 100644
--- a/src/backend/commands/comment.c
+++ b/src/backend/commands/comment.c
@@ -71,7 +71,8 @@ CommentObject(CommentStmt *stmt)
* against concurrent DROP operations.
*/
address = get_object_address(stmt->objtype, stmt->objname, stmt->objargs,
- &relation, ShareUpdateExclusiveLock, false);
+ &relation, ShareUpdateExclusiveLock,
+ false, false);
/* Require ownership of the target object. */
check_object_ownership(GetUserId(), stmt->objtype, address,
diff --git a/src/backend/commands/dropcmds.c b/src/backend/commands/dropcmds.c
index b32ad3a..4529727 100644
--- a/src/backend/commands/dropcmds.c
+++ b/src/backend/commands/dropcmds.c
@@ -31,6 +31,8 @@
static void does_not_exist_skipping(ObjectType objtype,
List *objname, List *objargs);
+static void parent_not_exists_skipping(ObjectType objtype,
+ List *objname);
/*
* Drop one or more objects.
@@ -71,12 +73,17 @@ RemoveObjects(DropStmt *stmt)
objname, objargs,
&relation,
AccessExclusiveLock,
- stmt->missing_ok);
+ stmt->missing_ok,
+ stmt->missing_parent_ok);
/* Issue NOTICE if supplied object was not found. */
if (!OidIsValid(address.objectId))
{
- does_not_exist_skipping(stmt->removeType, objname, objargs);
+ /* ObjectId can be invalid due missing parent relation */
+ if (stmt->missing_parent_ok && !OidIsValid(address.classId))
+ parent_not_exists_skipping(stmt->removeType, objname);
+ else
+ does_not_exist_skipping(stmt->removeType, objname, objargs);
continue;
}
@@ -244,3 +251,25 @@ does_not_exist_skipping(ObjectType objtype, List *objname, List *objargs)
else
ereport(NOTICE, (errmsg(msg, name, args)));
}
+
+/*
+ * Generate a NOTICE "table does not exists, skipping". It is used when
+ * clause IF EXISTS is twice used.
+ */
+static void
+parent_not_exists_skipping(ObjectType objtype, List *objname)
+{
+ switch (objtype)
+ {
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ ereport(NOTICE,
+ (errmsg("table \%s\" does not exists, skipping",
+ NameListToString(list_truncate(list_copy(objname),
+ list_length(objname) - 1)))));
+ break;
+ default:
+ elog(ERROR, "unexpected object type (%d)", (int) objtype);
+ break;
+ }
+}
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 798c92a..83a6d92 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -2908,7 +2908,8 @@ ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt)
* against concurrent DROP and ALTER EXTENSION ADD/DROP operations.
*/
object = get_object_address(stmt->objtype, stmt->objname, stmt->objargs,
- &relation, ShareUpdateExclusiveLock, false);
+ &relation, ShareUpdateExclusiveLock,
+ false, false);
/* Permission check: must own target object, too */
check_object_ownership(GetUserId(), stmt->objtype, object,
diff --git a/src/backend/commands/seclabel.c b/src/backend/commands/seclabel.c
index eaf0d0d..115c395 100644
--- a/src/backend/commands/seclabel.c
+++ b/src/backend/commands/seclabel.c
@@ -88,7 +88,8 @@ ExecSecLabelStmt(SecLabelStmt *stmt)
* guard against concurrent modifications.
*/
address = get_object_address(stmt->objtype, stmt->objname, stmt->objargs,
- &relation, ShareUpdateExclusiveLock, false);
+ &relation, ShareUpdateExclusiveLock,
+ false, false);
/* Require ownership of the target object. */
check_object_ownership(GetUserId(), stmt->objtype, address,
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 1733da6..a8c5b85 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -2798,6 +2798,7 @@ _copyDropStmt(const DropStmt *from)
COPY_SCALAR_FIELD(removeType);
COPY_SCALAR_FIELD(behavior);
COPY_SCALAR_FIELD(missing_ok);
+ COPY_SCALAR_FIELD(missing_parent_ok);
COPY_SCALAR_FIELD(concurrent);
return newnode;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 7b29812..7fe85fb 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1137,6 +1137,7 @@ _equalDropStmt(const DropStmt *a, const DropStmt *b)
COMPARE_SCALAR_FIELD(removeType);
COMPARE_SCALAR_FIELD(behavior);
COMPARE_SCALAR_FIELD(missing_ok);
+ COMPARE_SCALAR_FIELD(missing_parent_ok);
COMPARE_SCALAR_FIELD(concurrent);
return true;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 8dc4b1c..2fb9388 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -3546,6 +3546,7 @@ DropPLangStmt:
n->arguments = NIL;
n->behavior = $5;
n->missing_ok = false;
+ n->missing_parent_ok = false;
n->concurrent = false;
$$ = (Node *)n;
}
@@ -3556,6 +3557,7 @@ DropPLangStmt:
n->objects = list_make1(list_make1(makeString($6)));
n->behavior = $7;
n->missing_ok = true;
+ n->missing_parent_ok = false;
n->concurrent = false;
$$ = (Node *)n;
}
@@ -3969,6 +3971,7 @@ DropFdwStmt: DROP FOREIGN DATA_P WRAPPER name opt_drop_behavior
n->objects = list_make1(list_make1(makeString($5)));
n->arguments = NIL;
n->missing_ok = false;
+ n->missing_parent_ok = false;
n->behavior = $6;
n->concurrent = false;
$$ = (Node *) n;
@@ -3980,6 +3983,7 @@ DropFdwStmt: DROP FOREIGN DATA_P WRAPPER name opt_drop_behavior
n->objects = list_make1(list_make1(makeString($7)));
n->arguments = NIL;
n->missing_ok = true;
+ n->missing_parent_ok = false;
n->behavior = $8;
n->concurrent = false;
$$ = (Node *) n;
@@ -4131,6 +4135,7 @@ DropForeignServerStmt: DROP SERVER name opt_drop_behavior
n->objects = list_make1(list_make1(makeString($3)));
n->arguments = NIL;
n->missing_ok = false;
+ n->missing_parent_ok = false;
n->behavior = $4;
n->concurrent = false;
$$ = (Node *) n;
@@ -4142,6 +4147,7 @@ DropForeignServerStmt: DROP SERVER name opt_drop_behavior
n->objects = list_make1(list_make1(makeString($5)));
n->arguments = NIL;
n->missing_ok = true;
+ n->missing_parent_ok = false;
n->behavior = $6;
n->concurrent = false;
$$ = (Node *) n;
@@ -4512,6 +4518,7 @@ DropTrigStmt:
n->arguments = NIL;
n->behavior = $6;
n->missing_ok = false;
+ n->missing_parent_ok = false;
n->concurrent = false;
$$ = (Node *) n;
}
@@ -4523,6 +4530,31 @@ DropTrigStmt:
n->arguments = NIL;
n->behavior = $8;
n->missing_ok = true;
+ n->missing_parent_ok = false;
+ n->concurrent = false;
+ $$ = (Node *) n;
+ }
+ | DROP TRIGGER name ON IF_P EXISTS any_name opt_drop_behavior
+ {
+ DropStmt *n = makeNode(DropStmt);
+ n->removeType = OBJECT_TRIGGER;
+ n->objects = list_make1(lappend($7, makeString($3)));
+ n->arguments = NIL;
+ n->behavior = $8;
+ n->missing_ok = false;
+ n->missing_parent_ok = true;
+ n->concurrent = false;
+ $$ = (Node *) n;
+ }
+ | DROP TRIGGER IF_P EXISTS name ON IF_P EXISTS any_name opt_drop_behavior
+ {
+ DropStmt *n = makeNode(DropStmt);
+ n->removeType = OBJECT_TRIGGER;
+ n->objects = list_make1(lappend($9, makeString($5)));
+ n->arguments = NIL;
+ n->behavior = $10;
+ n->missing_ok = true;
+ n->missing_parent_ok = true;
n->concurrent = false;
$$ = (Node *) n;
}
@@ -5055,6 +5087,7 @@ DropOpClassStmt:
n->removeType = OBJECT_OPCLASS;
n->behavior = $7;
n->missing_ok = false;
+ n->missing_parent_ok = false;
n->concurrent = false;
$$ = (Node *) n;
}
@@ -5066,6 +5099,7 @@ DropOpClassStmt:
n->removeType = OBJECT_OPCLASS;
n->behavior = $9;
n->missing_ok = true;
+ n->missing_parent_ok = false;
n->concurrent = false;
$$ = (Node *) n;
}
@@ -5080,6 +5114,7 @@ DropOpFamilyStmt:
n->removeType = OBJECT_OPFAMILY;
n->behavior = $7;
n->missing_ok = false;
+ n->missing_parent_ok = false;
n->concurrent = false;
$$ = (Node *) n;
}
@@ -5091,6 +5126,7 @@ DropOpFamilyStmt:
n->removeType = OBJECT_OPFAMILY;
n->behavior = $9;
n->missing_ok = true;
+ n->missing_parent_ok = false;
n->concurrent = false;
$$ = (Node *) n;
}
@@ -5139,6 +5175,7 @@ DropStmt: DROP drop_type IF_P EXISTS any_name_list opt_drop_behavior
DropStmt *n = makeNode(DropStmt);
n->removeType = $2;
n->missing_ok = TRUE;
+ n->missing_parent_ok = false;
n->objects = $5;
n->arguments = NIL;
n->behavior = $6;
@@ -5150,6 +5187,7 @@ DropStmt: DROP drop_type IF_P EXISTS any_name_list opt_drop_behavior
DropStmt *n = makeNode(DropStmt);
n->removeType = $2;
n->missing_ok = FALSE;
+ n->missing_parent_ok = false;
n->objects = $3;
n->arguments = NIL;
n->behavior = $4;
@@ -5161,6 +5199,7 @@ DropStmt: DROP drop_type IF_P EXISTS any_name_list opt_drop_behavior
DropStmt *n = makeNode(DropStmt);
n->removeType = OBJECT_INDEX;
n->missing_ok = FALSE;
+ n->missing_parent_ok = false;
n->objects = $4;
n->arguments = NIL;
n->behavior = $5;
@@ -5172,6 +5211,7 @@ DropStmt: DROP drop_type IF_P EXISTS any_name_list opt_drop_behavior
DropStmt *n = makeNode(DropStmt);
n->removeType = OBJECT_INDEX;
n->missing_ok = TRUE;
+ n->missing_parent_ok = false;
n->objects = $6;
n->arguments = NIL;
n->behavior = $7;
@@ -6635,6 +6675,7 @@ RemoveFuncStmt:
n->arguments = list_make1(extractArgTypes($4));
n->behavior = $5;
n->missing_ok = false;
+ n->missing_parent_ok = false;
n->concurrent = false;
$$ = (Node *)n;
}
@@ -6646,6 +6687,7 @@ RemoveFuncStmt:
n->arguments = list_make1(extractArgTypes($6));
n->behavior = $7;
n->missing_ok = true;
+ n->missing_parent_ok = false;
n->concurrent = false;
$$ = (Node *)n;
}
@@ -6660,6 +6702,7 @@ RemoveAggrStmt:
n->arguments = list_make1(extractArgTypes($4));
n->behavior = $5;
n->missing_ok = false;
+ n->missing_parent_ok = false;
n->concurrent = false;
$$ = (Node *)n;
}
@@ -6671,6 +6714,7 @@ RemoveAggrStmt:
n->arguments = list_make1(extractArgTypes($6));
n->behavior = $7;
n->missing_ok = true;
+ n->missing_parent_ok = false;
n->concurrent = false;
$$ = (Node *)n;
}
@@ -6685,6 +6729,7 @@ RemoveOperStmt:
n->arguments = list_make1($4);
n->behavior = $5;
n->missing_ok = false;
+ n->missing_parent_ok = false;
n->concurrent = false;
$$ = (Node *)n;
}
@@ -6696,6 +6741,7 @@ RemoveOperStmt:
n->arguments = list_make1($6);
n->behavior = $7;
n->missing_ok = true;
+ n->missing_parent_ok = false;
n->concurrent = false;
$$ = (Node *)n;
}
@@ -6813,6 +6859,7 @@ DropCastStmt: DROP CAST opt_if_exists '(' Typename AS Typename ')' opt_drop_beha
n->arguments = list_make1(list_make1($7));
n->behavior = $9;
n->missing_ok = $3;
+ n->missing_parent_ok = false;
n->concurrent = false;
$$ = (Node *)n;
}
@@ -7821,6 +7868,7 @@ DropRuleStmt:
n->arguments = NIL;
n->behavior = $6;
n->missing_ok = false;
+ n->missing_parent_ok = false;
n->concurrent = false;
$$ = (Node *) n;
}
@@ -7832,6 +7880,31 @@ DropRuleStmt:
n->arguments = NIL;
n->behavior = $8;
n->missing_ok = true;
+ n->missing_parent_ok = false;
+ n->concurrent = false;
+ $$ = (Node *) n;
+ }
+ | DROP RULE name ON IF_P EXISTS any_name opt_drop_behavior
+ {
+ DropStmt *n = makeNode(DropStmt);
+ n->removeType = OBJECT_RULE;
+ n->objects = list_make1(lappend($7, makeString($3)));
+ n->arguments = NIL;
+ n->behavior = $8;
+ n->missing_ok = false;
+ n->missing_parent_ok = true;
+ n->concurrent = false;
+ $$ = (Node *) n;
+ }
+ | DROP RULE IF_P EXISTS name ON IF_P EXISTS any_name opt_drop_behavior
+ {
+ DropStmt *n = makeNode(DropStmt);
+ n->removeType = OBJECT_RULE;
+ n->objects = list_make1(lappend($9, makeString($5)));
+ n->arguments = NIL;
+ n->behavior = $10;
+ n->missing_ok = true;
+ n->missing_parent_ok = true;
n->concurrent = false;
$$ = (Node *) n;
}
diff --git a/src/include/catalog/objectaddress.h b/src/include/catalog/objectaddress.h
index e2a5b0d..05f20ff 100644
--- a/src/include/catalog/objectaddress.h
+++ b/src/include/catalog/objectaddress.h
@@ -30,7 +30,8 @@ typedef struct ObjectAddress
extern ObjectAddress get_object_address(ObjectType objtype, List *objname,
List *objargs, Relation *relp,
- LOCKMODE lockmode, bool missing_ok);
+ LOCKMODE lockmode,
+ bool missing_ok, bool missing_parent_ok);
extern void check_object_ownership(Oid roleid,
ObjectType objtype, ObjectAddress address,
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 952fbb3..57178bd 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2003,6 +2003,7 @@ typedef struct DropStmt
ObjectType removeType; /* object type */
DropBehavior behavior; /* RESTRICT or CASCADE behavior */
bool missing_ok; /* skip error if object is missing? */
+ bool missing_parent_ok; /* skip error if parent is missing? */
bool concurrent; /* drop index concurrently? */
} DropStmt;
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 62fc7c5..c688999 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -2630,3 +2630,10 @@ ALTER RULE "_RETURN" ON rule_v1 RENAME TO abc; -- ON SELECT rule cannot be renam
ERROR: renaming an ON SELECT rule is not allowed
DROP VIEW rule_v1;
DROP TABLE rule_t1;
+--
+-- fault tolerant drop rule
+--
+DROP RULE IF EXISTS noexistname ON IF EXISTS noexistname;
+NOTICE: table noexistname" does not exists, skipping
+DROP RULE noexistname ON IF EXISTS noexistname;
+NOTICE: table noexistname" does not exists, skipping
diff --git a/src/test/regress/expected/triggers.out b/src/test/regress/expected/triggers.out
index 6a6ecf7..35622cc 100644
--- a/src/test/regress/expected/triggers.out
+++ b/src/test/regress/expected/triggers.out
@@ -1731,3 +1731,8 @@ select * from self_ref_trigger;
drop table self_ref_trigger;
drop function self_ref_trigger_ins_func();
drop function self_ref_trigger_del_func();
+-- fault tolerant trigger
+drop trigger not_exists_trigger on if exists not_exists_table;
+NOTICE: table not_exists_table" does not exists, skipping
+drop trigger if exists not_exists_trigger on if exists not_exists_table;
+NOTICE: table not_exists_table" does not exists, skipping
diff --git a/src/test/regress/sql/rules.sql b/src/test/regress/sql/rules.sql
index 1e15f84..23e9423 100644
--- a/src/test/regress/sql/rules.sql
+++ b/src/test/regress/sql/rules.sql
@@ -1007,3 +1007,9 @@ ALTER RULE "_RETURN" ON rule_v1 RENAME TO abc; -- ON SELECT rule cannot be renam
DROP VIEW rule_v1;
DROP TABLE rule_t1;
+
+--
+-- fault tolerant drop rule
+--
+DROP RULE IF EXISTS noexistname ON IF EXISTS noexistname;
+DROP RULE noexistname ON IF EXISTS noexistname;
diff --git a/src/test/regress/sql/triggers.sql b/src/test/regress/sql/triggers.sql
index 0ea2c31..6174f95 100644
--- a/src/test/regress/sql/triggers.sql
+++ b/src/test/regress/sql/triggers.sql
@@ -1173,3 +1173,7 @@ select * from self_ref_trigger;
drop table self_ref_trigger;
drop function self_ref_trigger_ins_func();
drop function self_ref_trigger_del_func();
+
+-- fault tolerant trigger
+drop trigger not_exists_trigger on if exists not_exists_table;
+drop trigger if exists not_exists_trigger on if exists not_exists_table;
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers