diff --git a/doc/src/sgml/event-trigger.sgml b/doc/src/sgml/event-trigger.sgml index 10b20f0339..234b4ffd02 100644 --- a/doc/src/sgml/event-trigger.sgml +++ b/doc/src/sgml/event-trigger.sgml @@ -1032,6 +1032,14 @@ - + + REINDEX + X + X + - + - + + REVOKE X diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 143fae01eb..b8c7945322 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3558,7 +3558,8 @@ IndexGetRelation(Oid indexId, bool missing_ok) * reindex_index - This routine is used to recreate a single index */ void -reindex_index(Oid indexId, bool skip_constraint_checks, char persistence, +reindex_index(const ReindexStmt *stmt, Oid indexId, + bool skip_constraint_checks, char persistence, const ReindexParams *params) { Relation iRel, @@ -3630,6 +3631,20 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence, pgstat_progress_update_param(PROGRESS_CREATEIDX_ACCESS_METHOD_OID, iRel->rd_rel->relam); + /* + * If a statement is available, telling that this comes from a REINDEX + * command, collect the index for event triggers. + */ + if (stmt) + { + ObjectAddress address; + + ObjectAddressSet(address, RelationRelationId, indexId); + EventTriggerCollectSimpleCommand(address, + InvalidObjectAddress, + (Node *) stmt); + } + /* * Partitioned indexes should never get processed here, as they have no * physical storage. @@ -3865,7 +3880,8 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence, * index rebuild. */ bool -reindex_relation(Oid relid, int flags, const ReindexParams *params) +reindex_relation(const ReindexStmt *stmt, Oid relid, int flags, + const ReindexParams *params) { Relation rel; Oid toast_relid; @@ -3953,7 +3969,7 @@ reindex_relation(Oid relid, int flags, const ReindexParams *params) continue; } - reindex_index(indexOid, !(flags & REINDEX_REL_CHECK_CONSTRAINTS), + reindex_index(stmt, indexOid, !(flags & REINDEX_REL_CHECK_CONSTRAINTS), persistence, params); CommandCounterIncrement(); @@ -3990,7 +4006,7 @@ reindex_relation(Oid relid, int flags, const ReindexParams *params) newparams.options &= ~(REINDEXOPT_MISSING_OK); newparams.tablespaceOid = InvalidOid; - result |= reindex_relation(toast_relid, flags, &newparams); + result |= reindex_relation(stmt, toast_relid, flags, &newparams); } return result; diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index a3bef6ac34..1f52d3913f 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -1518,7 +1518,7 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap, pgstat_progress_update_param(PROGRESS_CLUSTER_PHASE, PROGRESS_CLUSTER_PHASE_REBUILD_INDEX); - reindex_relation(OIDOldHeap, reindex_flags, &reindex_params); + reindex_relation(NULL, OIDOldHeap, reindex_flags, &reindex_params); /* Report that we are now doing clean up */ pgstat_progress_update_param(PROGRESS_CLUSTER_PHASE, diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 795f29d02d..412e1ba84f 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -94,20 +94,21 @@ static char *ChooseIndexName(const char *tabname, Oid namespaceId, bool primary, bool isconstraint); static char *ChooseIndexNameAddition(const List *colnames); static List *ChooseIndexColumnNames(const List *indexElems); -static void ReindexIndex(const RangeVar *indexRelation, const ReindexParams *params, +static void ReindexIndex(const ReindexStmt *stmt, const ReindexParams *params, bool isTopLevel); static void RangeVarCallbackForReindexIndex(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg); -static Oid ReindexTable(const RangeVar *relation, const ReindexParams *params, +static Oid ReindexTable(const ReindexStmt *stmt, const ReindexParams *params, bool isTopLevel); -static void ReindexMultipleTables(const char *objectName, - ReindexObjectType objectKind, const ReindexParams *params); +static void ReindexMultipleTables(const ReindexStmt *stmt, + const ReindexParams *params); static void reindex_error_callback(void *arg); -static void ReindexPartitions(Oid relid, const ReindexParams *params, - bool isTopLevel); -static void ReindexMultipleInternal(const List *relids, +static void ReindexPartitions(const ReindexStmt *stmt, Oid relid, + const ReindexParams *params, bool isTopLevel); +static void ReindexMultipleInternal(const ReindexStmt *stmt, const List *relids, const ReindexParams *params); -static bool ReindexRelationConcurrently(Oid relationOid, +static bool ReindexRelationConcurrently(const ReindexStmt *stmt, + Oid relationOid, const ReindexParams *params); static void update_relispartition(Oid relationId, bool newval); static inline void set_indexsafe_procflags(void); @@ -2735,10 +2736,10 @@ ExecReindex(ParseState *pstate, const ReindexStmt *stmt, bool isTopLevel) switch (stmt->kind) { case REINDEX_OBJECT_INDEX: - ReindexIndex(stmt->relation, ¶ms, isTopLevel); + ReindexIndex(stmt, ¶ms, isTopLevel); break; case REINDEX_OBJECT_TABLE: - ReindexTable(stmt->relation, ¶ms, isTopLevel); + ReindexTable(stmt, ¶ms, isTopLevel); break; case REINDEX_OBJECT_SCHEMA: case REINDEX_OBJECT_SYSTEM: @@ -2754,7 +2755,7 @@ ExecReindex(ParseState *pstate, const ReindexStmt *stmt, bool isTopLevel) (stmt->kind == REINDEX_OBJECT_SCHEMA) ? "REINDEX SCHEMA" : (stmt->kind == REINDEX_OBJECT_SYSTEM) ? "REINDEX SYSTEM" : "REINDEX DATABASE"); - ReindexMultipleTables(stmt->name, stmt->kind, ¶ms); + ReindexMultipleTables(stmt, ¶ms); break; default: elog(ERROR, "unrecognized object type: %d", @@ -2768,8 +2769,9 @@ ExecReindex(ParseState *pstate, const ReindexStmt *stmt, bool isTopLevel) * Recreate a specific index. */ static void -ReindexIndex(const RangeVar *indexRelation, const ReindexParams *params, bool isTopLevel) +ReindexIndex(const ReindexStmt *stmt, const ReindexParams *params, bool isTopLevel) { + const RangeVar *indexRelation = stmt->relation; struct ReindexIndexCallbackState state; Oid indOid; char persistence; @@ -2802,16 +2804,16 @@ ReindexIndex(const RangeVar *indexRelation, const ReindexParams *params, bool is relkind = get_rel_relkind(indOid); if (relkind == RELKIND_PARTITIONED_INDEX) - ReindexPartitions(indOid, params, isTopLevel); + ReindexPartitions(stmt, indOid, params, isTopLevel); else if ((params->options & REINDEXOPT_CONCURRENTLY) != 0 && persistence != RELPERSISTENCE_TEMP) - ReindexRelationConcurrently(indOid, params); + ReindexRelationConcurrently(stmt, indOid, params); else { ReindexParams newparams = *params; newparams.options |= REINDEXOPT_REPORT_PROGRESS; - reindex_index(indOid, false, persistence, &newparams); + reindex_index(stmt, indOid, false, persistence, &newparams); } } @@ -2891,10 +2893,11 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation, * Recreate all indexes of a table (and of its toast table, if any) */ static Oid -ReindexTable(const RangeVar *relation, const ReindexParams *params, bool isTopLevel) +ReindexTable(const ReindexStmt *stmt, const ReindexParams *params, bool isTopLevel) { Oid heapOid; bool result; + const RangeVar *relation = stmt->relation; /* * The lock level used here should match reindex_relation(). @@ -2911,11 +2914,11 @@ ReindexTable(const RangeVar *relation, const ReindexParams *params, bool isTopLe RangeVarCallbackOwnsTable, NULL); if (get_rel_relkind(heapOid) == RELKIND_PARTITIONED_TABLE) - ReindexPartitions(heapOid, params, isTopLevel); + ReindexPartitions(stmt, heapOid, params, isTopLevel); else if ((params->options & REINDEXOPT_CONCURRENTLY) != 0 && get_rel_persistence(heapOid) != RELPERSISTENCE_TEMP) { - result = ReindexRelationConcurrently(heapOid, params); + result = ReindexRelationConcurrently(stmt, heapOid, params); if (!result) ereport(NOTICE, @@ -2927,7 +2930,7 @@ ReindexTable(const RangeVar *relation, const ReindexParams *params, bool isTopLe ReindexParams newparams = *params; newparams.options |= REINDEXOPT_REPORT_PROGRESS; - result = reindex_relation(heapOid, + result = reindex_relation(stmt, heapOid, REINDEX_REL_PROCESS_TOAST | REINDEX_REL_CHECK_CONSTRAINTS, &newparams); @@ -2949,9 +2952,9 @@ ReindexTable(const RangeVar *relation, const ReindexParams *params, bool isTopLe * That means this must not be called within a user transaction block! */ static void -ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, - const ReindexParams *params) +ReindexMultipleTables(const ReindexStmt *stmt, const ReindexParams *params) { + Oid objectOid; Relation relationRelation; TableScanDesc scan; @@ -2963,6 +2966,8 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, int num_keys; bool concurrent_warning = false; bool tablespace_warning = false; + const char *objectName = stmt->name; + const ReindexObjectType objectKind = stmt->kind; Assert(objectKind == REINDEX_OBJECT_SCHEMA || objectKind == REINDEX_OBJECT_SYSTEM || @@ -3158,7 +3163,7 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, * Process each relation listed in a separate transaction. Note that this * commits and then starts a new transaction immediately. */ - ReindexMultipleInternal(relids, params); + ReindexMultipleInternal(stmt, relids, params); MemoryContextDelete(private_context); } @@ -3188,7 +3193,7 @@ reindex_error_callback(void *arg) * by the caller. */ static void -ReindexPartitions(Oid relid, const ReindexParams *params, bool isTopLevel) +ReindexPartitions(const ReindexStmt *stmt, Oid relid, const ReindexParams *params, bool isTopLevel) { List *partitions = NIL; char relkind = get_rel_relkind(relid); @@ -3264,7 +3269,7 @@ ReindexPartitions(Oid relid, const ReindexParams *params, bool isTopLevel) * Process each partition listed in a separate transaction. Note that * this commits and then starts a new transaction immediately. */ - ReindexMultipleInternal(partitions, params); + ReindexMultipleInternal(stmt, partitions, params); /* * Clean up working storage --- note we must do this after @@ -3282,7 +3287,7 @@ ReindexPartitions(Oid relid, const ReindexParams *params, bool isTopLevel) * and starts a new transaction when finished. */ static void -ReindexMultipleInternal(const List *relids, const ReindexParams *params) +ReindexMultipleInternal(const ReindexStmt *stmt, const List *relids, const ReindexParams *params) { ListCell *l; @@ -3341,7 +3346,7 @@ ReindexMultipleInternal(const List *relids, const ReindexParams *params) ReindexParams newparams = *params; newparams.options |= REINDEXOPT_MISSING_OK; - (void) ReindexRelationConcurrently(relid, &newparams); + (void) ReindexRelationConcurrently(stmt, relid, &newparams); /* ReindexRelationConcurrently() does the verbose output */ } else if (relkind == RELKIND_INDEX) @@ -3350,7 +3355,7 @@ ReindexMultipleInternal(const List *relids, const ReindexParams *params) newparams.options |= REINDEXOPT_REPORT_PROGRESS | REINDEXOPT_MISSING_OK; - reindex_index(relid, false, relpersistence, &newparams); + reindex_index(stmt, relid, false, relpersistence, &newparams); PopActiveSnapshot(); /* reindex_index() does the verbose output */ } @@ -3361,7 +3366,7 @@ ReindexMultipleInternal(const List *relids, const ReindexParams *params) newparams.options |= REINDEXOPT_REPORT_PROGRESS | REINDEXOPT_MISSING_OK; - result = reindex_relation(relid, + result = reindex_relation(stmt, relid, REINDEX_REL_PROCESS_TOAST | REINDEX_REL_CHECK_CONSTRAINTS, &newparams); @@ -3406,7 +3411,7 @@ ReindexMultipleInternal(const List *relids, const ReindexParams *params) * anyway, and a non-concurrent reindex is more efficient. */ static bool -ReindexRelationConcurrently(Oid relationOid, const ReindexParams *params) +ReindexRelationConcurrently(const ReindexStmt *stmt, Oid relationOid, const ReindexParams *params) { typedef struct ReindexIndexInfo { @@ -3843,6 +3848,20 @@ ReindexRelationConcurrently(Oid relationOid, const ReindexParams *params) SetUserIdAndSecContext(save_userid, save_sec_context); table_close(heapRel, NoLock); + + /* + * If a statement is available, telling that this comes from a REINDEX + * command, collect the new index for event triggers. + */ + if (stmt) + { + ObjectAddress address; + + ObjectAddressSet(address, RelationRelationId, newIndexId); + EventTriggerCollectSimpleCommand(address, + InvalidObjectAddress, + (Node *) stmt); + } } /* diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 7206da7c53..6b0a20010e 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -2169,7 +2169,7 @@ ExecuteTruncateGuts(List *explicit_rels, /* * Reconstruct the indexes to match, and we're done. */ - reindex_relation(heap_relid, REINDEX_REL_PROCESS_TOAST, + reindex_relation(NULL, heap_relid, REINDEX_REL_PROCESS_TOAST, &reindex_params); } diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index e3ccf6c7f7..366a27ae8e 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -960,10 +960,6 @@ standard_ProcessUtility(PlannedStmt *pstmt, (RecoveryInProgress() ? 0 : CHECKPOINT_FORCE)); break; - case T_ReindexStmt: - ExecReindex(pstate, (ReindexStmt *) parsetree, isTopLevel); - break; - /* * The following statements are supported by Event Triggers only * in some cases, so we "fast path" them in the other cases. @@ -1574,6 +1570,13 @@ ProcessUtilitySlow(ParseState *pstate, } break; + case T_ReindexStmt: + ExecReindex(pstate, (ReindexStmt *) parsetree, isTopLevel); + + /* EventTriggerCollectSimpleCommand is called directly */ + commandCollected = true; + break; + case T_CreateExtensionStmt: address = CreateExtension(pstate, (CreateExtensionStmt *) parsetree); break; diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h index a4770eaf12..41a0b9aee1 100644 --- a/src/include/catalog/index.h +++ b/src/include/catalog/index.h @@ -149,8 +149,9 @@ extern void index_set_state_flags(Oid indexId, IndexStateFlagsAction action); extern Oid IndexGetRelation(Oid indexId, bool missing_ok); -extern void reindex_index(Oid indexId, bool skip_constraint_checks, - char persistence, const ReindexParams *params); +extern void reindex_index(const ReindexStmt *stmt, Oid indexId, + bool skip_constraint_checks, char persistence, + const ReindexParams *params); /* Flag bits for reindex_relation(): */ #define REINDEX_REL_PROCESS_TOAST 0x01 @@ -159,7 +160,8 @@ extern void reindex_index(Oid indexId, bool skip_constraint_checks, #define REINDEX_REL_FORCE_INDEXES_UNLOGGED 0x08 #define REINDEX_REL_FORCE_INDEXES_PERMANENT 0x10 -extern bool reindex_relation(Oid relid, int flags, const ReindexParams *params); +extern bool reindex_relation(const ReindexStmt *stmt, Oid relid, int flags, + const ReindexParams *params); extern bool ReindexIsProcessingHeap(Oid heapOid); extern bool ReindexIsProcessingIndex(Oid indexOid); diff --git a/src/include/tcop/cmdtaglist.h b/src/include/tcop/cmdtaglist.h index 553a31874f..320ee91512 100644 --- a/src/include/tcop/cmdtaglist.h +++ b/src/include/tcop/cmdtaglist.h @@ -194,7 +194,7 @@ PG_CMDTAG(CMDTAG_PREPARE, "PREPARE", false, false, false) PG_CMDTAG(CMDTAG_PREPARE_TRANSACTION, "PREPARE TRANSACTION", false, false, false) PG_CMDTAG(CMDTAG_REASSIGN_OWNED, "REASSIGN OWNED", false, false, false) PG_CMDTAG(CMDTAG_REFRESH_MATERIALIZED_VIEW, "REFRESH MATERIALIZED VIEW", true, false, false) -PG_CMDTAG(CMDTAG_REINDEX, "REINDEX", false, false, false) +PG_CMDTAG(CMDTAG_REINDEX, "REINDEX", true, false, false) PG_CMDTAG(CMDTAG_RELEASE, "RELEASE", false, false, false) PG_CMDTAG(CMDTAG_RESET, "RESET", false, false, false) PG_CMDTAG(CMDTAG_REVOKE, "REVOKE", true, false, false) diff --git a/src/test/regress/expected/event_trigger.out b/src/test/regress/expected/event_trigger.out index 0b87a42d0a..fdcd127945 100644 --- a/src/test/regress/expected/event_trigger.out +++ b/src/test/regress/expected/event_trigger.out @@ -556,6 +556,58 @@ ERROR: cannot alter type "rewritetype" because column "rewritemetoo3.a" uses it drop table rewriteme; drop event trigger no_rewrite_allowed; drop function test_evtrig_no_rewrite(); +-- Tests for REINDEX +CREATE OR REPLACE FUNCTION reindex_start_command() +RETURNS event_trigger AS $$ +BEGIN + RAISE NOTICE 'REINDEX START: % %', tg_event, tg_tag; +END; +$$ LANGUAGE plpgsql; +CREATE EVENT TRIGGER regress_reindex_start ON ddl_command_start + WHEN TAG IN ('REINDEX') + EXECUTE PROCEDURE reindex_start_command(); +CREATE FUNCTION reindex_end_command() +RETURNS event_trigger AS $$ +DECLARE + obj record; +BEGIN + FOR obj IN SELECT * FROM pg_event_trigger_ddl_commands() + LOOP + RAISE NOTICE 'REINDEX END: command_tag=% type=% identity=%', + obj.command_tag, obj.object_type, obj.object_identity; + END LOOP; +END; +$$ LANGUAGE plpgsql; +CREATE EVENT TRIGGER regress_reindex_end ON ddl_command_end + WHEN TAG IN ('REINDEX') + EXECUTE PROCEDURE reindex_end_command(); +CREATE TABLE concur_reindex_tab (c1 int); +CREATE INDEX concur_reindex_ind ON concur_reindex_tab (c1); +-- Both start and end triggers enabled. +REINDEX INDEX concur_reindex_ind; +NOTICE: REINDEX START: ddl_command_start REINDEX +NOTICE: REINDEX END: command_tag=REINDEX type=index identity=public.concur_reindex_ind +REINDEX TABLE concur_reindex_tab; +NOTICE: REINDEX START: ddl_command_start REINDEX +NOTICE: REINDEX END: command_tag=REINDEX type=index identity=public.concur_reindex_ind +REINDEX INDEX CONCURRENTLY concur_reindex_ind; +NOTICE: REINDEX START: ddl_command_start REINDEX +NOTICE: REINDEX END: command_tag=REINDEX type=index identity=public.concur_reindex_ind +REINDEX TABLE CONCURRENTLY concur_reindex_tab; +NOTICE: REINDEX START: ddl_command_start REINDEX +NOTICE: REINDEX END: command_tag=REINDEX type=index identity=public.concur_reindex_ind +-- with start trigger disabled. +ALTER EVENT TRIGGER regress_reindex_start DISABLE; +REINDEX INDEX concur_reindex_ind; +NOTICE: REINDEX END: command_tag=REINDEX type=index identity=public.concur_reindex_ind +REINDEX INDEX CONCURRENTLY concur_reindex_ind; +NOTICE: REINDEX END: command_tag=REINDEX type=index identity=public.concur_reindex_ind +-- Clean up +DROP EVENT TRIGGER regress_reindex_start; +DROP EVENT TRIGGER regress_reindex_end; +DROP FUNCTION reindex_end_command(); +DROP FUNCTION reindex_start_command(); +DROP TABLE concur_reindex_tab; -- test Row Security Event Trigger RESET SESSION AUTHORIZATION; CREATE TABLE event_trigger_test (a integer, b text); diff --git a/src/test/regress/sql/event_trigger.sql b/src/test/regress/sql/event_trigger.sql index 6f0933b9e8..e5c8bf8412 100644 --- a/src/test/regress/sql/event_trigger.sql +++ b/src/test/regress/sql/event_trigger.sql @@ -418,6 +418,51 @@ drop table rewriteme; drop event trigger no_rewrite_allowed; drop function test_evtrig_no_rewrite(); +-- Tests for REINDEX +CREATE OR REPLACE FUNCTION reindex_start_command() +RETURNS event_trigger AS $$ +BEGIN + RAISE NOTICE 'REINDEX START: % %', tg_event, tg_tag; +END; +$$ LANGUAGE plpgsql; +CREATE EVENT TRIGGER regress_reindex_start ON ddl_command_start + WHEN TAG IN ('REINDEX') + EXECUTE PROCEDURE reindex_start_command(); +CREATE FUNCTION reindex_end_command() +RETURNS event_trigger AS $$ +DECLARE + obj record; +BEGIN + FOR obj IN SELECT * FROM pg_event_trigger_ddl_commands() + LOOP + RAISE NOTICE 'REINDEX END: command_tag=% type=% identity=%', + obj.command_tag, obj.object_type, obj.object_identity; + END LOOP; +END; +$$ LANGUAGE plpgsql; +CREATE EVENT TRIGGER regress_reindex_end ON ddl_command_end + WHEN TAG IN ('REINDEX') + EXECUTE PROCEDURE reindex_end_command(); + +CREATE TABLE concur_reindex_tab (c1 int); +CREATE INDEX concur_reindex_ind ON concur_reindex_tab (c1); +-- Both start and end triggers enabled. +REINDEX INDEX concur_reindex_ind; +REINDEX TABLE concur_reindex_tab; +REINDEX INDEX CONCURRENTLY concur_reindex_ind; +REINDEX TABLE CONCURRENTLY concur_reindex_tab; +-- with start trigger disabled. +ALTER EVENT TRIGGER regress_reindex_start DISABLE; +REINDEX INDEX concur_reindex_ind; +REINDEX INDEX CONCURRENTLY concur_reindex_ind; + +-- Clean up +DROP EVENT TRIGGER regress_reindex_start; +DROP EVENT TRIGGER regress_reindex_end; +DROP FUNCTION reindex_end_command(); +DROP FUNCTION reindex_start_command(); +DROP TABLE concur_reindex_tab; + -- test Row Security Event Trigger RESET SESSION AUTHORIZATION; CREATE TABLE event_trigger_test (a integer, b text);