Alvaro Herrera <alvhe...@2ndquadrant.com> writes:
> The bigger change I mentioned was the stuff in dependency.c -- I wasn't
> too happy about exposing the whole ObjectAddresses stuff to the outside
> world.  The attached version only exposes simple accessors to let an
> external user of that to iterate on such arrays.  Some more commentary
> is probably needed on those new functions.  Also, if we're going to
> extend things in this way we probably need to get "extra" out alongside
> the object array itself.

Thanks for that.

I added some comments on those new functions, and made it so that we
call get_object_addresses_numelements() only once per loop rather than
at each step in the loop. See attached.

> A larger issue with the patch is handling of subxacts.  A quick test
> doesn't reveal any obvious misbehavior, but having the list of objects
> dropped by a global variable might be problematic.  What if, say, the
> event trigger function does something funny in an EXCEPTION block and it
> fails?  Some clever test case is needed here, I think.  Also, if we
> reset the variable at EOXact, do we also need to do something at
> EOSubXact?

Now that you mention it, the case I'd be worried about is:

  BEGIN;
   SAVEPOINT a;
   DROP TABLE foo;
   ROLLBACK TO SAVEPOINT a;
   DROP TABLE bar;
  COMMIT;

As we currently have no support for on-commit triggers or the like, the
user function is going to run "as part" of the DROP TABLE foo; command,
and its effects are all going to disappear at the next ROLLBACK TO
SAVEPOINT anyway.

If the event trigger user function fails in an EXCEPTION block, I
suppose that the whole transaction is going to get a ROLLBACK, which
will call AbortTransaction() or CleanupTransaction(), which will reset
the static variable EventTriggerSQLDropInProgress. And the list itself
is gone away with the memory context reset.

I think the only missing detail is to force EventTriggerSQLDropList back
to NULL from within AtEOXact_EventTrigger(), and I've done so in the
attached. As we're only looking at the list when the protecting boolean
is true, I don't think it's offering anything else than clarity, which
makes it worthwile already.

You will find both the patch-on-top-of-your-patch (named .2.b) and the
new whole patch attached (named .3), as it makes things way easier IME.

Regards,
-- 
Dimitri Fontaine
http://2ndQuadrant.fr     PostgreSQL : Expertise, Formation et Support

diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index 6f95f50..3732fc8 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -2152,12 +2152,24 @@ record_object_address_dependencies(const ObjectAddress *depender,
 							   behavior);
 }
 
+/*
+ * get_object_addresses_numelements
+ *
+ * Return the number of object addresses in the given ObjectAddresses, allowing
+ * external modules to loop over the array.
+ */
 int
 get_object_addresses_numelements(const ObjectAddresses *addresses)
 {
 	return addresses->numrefs;
 }
 
+/*
+ * get_object_addresses_element
+ *
+ * Return the ObjectAddress at position i, allowing to fetch it from an
+ * external module.
+ */
 ObjectAddress *
 get_object_addresses_element(const ObjectAddresses *addresses, int i)
 {
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index 9ed5715..4e112af 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -862,6 +862,8 @@ AtEOXact_EventTrigger(bool isCommit)
 {
 	/* even on success we want to reset EventTriggerSQLDropInProgress */
 	EventTriggerSQLDropInProgress = false;
+	/* the list is palloc()ed and has already been taken care of */
+	EventTriggerSQLDropList = NULL;
 }
 
 /*
@@ -878,7 +880,7 @@ pg_event_trigger_dropped_objects(PG_FUNCTION_ARGS)
 	Tuplestorestate		*tupstore;
 	MemoryContext		 per_query_ctx;
 	MemoryContext		 oldcontext;
-	int					 i;
+	int					 i, n;
 
 	/*
 	 * This function is meant to be called from within an event trigger in
@@ -914,7 +916,10 @@ pg_event_trigger_dropped_objects(PG_FUNCTION_ARGS)
 
 	MemoryContextSwitchTo(oldcontext);
 
-	for (i = 0; i < get_object_addresses_numelements(EventTriggerSQLDropList); i++)
+	/* only call the get_object_addresses_numelements accessor function once */
+	n = get_object_addresses_numelements(EventTriggerSQLDropList);
+
+	for (i = 0; i < n; i++)
 	{
 		ObjectAddress *object;
 		Datum		values[3];

Attachment: dropped_objects.3.patch.gz
Description: Binary data

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to