Hello.

When I created an event trigger for ddl_command_end, I think the only
means to identify for what the trigger function is called is
pg_event_trigger_ddl_commands() so I wrote as the following function
and defined an event trigger for ddl_command_end.

CREATE OR REPLACE FUNCTION hoge() RETURNS event_trigger AS $$
DECLARE
  cmd record =  pg_event_trigger_ddl_commands();
BEGIN
  RAISE NOTICE '"%" "%" "%"',
        cmd.command_tag, cmd.object_type, cmd.object_identity;
END
$$ LANGUAGE plpgsql;

CREATE EVENT TRIGGER hoge_trigger ON ddl_command_end EXECUTE FUNCTION hoge();

Finally I got an ERROR while DROP.

=# CREATE TABLE t (a int);
NOTICE:  "CREATE TABLE" "table" "public.t"
CREATE TABLE
postgres=# DROP TABLE t;
ERROR:  record "cmd" is not assigned yet
DETAIL:  The tuple structure of a not-yet-assigned record is indeterminate.
CONTEXT:  PL/pgSQL function hoge() line 5 at RAISE

The function doesn't return a record for DROP statements.

The documentation is written as the follows:

https://postgresql.org/docs/current/event-trigger-definition.html
> The ddl_command_end event occurs just after the execution of this same
> set of commands. To obtain more details on the DDL operations that
> took place, use the set-returning function
> pg_event_trigger_ddl_commands() from the ddl_command_end event trigger
> code (see Section 9.28). Note that the trigger fires after the actions
> have taken place (but before the transaction commits), and thus the
> system catalogs can be read as already changed.

So I think at least pg_event_trigger_ddl_command must return a record
for all commands that trigger ddl_command_end and the record should
have the correct command_tag.  DROP TABLE is currently classified as
supporting event trigger.  If we don't do that, any workaround and
documentation is needed.

I may be missing something, andt any opinions, thoughts or suggestions
are welcome.

regards.

-- 
Kyotaro Horiguchi
NTT Open Source Software Center
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index 91800d1fac..8376ce429b 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -1939,7 +1939,8 @@ pg_event_trigger_ddl_commands(PG_FUNCTION_ARGS)
 		 * state anyway.
 		 */
 		if (cmd->type == SCT_Simple &&
-			!OidIsValid(cmd->d.simple.address.objectId))
+			!OidIsValid(cmd->d.simple.address.objectId) &&
+			!IsA(cmd->parsetree, DropStmt))
 			continue;
 
 		MemSet(nulls, 0, sizeof(nulls));
@@ -1952,8 +1953,8 @@ pg_event_trigger_ddl_commands(PG_FUNCTION_ARGS)
 			case SCT_CreateOpClass:
 			case SCT_AlterTSConfig:
 				{
-					char	   *identity;
-					char	   *type;
+					char	   *identity = NULL;
+					char	   *type = NULL;
 					char	   *schema = NULL;
 
 					if (cmd->type == SCT_Simple)
@@ -1969,8 +1970,12 @@ pg_event_trigger_ddl_commands(PG_FUNCTION_ARGS)
 					else if (cmd->type == SCT_AlterTSConfig)
 						addr = cmd->d.atscfg.address;
 
-					type = getObjectTypeDescription(&addr);
-					identity = getObjectIdentity(&addr);
+					if (memcmp(&addr, &InvalidObjectAddress,
+							   sizeof(ObjectAddress)) != 0)
+					{
+						type = getObjectTypeDescription(&addr);
+						identity = getObjectIdentity(&addr);
+					}
 
 					/*
 					 * Obtain schema name, if any ("pg_temp" if a temp
@@ -2023,14 +2028,20 @@ pg_event_trigger_ddl_commands(PG_FUNCTION_ARGS)
 					/* command tag */
 					values[i++] = CStringGetTextDatum(CreateCommandName(cmd->parsetree));
 					/* object_type */
-					values[i++] = CStringGetTextDatum(type);
+					if (type != NULL)
+						values[i++] = CStringGetTextDatum(type);
+					else
+						nulls[i++] = true;
 					/* schema */
 					if (schema == NULL)
 						nulls[i++] = true;
 					else
 						values[i++] = CStringGetTextDatum(schema);
 					/* identity */
-					values[i++] = CStringGetTextDatum(identity);
+					if (identity != NULL)
+						values[i++] = CStringGetTextDatum(identity);
+					else
+						nulls[i++] = true;
 					/* in_extension */
 					values[i++] = BoolGetDatum(cmd->in_extension);
 					/* command */
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index b1f7f6e2d0..3b801d279a 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -1686,8 +1686,8 @@ ProcessUtilitySlow(ParseState *pstate,
 
 			case T_DropStmt:
 				ExecDropStmt((DropStmt *) parsetree, isTopLevel);
-				/* no commands stashed for DROP */
-				commandCollected = true;
+				/* Dropped object is not available */
+				address =  InvalidObjectAddress;
 				break;
 
 			case T_RenameStmt:

Reply via email to