bool isTopLevel = (context == PROCESS_UTILITY_TOPLEVEL);
bool isCompleteQuery = (context <= PROCESS_UTILITY_QUERY);
bool needCleanup;
+ bool commandStashed = false;
ObjectAddress address;
+ ObjectAddress secondaryObject = InvalidObjectAddress;
/* All event trigger calls are done only when isCompleteQuery is true */
needCleanup = isCompleteQuery && EventTriggerBeginCompleteQuery();
case T_CreateSchemaStmt:
CreateSchemaCommand((CreateSchemaStmt *) parsetree,
queryString);
+ /*
+ * CreateSchemaCommand calls EventTriggerStashCommand
+ * internally, for reasons explained there, so turn off
+ * command collection below.
+ */
+ commandStashed = true;
break;
case T_CreateStmt:
address = DefineRelation((CreateStmt *) stmt,
RELKIND_RELATION,
InvalidOid, NULL);
+ EventTriggerStashCommand(address, secondaryObject,
+ stmt);
/*
* Let NewRelationCreateToastTable decide if this
InvalidOid, NULL);
CreateForeignTable((CreateForeignTableStmt *) stmt,
address.objectId);
+ EventTriggerStashCommand(address, secondaryObject,
+ stmt);
}
else
{
- /* Recurse for anything else */
+ /*
+ * Recurse for anything else. Note the recursive
+ * call will stash the objects so created into our
+ * event trigger context.
+ */
ProcessUtility(stmt,
queryString,
PROCESS_UTILITY_SUBCOMMAND,
if (lnext(l) != NULL)
CommandCounterIncrement();
}
+
+ /*
+ * The multiple commands generated here are stashed
+ * individually, so disable collection below.
+ */
+ commandStashed = true;
}
break;
(errmsg("relation \"%s\" does not exist, skipping",
atstmt->relation->relname)));
}
+
+ /* ALTER TABLE stashes commands internally */
+ commandStashed = true;
break;
case T_AlterDomainStmt:
* Recursively alter column default for table and,
* if requested, for descendants
*/
- AlterDomainDefault(stmt->typeName,
- stmt->def);
+ address =
+ AlterDomainDefault(stmt->typeName,
+ stmt->def);
break;
case 'N': /* ALTER DOMAIN DROP NOT NULL */
- AlterDomainNotNull(stmt->typeName,
- false);
+ address =
+ AlterDomainNotNull(stmt->typeName,
+ false);
break;
case 'O': /* ALTER DOMAIN SET NOT NULL */
- AlterDomainNotNull(stmt->typeName,
- true);
+ address =
+ AlterDomainNotNull(stmt->typeName,
+ true);
break;
case 'C': /* ADD CONSTRAINT */
- AlterDomainAddConstraint(stmt->typeName,
- stmt->def,
- NULL);
+ address =
+ AlterDomainAddConstraint(stmt->typeName,
+ stmt->def,
+ &secondaryObject);
break;
case 'X': /* DROP CONSTRAINT */
- AlterDomainDropConstraint(stmt->typeName,
- stmt->name,
- stmt->behavior,
- stmt->missing_ok);
+ address =
+ AlterDomainDropConstraint(stmt->typeName,
+ stmt->name,
+ stmt->behavior,
+ stmt->missing_ok);
break;
case 'V': /* VALIDATE CONSTRAINT */
- AlterDomainValidateConstraint(stmt->typeName,
- stmt->name);
+ address =
+ AlterDomainValidateConstraint(stmt->typeName,
+ stmt->name);
break;
default: /* oops */
elog(ERROR, "unrecognized alter domain type: %d",
switch (stmt->kind)
{
case OBJECT_AGGREGATE:
- DefineAggregate(stmt->defnames, stmt->args,
- stmt->oldstyle, stmt->definition,
- queryString);
+ address =
+ DefineAggregate(stmt->defnames, stmt->args,
+ stmt->oldstyle,
+ stmt->definition, queryString);
break;
case OBJECT_OPERATOR:
Assert(stmt->args == NIL);
- DefineOperator(stmt->defnames, stmt->definition);
+ address = DefineOperator(stmt->defnames,
+ stmt->definition);
break;
case OBJECT_TYPE:
Assert(stmt->args == NIL);
- DefineType(stmt->defnames, stmt->definition);
+ address = DefineType(stmt->defnames,
+ stmt->definition);
break;
case OBJECT_TSPARSER:
Assert(stmt->args == NIL);
- DefineTSParser(stmt->defnames, stmt->definition);
+ address = DefineTSParser(stmt->defnames,
+ stmt->definition);
break;
case OBJECT_TSDICTIONARY:
Assert(stmt->args == NIL);
- DefineTSDictionary(stmt->defnames,
- stmt->definition);
+ address = DefineTSDictionary(stmt->defnames,
+ stmt->definition);
break;
case OBJECT_TSTEMPLATE:
Assert(stmt->args == NIL);
- DefineTSTemplate(stmt->defnames,
- stmt->definition);
+ address = DefineTSTemplate(stmt->defnames,
+ stmt->definition);
break;
case OBJECT_TSCONFIGURATION:
Assert(stmt->args == NIL);
- DefineTSConfiguration(stmt->defnames,
- stmt->definition,
- NULL);
+ address = DefineTSConfiguration(stmt->defnames,
+ stmt->definition,
+ &secondaryObject);
break;
case OBJECT_COLLATION:
Assert(stmt->args == NIL);
- DefineCollation(stmt->defnames, stmt->definition);
+ address = DefineCollation(stmt->defnames,
+ stmt->definition);
break;
default:
elog(ERROR, "unrecognized define stmt type: %d",
stmt = transformIndexStmt(relid, stmt, queryString);
/* ... and do it */
- DefineIndex(relid, /* OID of heap relation */
- stmt,
- InvalidOid, /* no predefined OID */
- false, /* is_alter_table */
- true, /* check_rights */
- false, /* skip_build */
- false); /* quiet */
+ address =
+ DefineIndex(relid, /* OID of heap relation */
+ stmt,
+ InvalidOid, /* no predefined OID */
+ false, /* is_alter_table */
+ true, /* check_rights */
+ false, /* skip_build */
+ false); /* quiet */
+ /*
+ * Add the CREATE INDEX node itself to stash right away; if
+ * there were any commands stashed in the ALTER TABLE code,
+ * we need them to appear after this one.
+ */
+ EventTriggerStashCommand(address, secondaryObject,
+ parsetree);
+ commandStashed = true;
}
break;
case T_CreateExtensionStmt:
- CreateExtension((CreateExtensionStmt *) parsetree);
+ address = CreateExtension((CreateExtensionStmt *) parsetree);
break;
case T_AlterExtensionStmt:
- ExecAlterExtensionStmt((AlterExtensionStmt *) parsetree);
+ address = ExecAlterExtensionStmt((AlterExtensionStmt *) parsetree);
break;
case T_AlterExtensionContentsStmt:
- ExecAlterExtensionContentsStmt((AlterExtensionContentsStmt *) parsetree,
- NULL);
+ address = ExecAlterExtensionContentsStmt((AlterExtensionContentsStmt *) parsetree,
+ &secondaryObject);
break;
case T_CreateFdwStmt:
- CreateForeignDataWrapper((CreateFdwStmt *) parsetree);
+ address = CreateForeignDataWrapper((CreateFdwStmt *) parsetree);
break;
case T_AlterFdwStmt:
- AlterForeignDataWrapper((AlterFdwStmt *) parsetree);
+ address = AlterForeignDataWrapper((AlterFdwStmt *) parsetree);
break;
case T_CreateForeignServerStmt:
- CreateForeignServer((CreateForeignServerStmt *) parsetree);
+ address = CreateForeignServer((CreateForeignServerStmt *) parsetree);
break;
case T_AlterForeignServerStmt:
- AlterForeignServer((AlterForeignServerStmt *) parsetree);
+ address = AlterForeignServer((AlterForeignServerStmt *) parsetree);
break;
case T_CreateUserMappingStmt:
- CreateUserMapping((CreateUserMappingStmt *) parsetree);
+ address = CreateUserMapping((CreateUserMappingStmt *) parsetree);
break;
case T_AlterUserMappingStmt:
- AlterUserMapping((AlterUserMappingStmt *) parsetree);
+ address = AlterUserMapping((AlterUserMappingStmt *) parsetree);
break;
case T_DropUserMappingStmt:
RemoveUserMapping((DropUserMappingStmt *) parsetree);
+ /* no commands stashed for DROP */
+ commandStashed = true;
break;
case T_ImportForeignSchemaStmt:
ImportForeignSchema((ImportForeignSchemaStmt *) parsetree);
+ /* commands are stashed inside ImportForeignSchema */
+ commandStashed = true;
break;
case T_CompositeTypeStmt: /* CREATE TYPE (composite) */
{
CompositeTypeStmt *stmt = (CompositeTypeStmt *) parsetree;
- DefineCompositeType(stmt->typevar, stmt->coldeflist);
+ address = DefineCompositeType(stmt->typevar,
+ stmt->coldeflist);
}
break;
case T_CreateEnumStmt: /* CREATE TYPE AS ENUM */
- DefineEnum((CreateEnumStmt *) parsetree);
+ address = DefineEnum((CreateEnumStmt *) parsetree);
break;
case T_CreateRangeStmt: /* CREATE TYPE AS RANGE */
- DefineRange((CreateRangeStmt *) parsetree);
+ address = DefineRange((CreateRangeStmt *) parsetree);
break;
case T_AlterEnumStmt: /* ALTER TYPE (enum) */
- AlterEnum((AlterEnumStmt *) parsetree, isTopLevel);
+ address = AlterEnum((AlterEnumStmt *) parsetree, isTopLevel);
break;
case T_ViewStmt: /* CREATE VIEW */
- DefineView((ViewStmt *) parsetree, queryString);
+ address = DefineView((ViewStmt *) parsetree, queryString);
+ EventTriggerStashCommand(address, secondaryObject, parsetree);
+ /* stashed internally */
+ commandStashed = true;
break;
case T_CreateFunctionStmt: /* CREATE FUNCTION */
- CreateFunction((CreateFunctionStmt *) parsetree, queryString);
+ address = CreateFunction((CreateFunctionStmt *) parsetree, queryString);
break;
case T_AlterFunctionStmt: /* ALTER FUNCTION */
- AlterFunction((AlterFunctionStmt *) parsetree);
+ address = AlterFunction((AlterFunctionStmt *) parsetree);
break;
case T_RuleStmt: /* CREATE RULE */
- DefineRule((RuleStmt *) parsetree, queryString);
+ address = DefineRule((RuleStmt *) parsetree, queryString);
break;
case T_CreateSeqStmt:
- DefineSequence((CreateSeqStmt *) parsetree);
+ address = DefineSequence((CreateSeqStmt *) parsetree);
break;
case T_AlterSeqStmt:
- AlterSequence((AlterSeqStmt *) parsetree);
+ address = AlterSequence((AlterSeqStmt *) parsetree);
break;
case T_CreateTableAsStmt:
- ExecCreateTableAs((CreateTableAsStmt *) parsetree,
+ address = ExecCreateTableAs((CreateTableAsStmt *) parsetree,
queryString, params, completionTag);
break;
case T_RefreshMatViewStmt:
- ExecRefreshMatView((RefreshMatViewStmt *) parsetree,
- queryString, params, completionTag);
+ /*
+ * REFRSH CONCURRENTLY executes some DDL commands internally.
+ * Inhibit DDL command collection here to avoid those commands
+ * from showing up in the deparsed command queue. The refresh
+ * command itself is queued, which is enough.
+ */
+ EventTriggerInhibitCommandCollection();
+ PG_TRY();
+ {
+ address = ExecRefreshMatView((RefreshMatViewStmt *) parsetree,
+ queryString, params, completionTag);
+ }
+ PG_CATCH();
+ {
+ EventTriggerUndoInhibitCommandCollection();
+ PG_RE_THROW();
+ }
+ PG_END_TRY();
+ EventTriggerUndoInhibitCommandCollection();
break;
case T_CreateTrigStmt:
- (void) CreateTrigger((CreateTrigStmt *) parsetree, queryString,
- InvalidOid, InvalidOid, InvalidOid,
- InvalidOid, false);
+ address = CreateTrigger((CreateTrigStmt *) parsetree,
+ queryString, InvalidOid, InvalidOid,
+ InvalidOid, InvalidOid, false);
break;
case T_CreatePLangStmt:
- CreateProceduralLanguage((CreatePLangStmt *) parsetree);
+ address = CreateProceduralLanguage((CreatePLangStmt *) parsetree);
break;
case T_CreateDomainStmt:
- DefineDomain((CreateDomainStmt *) parsetree);
+ address = DefineDomain((CreateDomainStmt *) parsetree);
break;
case T_CreateConversionStmt:
- CreateConversionCommand((CreateConversionStmt *) parsetree);
+ address = CreateConversionCommand((CreateConversionStmt *) parsetree);
break;
case T_CreateCastStmt:
- CreateCast((CreateCastStmt *) parsetree);
+ address = CreateCast((CreateCastStmt *) parsetree);
break;
case T_CreateOpClassStmt:
- DefineOpClass((CreateOpClassStmt *) parsetree);
+ address = DefineOpClass((CreateOpClassStmt *) parsetree);
break;
case T_CreateOpFamilyStmt:
- DefineOpFamily((CreateOpFamilyStmt *) parsetree);
+ address = DefineOpFamily((CreateOpFamilyStmt *) parsetree);
break;
case T_AlterOpFamilyStmt:
AlterOpFamily((AlterOpFamilyStmt *) parsetree);
+ /* commands are stashed in AlterOpFamily */
+ commandStashed = true;
break;
case T_AlterTSDictionaryStmt:
- AlterTSDictionary((AlterTSDictionaryStmt *) parsetree);
+ address = AlterTSDictionary((AlterTSDictionaryStmt *) parsetree);
break;
case T_AlterTSConfigurationStmt:
- AlterTSConfiguration((AlterTSConfigurationStmt *) parsetree);
+ address = AlterTSConfiguration((AlterTSConfigurationStmt *) parsetree);
break;
case T_AlterTableMoveAllStmt:
AlterTableMoveAll((AlterTableMoveAllStmt *) parsetree);
+ /* commands are stashed in AlterTableMoveAll */
+ commandStashed = true;
break;
case T_DropStmt:
ExecDropStmt((DropStmt *) parsetree, isTopLevel);
+ /* no commands stashed for DROP */
+ commandStashed = true;
break;
case T_RenameStmt:
- ExecRenameStmt((RenameStmt *) parsetree);
+ address = ExecRenameStmt((RenameStmt *) parsetree);
break;
case T_AlterObjectSchemaStmt:
- ExecAlterObjectSchemaStmt((AlterObjectSchemaStmt *) parsetree,
- NULL);
+ address =
+ ExecAlterObjectSchemaStmt((AlterObjectSchemaStmt *) parsetree,
+ &secondaryObject);
break;
case T_AlterOwnerStmt:
- ExecAlterOwnerStmt((AlterOwnerStmt *) parsetree);
+ address = ExecAlterOwnerStmt((AlterOwnerStmt *) parsetree);
break;
case T_CommentStmt:
- CommentObject((CommentStmt *) parsetree);
+ address = CommentObject((CommentStmt *) parsetree);
break;
case T_GrantStmt:
ExecuteGrantStmt((GrantStmt *) parsetree);
+ /* commands are stashed in ExecGrantStmt_oids */
+ commandStashed = true;
break;
case T_DropOwnedStmt:
DropOwnedObjects((DropOwnedStmt *) parsetree);
+ /* no commands stashed for DROP */
+ commandStashed = true;
break;
case T_AlterDefaultPrivilegesStmt:
ExecAlterDefaultPrivilegesStmt((AlterDefaultPrivilegesStmt *) parsetree);
+ /* XXX FIXME WTF? */
break;
case T_CreatePolicyStmt: /* CREATE POLICY */
- CreatePolicy((CreatePolicyStmt *) parsetree);
+ address = CreatePolicy((CreatePolicyStmt *) parsetree);
break;
case T_AlterPolicyStmt: /* ALTER POLICY */
- AlterPolicy((AlterPolicyStmt *) parsetree);
+ address = AlterPolicy((AlterPolicyStmt *) parsetree);
break;
case T_SecLabelStmt:
- ExecSecLabelStmt((SecLabelStmt *) parsetree);
+ address = ExecSecLabelStmt((SecLabelStmt *) parsetree);
break;
default:
break;
}
+ /*
+ * Remember the object so that ddl_command_end event triggers have
+ * access to it.
+ */
+ if (!commandStashed)
+ EventTriggerStashCommand(address, secondaryObject, parsetree);
+
if (isCompleteQuery)
{
EventTriggerSQLDrop(parsetree);