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: