Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit c426f7c

Browse files
committed
Fix assertion failure with REINDEX and event triggers
A REINDEX CONCURRENTLY run on a table with no indexes would always pop the topmost snapshot from the active snapshot stack, making the snapshot handling inconsistent between the multiple-relation and single-relation cases. This commit slightly changes the snapshot stack handling so as a snapshot is popped only ReindexMultipleInternal() in this case after a relation has been reindexed, fixing a problem where an event trigger function may need a snapshot but does not have one. This also keeps the places where PopActiveSnapshot() is called closer to each other. While on it, this expands the existing tests to cover all the cases that could be faced with REINDEX commands and such event triggers, for one or more relations, with or without indexes. This behavior is inconsistent since 5dc92b8, but we've never had a need for an active snapshot at the end of a REINDEX until now. Thanks also to Jian He for the input. Reported-by: Alexander Lakhin Discussion: https://postgr.es/m/cb538743-484c-eb6a-a8c5-359980cd3a17@gmail.com
1 parent c2a465b commit c426f7c

File tree

3 files changed

+99
-3
lines changed

3 files changed

+99
-3
lines changed

src/backend/commands/indexcmds.c

+2-3
Original file line numberDiff line numberDiff line change
@@ -3347,6 +3347,8 @@ ReindexMultipleInternal(const ReindexStmt *stmt, const List *relids, const Reind
33473347

33483348
newparams.options |= REINDEXOPT_MISSING_OK;
33493349
(void) ReindexRelationConcurrently(stmt, relid, &newparams);
3350+
if (ActiveSnapshotSet())
3351+
PopActiveSnapshot();
33503352
/* ReindexRelationConcurrently() does the verbose output */
33513353
}
33523354
else if (relkind == RELKIND_INDEX)
@@ -3698,10 +3700,7 @@ ReindexRelationConcurrently(const ReindexStmt *stmt, Oid relationOid, const Rein
36983700
* session until this operation completes.
36993701
*/
37003702
if (indexIds == NIL)
3701-
{
3702-
PopActiveSnapshot();
37033703
return false;
3704-
}
37053704

37063705
/* It's not a shared catalog, so refuse to move it to shared tablespace */
37073706
if (params->tablespaceOid == GLOBALTABLESPACE_OID)

src/test/regress/expected/event_trigger.out

+52
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,12 @@ $$ LANGUAGE plpgsql;
581581
CREATE EVENT TRIGGER regress_reindex_end ON ddl_command_end
582582
WHEN TAG IN ('REINDEX')
583583
EXECUTE PROCEDURE reindex_end_command();
584+
-- Extra event to force the use of a snapshot.
585+
CREATE FUNCTION reindex_end_command_snap() RETURNS EVENT_TRIGGER
586+
AS $$ BEGIN PERFORM 1; END $$ LANGUAGE plpgsql;
587+
CREATE EVENT TRIGGER regress_reindex_end_snap ON ddl_command_end
588+
EXECUTE FUNCTION reindex_end_command_snap();
589+
-- With simple relation
584590
CREATE TABLE concur_reindex_tab (c1 int);
585591
CREATE INDEX concur_reindex_ind ON concur_reindex_tab (c1);
586592
-- Both start and end triggers enabled.
@@ -602,10 +608,56 @@ REINDEX INDEX concur_reindex_ind;
602608
NOTICE: REINDEX END: command_tag=REINDEX type=index identity=public.concur_reindex_ind
603609
REINDEX INDEX CONCURRENTLY concur_reindex_ind;
604610
NOTICE: REINDEX END: command_tag=REINDEX type=index identity=public.concur_reindex_ind
611+
-- without an index
612+
DROP INDEX concur_reindex_ind;
613+
REINDEX TABLE concur_reindex_tab;
614+
NOTICE: table "concur_reindex_tab" has no indexes to reindex
615+
REINDEX TABLE CONCURRENTLY concur_reindex_tab;
616+
NOTICE: table "concur_reindex_tab" has no indexes that can be reindexed concurrently
617+
-- With a Schema
618+
CREATE SCHEMA concur_reindex_schema;
619+
-- No indexes
620+
REINDEX SCHEMA concur_reindex_schema;
621+
REINDEX SCHEMA CONCURRENTLY concur_reindex_schema;
622+
CREATE TABLE concur_reindex_schema.tab (a int);
623+
CREATE INDEX ind ON concur_reindex_schema.tab (a);
624+
-- One index reported
625+
REINDEX SCHEMA concur_reindex_schema;
626+
NOTICE: REINDEX END: command_tag=REINDEX type=index identity=concur_reindex_schema.ind
627+
REINDEX SCHEMA CONCURRENTLY concur_reindex_schema;
628+
NOTICE: REINDEX END: command_tag=REINDEX type=index identity=concur_reindex_schema.ind
629+
-- One table on schema but no indexes
630+
DROP INDEX concur_reindex_schema.ind;
631+
REINDEX SCHEMA concur_reindex_schema;
632+
REINDEX SCHEMA CONCURRENTLY concur_reindex_schema;
633+
DROP SCHEMA concur_reindex_schema CASCADE;
634+
NOTICE: drop cascades to table concur_reindex_schema.tab
635+
-- With a partitioned table, and nothing else.
636+
CREATE TABLE concur_reindex_part (id int) PARTITION BY RANGE (id);
637+
REINDEX TABLE concur_reindex_part;
638+
REINDEX TABLE CONCURRENTLY concur_reindex_part;
639+
-- Partition that would be reindexed, still nothing.
640+
CREATE TABLE concur_reindex_child PARTITION OF concur_reindex_part
641+
FOR VALUES FROM (0) TO (10);
642+
REINDEX TABLE concur_reindex_part;
643+
REINDEX TABLE CONCURRENTLY concur_reindex_part;
644+
-- Now add some indexes.
645+
CREATE INDEX concur_reindex_partidx ON concur_reindex_part (id);
646+
REINDEX INDEX concur_reindex_partidx;
647+
NOTICE: REINDEX END: command_tag=REINDEX type=index identity=public.concur_reindex_child_id_idx
648+
REINDEX INDEX CONCURRENTLY concur_reindex_partidx;
649+
NOTICE: REINDEX END: command_tag=REINDEX type=index identity=public.concur_reindex_child_id_idx
650+
REINDEX TABLE concur_reindex_part;
651+
NOTICE: REINDEX END: command_tag=REINDEX type=index identity=public.concur_reindex_child_id_idx
652+
REINDEX TABLE CONCURRENTLY concur_reindex_part;
653+
NOTICE: REINDEX END: command_tag=REINDEX type=index identity=public.concur_reindex_child_id_idx
654+
DROP TABLE concur_reindex_part;
605655
-- Clean up
606656
DROP EVENT TRIGGER regress_reindex_start;
607657
DROP EVENT TRIGGER regress_reindex_end;
658+
DROP EVENT TRIGGER regress_reindex_end_snap;
608659
DROP FUNCTION reindex_end_command();
660+
DROP FUNCTION reindex_end_command_snap();
609661
DROP FUNCTION reindex_start_command();
610662
DROP TABLE concur_reindex_tab;
611663
-- test Row Security Event Trigger

src/test/regress/sql/event_trigger.sql

+45
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,13 @@ $$ LANGUAGE plpgsql;
443443
CREATE EVENT TRIGGER regress_reindex_end ON ddl_command_end
444444
WHEN TAG IN ('REINDEX')
445445
EXECUTE PROCEDURE reindex_end_command();
446+
-- Extra event to force the use of a snapshot.
447+
CREATE FUNCTION reindex_end_command_snap() RETURNS EVENT_TRIGGER
448+
AS $$ BEGIN PERFORM 1; END $$ LANGUAGE plpgsql;
449+
CREATE EVENT TRIGGER regress_reindex_end_snap ON ddl_command_end
450+
EXECUTE FUNCTION reindex_end_command_snap();
446451

452+
-- With simple relation
447453
CREATE TABLE concur_reindex_tab (c1 int);
448454
CREATE INDEX concur_reindex_ind ON concur_reindex_tab (c1);
449455
-- Both start and end triggers enabled.
@@ -455,11 +461,50 @@ REINDEX TABLE CONCURRENTLY concur_reindex_tab;
455461
ALTER EVENT TRIGGER regress_reindex_start DISABLE;
456462
REINDEX INDEX concur_reindex_ind;
457463
REINDEX INDEX CONCURRENTLY concur_reindex_ind;
464+
-- without an index
465+
DROP INDEX concur_reindex_ind;
466+
REINDEX TABLE concur_reindex_tab;
467+
REINDEX TABLE CONCURRENTLY concur_reindex_tab;
468+
469+
-- With a Schema
470+
CREATE SCHEMA concur_reindex_schema;
471+
-- No indexes
472+
REINDEX SCHEMA concur_reindex_schema;
473+
REINDEX SCHEMA CONCURRENTLY concur_reindex_schema;
474+
CREATE TABLE concur_reindex_schema.tab (a int);
475+
CREATE INDEX ind ON concur_reindex_schema.tab (a);
476+
-- One index reported
477+
REINDEX SCHEMA concur_reindex_schema;
478+
REINDEX SCHEMA CONCURRENTLY concur_reindex_schema;
479+
-- One table on schema but no indexes
480+
DROP INDEX concur_reindex_schema.ind;
481+
REINDEX SCHEMA concur_reindex_schema;
482+
REINDEX SCHEMA CONCURRENTLY concur_reindex_schema;
483+
DROP SCHEMA concur_reindex_schema CASCADE;
484+
485+
-- With a partitioned table, and nothing else.
486+
CREATE TABLE concur_reindex_part (id int) PARTITION BY RANGE (id);
487+
REINDEX TABLE concur_reindex_part;
488+
REINDEX TABLE CONCURRENTLY concur_reindex_part;
489+
-- Partition that would be reindexed, still nothing.
490+
CREATE TABLE concur_reindex_child PARTITION OF concur_reindex_part
491+
FOR VALUES FROM (0) TO (10);
492+
REINDEX TABLE concur_reindex_part;
493+
REINDEX TABLE CONCURRENTLY concur_reindex_part;
494+
-- Now add some indexes.
495+
CREATE INDEX concur_reindex_partidx ON concur_reindex_part (id);
496+
REINDEX INDEX concur_reindex_partidx;
497+
REINDEX INDEX CONCURRENTLY concur_reindex_partidx;
498+
REINDEX TABLE concur_reindex_part;
499+
REINDEX TABLE CONCURRENTLY concur_reindex_part;
500+
DROP TABLE concur_reindex_part;
458501

459502
-- Clean up
460503
DROP EVENT TRIGGER regress_reindex_start;
461504
DROP EVENT TRIGGER regress_reindex_end;
505+
DROP EVENT TRIGGER regress_reindex_end_snap;
462506
DROP FUNCTION reindex_end_command();
507+
DROP FUNCTION reindex_end_command_snap();
463508
DROP FUNCTION reindex_start_command();
464509
DROP TABLE concur_reindex_tab;
465510

0 commit comments

Comments
 (0)