1
0
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:
Robert Haas
2012-07-20 11:38:47 -04:00
parent be86e3dd5b
commit 3a0e4d36eb
28 changed files with 1087 additions and 197 deletions

View File

@@ -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));

View File

@@ -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;