Skip to content

Commit

Permalink
Add support for REINDEX in event triggers
Browse files Browse the repository at this point in the history
This commit adds support for REINDEX in event triggers, making this
command react for the events ddl_command_start and ddl_command_end.  The
indexes rebuilt are collected with the ReindexStmt emitted by the
caller, for the concurrent and non-concurrent paths.

Thanks to that, it is possible to know a full list of the indexes that a
single REINDEX command has worked on.

Author: Garrett Thornburg, Jian He
Reviewed-by: Jim Jones, Michael Paquier
Discussion: https://postgr.es/m/CAEEqfk5bm32G7sbhzHbES9WejD8O8DCEOaLkxoBP7HNWxjPpvg@mail.gmail.com
  • Loading branch information
michaelpq committed Dec 4, 2023
1 parent d78b6cb commit f21848d
Show file tree
Hide file tree
Showing 10 changed files with 188 additions and 43 deletions.
8 changes: 8 additions & 0 deletions doc/src/sgml/event-trigger.sgml
Original file line number Diff line number Diff line change
Expand Up @@ -1032,6 +1032,14 @@
<entry align="center"><literal>-</literal></entry>
<entry align="left"></entry>
</row>
<row>
<entry align="left"><literal>REINDEX</literal></entry>
<entry align="center"><literal>X</literal></entry>
<entry align="center"><literal>X</literal></entry>
<entry align="center"><literal>-</literal></entry>
<entry align="center"><literal>-</literal></entry>
<entry align="left"></entry>
</row>
<row>
<entry align="left"><literal>REVOKE</literal></entry>
<entry align="center"><literal>X</literal></entry>
Expand Down
24 changes: 20 additions & 4 deletions src/backend/catalog/index.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/backend/commands/cluster.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
77 changes: 48 additions & 29 deletions src/backend/commands/indexcmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -2735,10 +2736,10 @@ ExecReindex(ParseState *pstate, const ReindexStmt *stmt, bool isTopLevel)
switch (stmt->kind)
{
case REINDEX_OBJECT_INDEX:
ReindexIndex(stmt->relation, &params, isTopLevel);
ReindexIndex(stmt, &params, isTopLevel);
break;
case REINDEX_OBJECT_TABLE:
ReindexTable(stmt->relation, &params, isTopLevel);
ReindexTable(stmt, &params, isTopLevel);
break;
case REINDEX_OBJECT_SCHEMA:
case REINDEX_OBJECT_SYSTEM:
Expand All @@ -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, &params);
ReindexMultipleTables(stmt, &params);
break;
default:
elog(ERROR, "unrecognized object type: %d",
Expand All @@ -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;
Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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().
Expand All @@ -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,
Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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 ||
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand All @@ -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;

Expand Down Expand Up @@ -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)
Expand All @@ -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 */
}
Expand All @@ -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);
Expand Down Expand Up @@ -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
{
Expand Down Expand Up @@ -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);
}
}

/*
Expand Down
2 changes: 1 addition & 1 deletion src/backend/commands/tablecmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
11 changes: 7 additions & 4 deletions src/backend/tcop/utility.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down
8 changes: 5 additions & 3 deletions src/include/catalog/index.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/include/tcop/cmdtaglist.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading

0 comments on commit f21848d

Please sign in to comment.