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: