summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/indexcmds.c29
-rw-r--r--src/backend/utils/cache/lsyscache.c23
-rw-r--r--src/include/utils/lsyscache.h1
-rw-r--r--src/test/regress/expected/indexing.out35
-rw-r--r--src/test/regress/sql/indexing.sql26
5 files changed, 108 insertions, 6 deletions
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index d679fef951c..b8d0a5449cc 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1160,6 +1160,7 @@ DefineIndex(Oid relationId,
IndexStmt *childStmt = copyObject(stmt);
bool found_whole_row;
ListCell *lc;
+ ObjectAddress childAddr;
/*
* We can't use the same index name for the child index,
@@ -1212,14 +1213,24 @@ DefineIndex(Oid relationId,
Assert(GetUserId() == child_save_userid);
SetUserIdAndSecContext(root_save_userid,
root_save_sec_context);
- DefineIndex(childRelid, childStmt,
- InvalidOid, /* no predefined OID */
- indexRelationId, /* this is our child */
- createdConstraintId,
- is_alter_table, check_rights, check_not_in_use,
- skip_build, quiet);
+ childAddr =
+ DefineIndex(childRelid, childStmt,
+ InvalidOid, /* no predefined OID */
+ indexRelationId, /* this is our child */
+ createdConstraintId,
+ is_alter_table, check_rights,
+ check_not_in_use,
+ skip_build, quiet);
SetUserIdAndSecContext(child_save_userid,
child_save_sec_context);
+
+ /*
+ * Check if the index just created is valid or not, as it
+ * could be possible that it has been switched as invalid
+ * when recursing across multiple partition levels.
+ */
+ if (!get_index_isvalid(childAddr.objectId))
+ invalidate_parent = true;
}
pfree(attmap);
@@ -1249,6 +1260,12 @@ DefineIndex(Oid relationId,
ReleaseSysCache(tup);
heap_close(pg_index, RowExclusiveLock);
heap_freetuple(newtup);
+
+ /*
+ * CCI here to make this update visible, in case this recurses
+ * across multiple partition levels.
+ */
+ CommandCounterIncrement();
}
}
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index 913cad35105..d3fca7129a9 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -3204,3 +3204,26 @@ get_index_isclustered(Oid index_oid)
return isclustered;
}
+
+/*
+ * get_index_isvalid
+ *
+ * Given the index OID, return pg_index.indisvalid.
+ */
+bool
+get_index_isvalid(Oid index_oid)
+{
+ bool isvalid;
+ HeapTuple tuple;
+ Form_pg_index rd_index;
+
+ tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for index %u", index_oid);
+
+ rd_index = (Form_pg_index) GETSTRUCT(tuple);
+ isvalid = rd_index->indisvalid;
+ ReleaseSysCache(tuple);
+
+ return isvalid;
+}
diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h
index 21ec4cbd355..c9d6aa7f1c3 100644
--- a/src/include/utils/lsyscache.h
+++ b/src/include/utils/lsyscache.h
@@ -179,6 +179,7 @@ extern char *get_namespace_name_or_temp(Oid nspid);
extern Oid get_range_subtype(Oid rangeOid);
extern Oid get_range_collation(Oid rangeOid);
extern bool get_index_isreplident(Oid index_oid);
+extern bool get_index_isvalid(Oid index_oid);
extern bool get_index_isclustered(Oid index_oid);
#define type_is_array(typid) (get_element_type(typid) != InvalidOid)
diff --git a/src/test/regress/expected/indexing.out b/src/test/regress/expected/indexing.out
index 2544f389e2f..3eec572e917 100644
--- a/src/test/regress/expected/indexing.out
+++ b/src/test/regress/expected/indexing.out
@@ -1537,3 +1537,38 @@ select indexrelid::regclass, indisvalid,
(5 rows)
drop table parted_inval_tab;
+-- Check setup of indisvalid across a complex partition tree on index
+-- creation. If one index in a partition index is invalid, so should its
+-- partitioned index.
+create table parted_isvalid_tab (a int, b int) partition by range (a);
+create table parted_isvalid_tab_1 partition of parted_isvalid_tab
+ for values from (1) to (10) partition by range (a);
+create table parted_isvalid_tab_2 partition of parted_isvalid_tab
+ for values from (10) to (20) partition by range (a);
+create table parted_isvalid_tab_11 partition of parted_isvalid_tab_1
+ for values from (1) to (5);
+create table parted_isvalid_tab_12 partition of parted_isvalid_tab_1
+ for values from (5) to (10);
+-- create an invalid index on one of the partitions.
+insert into parted_isvalid_tab_11 values (1, 0);
+create index concurrently parted_isvalid_idx_11 on parted_isvalid_tab_11 ((a/b));
+ERROR: division by zero
+-- The previous invalid index is selected, invalidating all the indexes up to
+-- the top-most parent.
+create index parted_isvalid_idx on parted_isvalid_tab ((a/b));
+select indexrelid::regclass, indisvalid,
+ indrelid::regclass, inhparent::regclass
+ from pg_index idx left join
+ pg_inherits inh on (idx.indexrelid = inh.inhrelid)
+ where indexrelid::regclass::text like 'parted_isvalid%'
+ order by indexrelid::regclass::text collate "C";
+ indexrelid | indisvalid | indrelid | inhparent
+--------------------------------+------------+-----------------------+-------------------------------
+ parted_isvalid_idx | f | parted_isvalid_tab |
+ parted_isvalid_idx_11 | f | parted_isvalid_tab_11 | parted_isvalid_tab_1_expr_idx
+ parted_isvalid_tab_12_expr_idx | t | parted_isvalid_tab_12 | parted_isvalid_tab_1_expr_idx
+ parted_isvalid_tab_1_expr_idx | f | parted_isvalid_tab_1 | parted_isvalid_idx
+ parted_isvalid_tab_2_expr_idx | t | parted_isvalid_tab_2 | parted_isvalid_idx
+(5 rows)
+
+drop table parted_isvalid_tab;
diff --git a/src/test/regress/sql/indexing.sql b/src/test/regress/sql/indexing.sql
index 6f8233dd445..5e89a0bcd9b 100644
--- a/src/test/regress/sql/indexing.sql
+++ b/src/test/regress/sql/indexing.sql
@@ -817,3 +817,29 @@ select indexrelid::regclass, indisvalid,
where indexrelid::regclass::text like 'parted_inval%'
order by indexrelid::regclass::text collate "C";
drop table parted_inval_tab;
+
+-- Check setup of indisvalid across a complex partition tree on index
+-- creation. If one index in a partition index is invalid, so should its
+-- partitioned index.
+create table parted_isvalid_tab (a int, b int) partition by range (a);
+create table parted_isvalid_tab_1 partition of parted_isvalid_tab
+ for values from (1) to (10) partition by range (a);
+create table parted_isvalid_tab_2 partition of parted_isvalid_tab
+ for values from (10) to (20) partition by range (a);
+create table parted_isvalid_tab_11 partition of parted_isvalid_tab_1
+ for values from (1) to (5);
+create table parted_isvalid_tab_12 partition of parted_isvalid_tab_1
+ for values from (5) to (10);
+-- create an invalid index on one of the partitions.
+insert into parted_isvalid_tab_11 values (1, 0);
+create index concurrently parted_isvalid_idx_11 on parted_isvalid_tab_11 ((a/b));
+-- The previous invalid index is selected, invalidating all the indexes up to
+-- the top-most parent.
+create index parted_isvalid_idx on parted_isvalid_tab ((a/b));
+select indexrelid::regclass, indisvalid,
+ indrelid::regclass, inhparent::regclass
+ from pg_index idx left join
+ pg_inherits inh on (idx.indexrelid = inh.inhrelid)
+ where indexrelid::regclass::text like 'parted_isvalid%'
+ order by indexrelid::regclass::text collate "C";
+drop table parted_isvalid_tab;