mirror of
https://github.com/postgres/postgres.git
synced 2025-09-02 04:21:28 +03:00
Make new event trigger facility actually do something.
Commit 3855968f32
added syntax, pg_dump,
psql support, and documentation, but the triggers didn't actually fire.
With this commit, they now do. This is still a pretty basic facility
overall because event triggers do not get a whole lot of information
about what the user is trying to do unless you write them in C; and
there's still no option to fire them anywhere except at the very
beginning of the execution sequence, but it's better than nothing,
and a good building block for future work.
Along the way, add a regression test for ALTER LARGE OBJECT, since
testing of event triggers reveals that we haven't got one.
Dimitri Fontaine and Robert Haas
This commit is contained in:
@@ -1186,9 +1186,10 @@ PortalRunUtility(Portal portal, Node *utilityStmt, bool isTopLevel,
|
||||
ProcessUtility(utilityStmt,
|
||||
portal->sourceText,
|
||||
portal->portalParams,
|
||||
isTopLevel,
|
||||
dest,
|
||||
completionTag);
|
||||
completionTag,
|
||||
isTopLevel ?
|
||||
PROCESS_UTILITY_TOPLEVEL : PROCESS_UTILITY_QUERY);
|
||||
|
||||
/* Some utility statements may change context on us */
|
||||
MemoryContextSwitchTo(PortalGetHeapMemory(portal));
|
||||
|
@@ -320,9 +320,9 @@ void
|
||||
ProcessUtility(Node *parsetree,
|
||||
const char *queryString,
|
||||
ParamListInfo params,
|
||||
bool isTopLevel,
|
||||
DestReceiver *dest,
|
||||
char *completionTag)
|
||||
char *completionTag,
|
||||
ProcessUtilityContext context)
|
||||
{
|
||||
Assert(queryString != NULL); /* required as of 8.4 */
|
||||
|
||||
@@ -333,20 +333,23 @@ ProcessUtility(Node *parsetree,
|
||||
*/
|
||||
if (ProcessUtility_hook)
|
||||
(*ProcessUtility_hook) (parsetree, queryString, params,
|
||||
isTopLevel, dest, completionTag);
|
||||
dest, completionTag, context);
|
||||
else
|
||||
standard_ProcessUtility(parsetree, queryString, params,
|
||||
isTopLevel, dest, completionTag);
|
||||
dest, completionTag, context);
|
||||
}
|
||||
|
||||
void
|
||||
standard_ProcessUtility(Node *parsetree,
|
||||
const char *queryString,
|
||||
ParamListInfo params,
|
||||
bool isTopLevel,
|
||||
DestReceiver *dest,
|
||||
char *completionTag)
|
||||
char *completionTag,
|
||||
ProcessUtilityContext context)
|
||||
{
|
||||
bool isTopLevel = (context == PROCESS_UTILITY_TOPLEVEL);
|
||||
bool isCompleteQuery = (context <= PROCESS_UTILITY_QUERY);
|
||||
|
||||
check_xact_readonly(parsetree);
|
||||
|
||||
if (completionTag)
|
||||
@@ -503,6 +506,8 @@ standard_ProcessUtility(Node *parsetree,
|
||||
* relation and attribute manipulation
|
||||
*/
|
||||
case T_CreateSchemaStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
CreateSchemaCommand((CreateSchemaStmt *) parsetree,
|
||||
queryString);
|
||||
break;
|
||||
@@ -514,6 +519,9 @@ standard_ProcessUtility(Node *parsetree,
|
||||
ListCell *l;
|
||||
Oid relOid;
|
||||
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
|
||||
/* Run parse analysis ... */
|
||||
stmts = transformCreateStmt((CreateStmt *) parsetree,
|
||||
queryString);
|
||||
@@ -565,9 +573,9 @@ standard_ProcessUtility(Node *parsetree,
|
||||
ProcessUtility(stmt,
|
||||
queryString,
|
||||
params,
|
||||
false,
|
||||
None_Receiver,
|
||||
NULL);
|
||||
NULL,
|
||||
PROCESS_UTILITY_GENERATED);
|
||||
}
|
||||
|
||||
/* Need CCI between commands */
|
||||
@@ -578,79 +586,110 @@ standard_ProcessUtility(Node *parsetree,
|
||||
break;
|
||||
|
||||
case T_CreateTableSpaceStmt:
|
||||
/* no event triggers for global objects */
|
||||
PreventTransactionChain(isTopLevel, "CREATE TABLESPACE");
|
||||
CreateTableSpace((CreateTableSpaceStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_DropTableSpaceStmt:
|
||||
/* no event triggers for global objects */
|
||||
PreventTransactionChain(isTopLevel, "DROP TABLESPACE");
|
||||
DropTableSpace((DropTableSpaceStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_AlterTableSpaceOptionsStmt:
|
||||
/* no event triggers for global objects */
|
||||
AlterTableSpaceOptions((AlterTableSpaceOptionsStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_CreateExtensionStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
CreateExtension((CreateExtensionStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_AlterExtensionStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
ExecAlterExtensionStmt((AlterExtensionStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_AlterExtensionContentsStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
ExecAlterExtensionContentsStmt((AlterExtensionContentsStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_CreateFdwStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
CreateForeignDataWrapper((CreateFdwStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_AlterFdwStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
AlterForeignDataWrapper((AlterFdwStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_CreateForeignServerStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
CreateForeignServer((CreateForeignServerStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_AlterForeignServerStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
AlterForeignServer((AlterForeignServerStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_CreateUserMappingStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
CreateUserMapping((CreateUserMappingStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_AlterUserMappingStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
AlterUserMapping((AlterUserMappingStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_DropUserMappingStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
RemoveUserMapping((DropUserMappingStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_DropStmt:
|
||||
switch (((DropStmt *) parsetree)->removeType)
|
||||
{
|
||||
case OBJECT_INDEX:
|
||||
if (((DropStmt *) parsetree)->concurrent)
|
||||
PreventTransactionChain(isTopLevel,
|
||||
"DROP INDEX CONCURRENTLY");
|
||||
/* fall through */
|
||||
DropStmt *stmt = (DropStmt *) parsetree;
|
||||
|
||||
case OBJECT_TABLE:
|
||||
case OBJECT_SEQUENCE:
|
||||
case OBJECT_VIEW:
|
||||
case OBJECT_FOREIGN_TABLE:
|
||||
RemoveRelations((DropStmt *) parsetree);
|
||||
break;
|
||||
default:
|
||||
RemoveObjects((DropStmt *) parsetree);
|
||||
break;
|
||||
if (isCompleteQuery
|
||||
&& EventTriggerSupportsObjectType(stmt->removeType))
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
|
||||
switch (stmt->removeType)
|
||||
{
|
||||
case OBJECT_INDEX:
|
||||
if (stmt->concurrent)
|
||||
PreventTransactionChain(isTopLevel,
|
||||
"DROP INDEX CONCURRENTLY");
|
||||
/* fall through */
|
||||
|
||||
case OBJECT_TABLE:
|
||||
case OBJECT_SEQUENCE:
|
||||
case OBJECT_VIEW:
|
||||
case OBJECT_FOREIGN_TABLE:
|
||||
RemoveRelations((DropStmt *) parsetree);
|
||||
break;
|
||||
default:
|
||||
RemoveObjects((DropStmt *) parsetree);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case T_TruncateStmt:
|
||||
ExecuteTruncate((TruncateStmt *) parsetree);
|
||||
@@ -695,16 +734,40 @@ standard_ProcessUtility(Node *parsetree,
|
||||
* schema
|
||||
*/
|
||||
case T_RenameStmt:
|
||||
ExecRenameStmt((RenameStmt *) parsetree);
|
||||
break;
|
||||
{
|
||||
RenameStmt *stmt;
|
||||
|
||||
stmt = (RenameStmt *) parsetree;
|
||||
if (isCompleteQuery &&
|
||||
EventTriggerSupportsObjectType(stmt->renameType))
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
ExecRenameStmt(stmt);
|
||||
break;
|
||||
}
|
||||
|
||||
case T_AlterObjectSchemaStmt:
|
||||
ExecAlterObjectSchemaStmt((AlterObjectSchemaStmt *) parsetree);
|
||||
break;
|
||||
{
|
||||
AlterObjectSchemaStmt *stmt;
|
||||
|
||||
stmt = (AlterObjectSchemaStmt *) parsetree;
|
||||
if (isCompleteQuery &&
|
||||
EventTriggerSupportsObjectType(stmt->objectType))
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
ExecAlterObjectSchemaStmt(stmt);
|
||||
break;
|
||||
}
|
||||
|
||||
case T_AlterOwnerStmt:
|
||||
ExecAlterOwnerStmt((AlterOwnerStmt *) parsetree);
|
||||
break;
|
||||
{
|
||||
AlterOwnerStmt *stmt;
|
||||
|
||||
stmt = (AlterOwnerStmt *) parsetree;
|
||||
if (isCompleteQuery &&
|
||||
EventTriggerSupportsObjectType(stmt->objectType))
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
ExecAlterOwnerStmt(stmt);
|
||||
break;
|
||||
}
|
||||
|
||||
case T_AlterTableStmt:
|
||||
{
|
||||
@@ -714,6 +777,9 @@ standard_ProcessUtility(Node *parsetree,
|
||||
ListCell *l;
|
||||
LOCKMODE lockmode;
|
||||
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
|
||||
/*
|
||||
* Figure out lock mode, and acquire lock. This also does
|
||||
* basic permissions checks, so that we won't wait for a lock
|
||||
@@ -744,9 +810,9 @@ standard_ProcessUtility(Node *parsetree,
|
||||
ProcessUtility(stmt,
|
||||
queryString,
|
||||
params,
|
||||
false,
|
||||
None_Receiver,
|
||||
NULL);
|
||||
NULL,
|
||||
PROCESS_UTILITY_GENERATED);
|
||||
}
|
||||
|
||||
/* Need CCI between commands */
|
||||
@@ -765,6 +831,9 @@ standard_ProcessUtility(Node *parsetree,
|
||||
{
|
||||
AlterDomainStmt *stmt = (AlterDomainStmt *) parsetree;
|
||||
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
|
||||
/*
|
||||
* Some or all of these functions are recursive to cover
|
||||
* inherited things, so permission checks are done there.
|
||||
@@ -819,6 +888,8 @@ standard_ProcessUtility(Node *parsetree,
|
||||
break;
|
||||
|
||||
case T_AlterDefaultPrivilegesStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
ExecAlterDefaultPrivilegesStmt((AlterDefaultPrivilegesStmt *) parsetree);
|
||||
break;
|
||||
|
||||
@@ -829,6 +900,9 @@ standard_ProcessUtility(Node *parsetree,
|
||||
{
|
||||
DefineStmt *stmt = (DefineStmt *) parsetree;
|
||||
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
|
||||
switch (stmt->kind)
|
||||
{
|
||||
case OBJECT_AGGREGATE:
|
||||
@@ -875,19 +949,28 @@ standard_ProcessUtility(Node *parsetree,
|
||||
{
|
||||
CompositeTypeStmt *stmt = (CompositeTypeStmt *) parsetree;
|
||||
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
|
||||
DefineCompositeType(stmt->typevar, stmt->coldeflist);
|
||||
}
|
||||
break;
|
||||
|
||||
case T_CreateEnumStmt: /* CREATE TYPE AS ENUM */
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
DefineEnum((CreateEnumStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_CreateRangeStmt: /* CREATE TYPE AS RANGE */
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
DefineRange((CreateRangeStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_AlterEnumStmt: /* ALTER TYPE (enum) */
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
|
||||
/*
|
||||
* We disallow this in transaction blocks, because we can't cope
|
||||
@@ -899,14 +982,20 @@ standard_ProcessUtility(Node *parsetree,
|
||||
break;
|
||||
|
||||
case T_ViewStmt: /* CREATE VIEW */
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
DefineView((ViewStmt *) parsetree, queryString);
|
||||
break;
|
||||
|
||||
case T_CreateFunctionStmt: /* CREATE FUNCTION */
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
CreateFunction((CreateFunctionStmt *) parsetree, queryString);
|
||||
break;
|
||||
|
||||
case T_AlterFunctionStmt: /* ALTER FUNCTION */
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
AlterFunction((AlterFunctionStmt *) parsetree);
|
||||
break;
|
||||
|
||||
@@ -914,6 +1003,8 @@ standard_ProcessUtility(Node *parsetree,
|
||||
{
|
||||
IndexStmt *stmt = (IndexStmt *) parsetree;
|
||||
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
if (stmt->concurrent)
|
||||
PreventTransactionChain(isTopLevel,
|
||||
"CREATE INDEX CONCURRENTLY");
|
||||
@@ -934,14 +1025,20 @@ standard_ProcessUtility(Node *parsetree,
|
||||
break;
|
||||
|
||||
case T_RuleStmt: /* CREATE RULE */
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
DefineRule((RuleStmt *) parsetree, queryString);
|
||||
break;
|
||||
|
||||
case T_CreateSeqStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
DefineSequence((CreateSeqStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_AlterSeqStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
AlterSequence((AlterSeqStmt *) parsetree);
|
||||
break;
|
||||
|
||||
@@ -950,15 +1047,18 @@ standard_ProcessUtility(Node *parsetree,
|
||||
break;
|
||||
|
||||
case T_CreatedbStmt:
|
||||
/* no event triggers for global objects */
|
||||
PreventTransactionChain(isTopLevel, "CREATE DATABASE");
|
||||
createdb((CreatedbStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_AlterDatabaseStmt:
|
||||
/* no event triggers for global objects */
|
||||
AlterDatabase((AlterDatabaseStmt *) parsetree, isTopLevel);
|
||||
break;
|
||||
|
||||
case T_AlterDatabaseSetStmt:
|
||||
/* no event triggers for global objects */
|
||||
AlterDatabaseSet((AlterDatabaseSetStmt *) parsetree);
|
||||
break;
|
||||
|
||||
@@ -966,6 +1066,7 @@ standard_ProcessUtility(Node *parsetree,
|
||||
{
|
||||
DropdbStmt *stmt = (DropdbStmt *) parsetree;
|
||||
|
||||
/* no event triggers for global objects */
|
||||
PreventTransactionChain(isTopLevel, "DROP DATABASE");
|
||||
dropdb(stmt->dbname, stmt->missing_ok);
|
||||
}
|
||||
@@ -1032,6 +1133,8 @@ standard_ProcessUtility(Node *parsetree,
|
||||
break;
|
||||
|
||||
case T_CreateTableAsStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
ExecCreateTableAs((CreateTableAsStmt *) parsetree,
|
||||
queryString, params, completionTag);
|
||||
break;
|
||||
@@ -1055,19 +1158,25 @@ standard_ProcessUtility(Node *parsetree,
|
||||
break;
|
||||
|
||||
case T_CreateTrigStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
(void) CreateTrigger((CreateTrigStmt *) parsetree, queryString,
|
||||
InvalidOid, InvalidOid, false);
|
||||
break;
|
||||
|
||||
case T_CreateEventTrigStmt:
|
||||
/* no event triggers on event triggers */
|
||||
CreateEventTrigger((CreateEventTrigStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_AlterEventTrigStmt:
|
||||
/* no event triggers on event triggers */
|
||||
AlterEventTrigger((AlterEventTrigStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_CreatePLangStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
CreateProceduralLanguage((CreatePLangStmt *) parsetree);
|
||||
break;
|
||||
|
||||
@@ -1075,6 +1184,8 @@ standard_ProcessUtility(Node *parsetree,
|
||||
* ******************************** DOMAIN statements ****
|
||||
*/
|
||||
case T_CreateDomainStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
DefineDomain((CreateDomainStmt *) parsetree);
|
||||
break;
|
||||
|
||||
@@ -1082,26 +1193,32 @@ standard_ProcessUtility(Node *parsetree,
|
||||
* ******************************** ROLE statements ****
|
||||
*/
|
||||
case T_CreateRoleStmt:
|
||||
/* no event triggers for global objects */
|
||||
CreateRole((CreateRoleStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_AlterRoleStmt:
|
||||
/* no event triggers for global objects */
|
||||
AlterRole((AlterRoleStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_AlterRoleSetStmt:
|
||||
/* no event triggers for global objects */
|
||||
AlterRoleSet((AlterRoleSetStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_DropRoleStmt:
|
||||
/* no event triggers for global objects */
|
||||
DropRole((DropRoleStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_DropOwnedStmt:
|
||||
/* no event triggers for global objects */
|
||||
DropOwnedObjects((DropOwnedStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_ReassignOwnedStmt:
|
||||
/* no event triggers for global objects */
|
||||
ReassignOwnedObjects((ReassignOwnedStmt *) parsetree);
|
||||
break;
|
||||
|
||||
@@ -1173,30 +1290,44 @@ standard_ProcessUtility(Node *parsetree,
|
||||
break;
|
||||
|
||||
case T_CreateConversionStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
CreateConversionCommand((CreateConversionStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_CreateCastStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
CreateCast((CreateCastStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_CreateOpClassStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
DefineOpClass((CreateOpClassStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_CreateOpFamilyStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
DefineOpFamily((CreateOpFamilyStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_AlterOpFamilyStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
AlterOpFamily((AlterOpFamilyStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_AlterTSDictionaryStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
AlterTSDictionary((AlterTSDictionaryStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_AlterTSConfigurationStmt:
|
||||
if (isCompleteQuery)
|
||||
EventTriggerDDLCommandStart(parsetree);
|
||||
AlterTSConfiguration((AlterTSConfigurationStmt *) parsetree);
|
||||
break;
|
||||
|
||||
|
Reference in New Issue
Block a user