Block ALTER INDEX/TABLE index_name ALTER COLUMN colname SET (options)
authorMichael Paquier <[email protected]>
Tue, 19 Oct 2021 02:03:52 +0000 (11:03 +0900)
committerMichael Paquier <[email protected]>
Tue, 19 Oct 2021 02:03:52 +0000 (11:03 +0900)
The grammar of this command run on indexes with column names has always
been authorized by the parser, and it has never been documented.

Since 911e702, it is possible to define opclass parameters as of CREATE
INDEX, which actually broke the old case of ALTER INDEX/TABLE where
relation-level parameters n_distinct and n_distinct_inherited could be
defined for an index (see 76a47c0 and its thread where this point has
been touched, still remained unused).  Attempting to do that in v13~
would cause the index to become unusable, as there is a new dedicated
code path to load opclass parameters instead of the relation-level ones
previously available.  Note that it is possible to fix things with a
manual catalog update to bring the relation back online.

This commit disables this command for now as the use of column names for
indexes does not make sense anyway, particularly when it comes to index
expressions where names are automatically computed.  One way to properly
support this case properly in the future would be to use column numbers
when it comes to indexes, in the same way as ALTER INDEX .. ALTER COLUMN
.. SET STATISTICS.

Partitioned indexes were already blocked, but not indexes.  Some tests
are added for both cases.

There was some code in ANALYZE to enforce n_distinct to be used for an
index expression if the parameter was defined, but just remove it for
now until/if there is support for this (note that index-level parameters
never had support in pg_dump either, previously), so this was just dead
code.

Reported-by: Matthijs van der Vleuten
Author: Nathan Bossart, Michael Paquier
Reviewed-by: Vik Fearing, Dilip Kumar
Discussion: https://postgr.es/m/17220-15d684c6c2171a83@postgresql.org
Backpatch-through: 13

src/backend/commands/analyze.c
src/backend/commands/tablecmds.c
src/test/regress/expected/btree_index.out
src/test/regress/sql/btree_index.sql

index 8bfb2ad9584fdd71f0268b657d566074e3a751aa..4928702aec0f61263d7203f6d3cf6a5ca5f4c67b 100644 (file)
@@ -965,9 +965,6 @@ compute_index_stats(Relation onerel, double totalrows,
                        for (i = 0; i < attr_cnt; i++)
                        {
                                VacAttrStats *stats = thisdata->vacattrstats[i];
-                               AttributeOpts *aopt =
-                               get_attribute_options(stats->attr->attrelid,
-                                                                         stats->attr->attnum);
 
                                stats->exprvals = exprvals + i;
                                stats->exprnulls = exprnulls + i;
@@ -977,14 +974,6 @@ compute_index_stats(Relation onerel, double totalrows,
                                                                         numindexrows,
                                                                         totalindexrows);
 
-                               /*
-                                * If the n_distinct option is specified, it overrides the
-                                * above computation.  For indices, we always use just
-                                * n_distinct, not n_distinct_inherited.
-                                */
-                               if (aopt != NULL && aopt->n_distinct != 0.0)
-                                       stats->stadistinct = aopt->n_distinct;
-
                                MemoryContextResetAndDeleteChildren(col_context);
                        }
                }
index 14c8003535b83a64ae8841b151bcbfc8905221ae..487852a14e1309737cad0a19733c22cc021c5342 100644 (file)
@@ -4494,7 +4494,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
                        break;
                case AT_SetOptions:             /* ALTER COLUMN SET ( options ) */
                case AT_ResetOptions:   /* ALTER COLUMN RESET ( options ) */
-                       ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW | ATT_INDEX | ATT_FOREIGN_TABLE);
+                       ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW | ATT_FOREIGN_TABLE);
                        /* This command never recurses */
                        pass = AT_PASS_MISC;
                        break;
index bc113a70b49c606c5735512ee5f569179aae35d9..c43e023716b7f0648ec25c8dcb44478b03a56d87 100644 (file)
@@ -329,3 +329,17 @@ INSERT INTO delete_test_table SELECT i, 1, 2, 3 FROM generate_series(1,1000) i;
 -- Test unsupported btree opclass parameters
 create index on btree_tall_tbl (id int4_ops(foo=1));
 ERROR:  operator class int4_ops has no options
+-- Test case of ALTER INDEX with abuse of column names for indexes.
+-- This grammar is not officially supported, but the parser allows it.
+CREATE INDEX btree_tall_idx2 ON btree_tall_tbl (id);
+ALTER INDEX btree_tall_idx2 ALTER COLUMN id SET (n_distinct=100);
+ERROR:  ALTER action ALTER COLUMN ... SET cannot be performed on relation "btree_tall_idx2"
+DETAIL:  This operation is not supported for indexes.
+DROP INDEX btree_tall_idx2;
+-- Partitioned index
+CREATE TABLE btree_part (id int4) PARTITION BY RANGE (id);
+CREATE INDEX btree_part_idx ON btree_part(id);
+ALTER INDEX btree_part_idx ALTER COLUMN id SET (n_distinct=100);
+ERROR:  ALTER action ALTER COLUMN ... SET cannot be performed on relation "btree_part_idx"
+DETAIL:  This operation is not supported for partitioned indexes.
+DROP TABLE btree_part;
index c60312db2deac44b21dc807beb88e7f5b3e5645b..c34502249f3ed043b2621736310e7be2fa56681c 100644 (file)
@@ -172,3 +172,14 @@ INSERT INTO delete_test_table SELECT i, 1, 2, 3 FROM generate_series(1,1000) i;
 
 -- Test unsupported btree opclass parameters
 create index on btree_tall_tbl (id int4_ops(foo=1));
+
+-- Test case of ALTER INDEX with abuse of column names for indexes.
+-- This grammar is not officially supported, but the parser allows it.
+CREATE INDEX btree_tall_idx2 ON btree_tall_tbl (id);
+ALTER INDEX btree_tall_idx2 ALTER COLUMN id SET (n_distinct=100);
+DROP INDEX btree_tall_idx2;
+-- Partitioned index
+CREATE TABLE btree_part (id int4) PARTITION BY RANGE (id);
+CREATE INDEX btree_part_idx ON btree_part(id);
+ALTER INDEX btree_part_idx ALTER COLUMN id SET (n_distinct=100);
+DROP TABLE btree_part;