Skip to content

Commit 6eba67e

Browse files
authored
ddl: Global index more restrictions (#55440) (#55451)
close #55424
1 parent 89bb81b commit 6eba67e

File tree

8 files changed

+234
-44
lines changed

8 files changed

+234
-44
lines changed

pkg/ddl/create_table.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ func buildTableInfoWithCheck(ctx sessionctx.Context, s *ast.CreateTableStmt, dbC
414414
if err = checkTableInfoValidWithStmt(ctx, tbInfo, s); err != nil {
415415
return nil, err
416416
}
417-
if err = checkTableInfoValidExtra(tbInfo); err != nil {
417+
if err = checkTableInfoValidExtra(ctx, tbInfo); err != nil {
418418
return nil, err
419419
}
420420
return tbInfo, nil
@@ -516,7 +516,7 @@ func checkGeneratedColumn(ctx sessionctx.Context, schemaName model.CIStr, tableN
516516
// name length and column count.
517517
// (checkTableInfoValid is also used in repairing objects which don't perform
518518
// these checks. Perhaps the two functions should be merged together regardless?)
519-
func checkTableInfoValidExtra(tbInfo *model.TableInfo) error {
519+
func checkTableInfoValidExtra(ctx sessionctx.Context, tbInfo *model.TableInfo) error {
520520
if err := checkTooLongTable(tbInfo.Name); err != nil {
521521
return err
522522
}
@@ -536,6 +536,9 @@ func checkTableInfoValidExtra(tbInfo *model.TableInfo) error {
536536
if err := checkColumnsAttributes(tbInfo.Columns); err != nil {
537537
return errors.Trace(err)
538538
}
539+
if err := checkGlobalIndexes(ctx, tbInfo); err != nil {
540+
return errors.Trace(err)
541+
}
539542

540543
// FIXME: perform checkConstraintNames
541544
if err := checkCharsetAndCollation(tbInfo.Charset, tbInfo.Collate); err != nil {

pkg/ddl/executor.go

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,47 @@ func checkInvisibleIndexOnPK(tblInfo *model.TableInfo) error {
940940
return nil
941941
}
942942

943+
// checkGlobalIndex check if the index is allowed to have global index
944+
func checkGlobalIndex(ctx sessionctx.Context, tblInfo *model.TableInfo, indexInfo *model.IndexInfo) error {
945+
pi := tblInfo.GetPartitionInfo()
946+
isPartitioned := pi != nil && pi.Type != model.PartitionTypeNone
947+
if indexInfo.Global {
948+
if !isPartitioned {
949+
// Makes no sense with LOCAL/GLOBAL index for non-partitioned tables, since we don't support
950+
// partitioning an index differently from the table partitioning.
951+
return dbterror.ErrGeneralUnsupportedDDL.GenWithStackByArgs("Global Index on non-partitioned table")
952+
}
953+
if !ctx.GetSessionVars().EnableGlobalIndex {
954+
return dbterror.ErrGeneralUnsupportedDDL.GenWithStackByArgs("GLOBAL IndexOption when tidb_enable_global_index is disabled")
955+
}
956+
// TODO: remove limitation
957+
if !indexInfo.Unique {
958+
return dbterror.ErrGeneralUnsupportedDDL.GenWithStackByArgs("GLOBAL IndexOption on non-unique index")
959+
}
960+
// TODO: remove limitation
961+
// check that not all partitioned columns are included.
962+
inAllPartitionColumns, err := checkPartitionKeysConstraint(pi, indexInfo.Columns, tblInfo)
963+
if err != nil {
964+
return errors.Trace(err)
965+
}
966+
if inAllPartitionColumns {
967+
return dbterror.ErrGeneralUnsupportedDDL.GenWithStackByArgs("Global Index including all columns in the partitioning expression")
968+
}
969+
}
970+
return nil
971+
}
972+
973+
// checkGlobalIndexes check if global index is supported.
974+
func checkGlobalIndexes(ctx sessionctx.Context, tblInfo *model.TableInfo) error {
975+
for _, indexInfo := range tblInfo.Indices {
976+
err := checkGlobalIndex(ctx, tblInfo, indexInfo)
977+
if err != nil {
978+
return err
979+
}
980+
}
981+
return nil
982+
}
983+
943984
func (e *executor) assignPartitionIDs(defs []model.PartitionDefinition) error {
944985
genIDs, err := e.genGlobalIDs(len(defs))
945986
if err != nil {
@@ -1048,7 +1089,7 @@ func (e *executor) createTableWithInfoJob(
10481089
}
10491090
}
10501091

1051-
if err := checkTableInfoValidExtra(tbInfo); err != nil {
1092+
if err := checkTableInfoValidExtra(ctx, tbInfo); err != nil {
10521093
return nil, err
10531094
}
10541095

@@ -4650,6 +4691,19 @@ func (e *executor) createIndex(ctx sessionctx.Context, ti ast.Ident, keyType ast
46504691
return errors.Trace(err)
46514692
}
46524693

4694+
globalIndex := false
4695+
if indexOption != nil && indexOption.Global {
4696+
globalIndex = true
4697+
}
4698+
if globalIndex {
4699+
if tblInfo.GetPartitionInfo() == nil {
4700+
return dbterror.ErrGeneralUnsupportedDDL.GenWithStackByArgs("Global Index on non-partitioned table")
4701+
}
4702+
if !unique {
4703+
// TODO: remove this limitation
4704+
return dbterror.ErrGeneralUnsupportedDDL.GenWithStackByArgs("Global IndexOption on non-unique index")
4705+
}
4706+
}
46534707
if unique && tblInfo.GetPartitionInfo() != nil {
46544708
ck, err := checkPartitionKeysConstraint(tblInfo.GetPartitionInfo(), indexColumns, tblInfo)
46554709
if err != nil {
@@ -4660,9 +4714,12 @@ func (e *executor) createIndex(ctx sessionctx.Context, ti ast.Ident, keyType ast
46604714
return dbterror.ErrUniqueKeyNeedAllFieldsInPf.GenWithStackByArgs("UNIQUE INDEX")
46614715
}
46624716
// index columns does not contain all partition columns, must set global
4663-
if indexOption == nil || !indexOption.Global {
4717+
if !globalIndex {
46644718
return dbterror.ErrGlobalIndexNotExplicitlySet.GenWithStackByArgs(indexName.O)
46654719
}
4720+
} else if globalIndex {
4721+
// TODO: remove this restriction
4722+
return dbterror.ErrGeneralUnsupportedDDL.GenWithStackByArgs("Global IndexOption on index including all columns in the partitioning expression")
46664723
}
46674724
}
46684725
// May be truncate comment here, when index comment too long and sql_mode is't strict.

pkg/ddl/tests/partition/BUILD.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ go_test(
88
"main_test.go",
99
],
1010
flaky = True,
11-
shard_count = 50,
11+
shard_count = 49,
1212
deps = [
1313
"//pkg/config",
1414
"//pkg/ddl",

pkg/ddl/tests/partition/db_partition_test.go

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3733,39 +3733,3 @@ func checkGlobalAndPK(t *testing.T, tk *testkit.TestKit, name string, indexes in
37333733
require.True(t, idxInfo.Primary)
37343734
}
37353735
}
3736-
func TestGlobalIndexExplicitOption(t *testing.T) {
3737-
store := testkit.CreateMockStore(t)
3738-
tk := testkit.NewTestKit(t, store)
3739-
tk.MustExec("use test")
3740-
tk.MustExec("set tidb_enable_global_index=OFF")
3741-
defer func() {
3742-
tk.MustExec("set tidb_enable_global_index=default")
3743-
}()
3744-
tk.MustContainErrMsg(`create table t3(a int not null, b int, primary key(a) nonclustered, unique idx_b(b) global) partition by hash(a) partitions 3`, "[ddl:1503]A UNIQUE INDEX must include all columns in the table's partitioning function")
3745-
3746-
tk.MustContainErrMsg(`create table t (a int primary key nonclustered, b int) partition by hash(b) partitions 3`, "[ddl:1503]A PRIMARY KEY must include all columns in the table's partitioning function")
3747-
tk.MustExec(`create table t (a int, b int, unique key (a)) partition by hash(a) partitions 3`)
3748-
tk.MustContainErrMsg(`alter table t partition by hash(b) partitions 3`, "[ddl:1503]A UNIQUE INDEX must include all columns in the table's partitioning function")
3749-
tk.MustContainErrMsg(`alter table t partition by hash(b) partitions 3 update indexes (a global)`, "[ddl:1503]A UNIQUE INDEX must include all columns in the table's partitioning function")
3750-
tk.MustExec(`drop table t`)
3751-
3752-
tk.MustExec("set tidb_enable_global_index=ON")
3753-
tk.MustExec(`create table t (a int not null, b int, primary key(a) nonclustered, unique idx_b(b) global) partition by hash(a) partitions 3`)
3754-
tk.MustExec(`drop table t`)
3755-
tk.MustContainErrMsg(`create table t (a int key global, b int) partition by hash(b) partitions 3`, "[ddl:1503]A CLUSTERED INDEX must include all columns in the table's partitioning function")
3756-
tk.MustContainErrMsg(`create table t (a int unique, b int) partition by hash(b) partitions 3`, "[ddl:8264]Global Index is needed for index 'a', since the unique index is not including all partitioning columns, and GLOBAL is not given as IndexOption")
3757-
tk.MustContainErrMsg(`create table t (a int unique key, b int) partition by hash(b) partitions 3`, "[ddl:8264]Global Index is needed for index 'a', since the unique index is not including all partitioning columns, and GLOBAL is not given as IndexOption")
3758-
tk.MustContainErrMsg(`create table t (a int primary key nonclustered, b int) partition by hash(b) partitions 3`, "[ddl:8264]Global Index is needed for index 'PRIMARY', since the unique index is not including all partitioning columns, and GLOBAL is not given as IndexOption")
3759-
createTable := "CREATE TABLE `t` (\n" +
3760-
" `a` int(11) NOT NULL,\n" +
3761-
" `b` int(11) DEFAULT NULL,\n" +
3762-
" PRIMARY KEY (`a`) /*T![clustered_index] NONCLUSTERED */ /*T![global_index] GLOBAL */\n" +
3763-
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n" +
3764-
"PARTITION BY HASH (`b`) PARTITIONS 3"
3765-
tk.MustExec(createTable)
3766-
tk.MustQuery(`show create table t`).Check(testkit.Rows("t " + createTable))
3767-
tk.MustExec(`drop table t`)
3768-
tk.MustExec(`create table t (a int, b int, unique key (a)) partition by hash(a) partitions 3`)
3769-
tk.MustContainErrMsg(`alter table t partition by hash(b) partitions 3`, "[ddl:8264]Global Index is needed for index 'a', since the unique index is not including all partitioning columns, and GLOBAL is not given as IndexOption")
3770-
tk.MustExec(`alter table t partition by hash(b) partitions 3 UPDATE INDEXES (a GLOBAL)`)
3771-
}

tests/integrationtest/r/ddl/db_partition.result

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3220,9 +3220,13 @@ create table pt14 (id int not null, lname varchar(30), fname varchar(100) genera
32203220
create table nt14 (id int not null, lname varchar(30), fname varchar(100) generated always as (concat(lname, ' ')) virtual);
32213221
alter table pt14 exchange partition p0 with table nt14;
32223222
## unique index
3223-
create table pt15 (id int not null, unique index uk_id (id) global) partition by hash(id) partitions 1;
3223+
create table pt15 (id int not null, unique index uk_id (id)) partition by hash(id) partitions 1;
32243224
create table nt15 (id int not null, index uk_id (id));
32253225
alter table pt15 exchange partition p0 with table nt15;
3226+
Error 1736 (HY000): Tables have different definitions
3227+
create table pt15b (id int not null, a int, unique index uk_id (a) global) partition by hash(id) partitions 1;
3228+
create table nt15b (id int not null, a int, unique index uk_id (a));
3229+
alter table pt15b exchange partition p0 with table nt15b;
32263230
Error 1731 (HY000): Non matching attribute 'global index: uk_id' between partition and table
32273231
## auto_increment
32283232
create table pt16 (id int not null primary key auto_increment) partition by hash(id) partitions 1;
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
set tidb_enable_global_index=OFF;
2+
create table t (a int, b int, unique index idx(a) global);
3+
Error 8200 (HY000): Unsupported Global Index on non-partitioned table
4+
create table t (a int, b int, index idx(a) global);
5+
Error 8200 (HY000): Unsupported Global Index on non-partitioned table
6+
create table t (a int, b int, unique index idx(a) global) partition by hash(b) partitions 3;
7+
Error 1503 (HY000): A UNIQUE INDEX must include all columns in the table's partitioning function
8+
create table t (a int, b int, index idx(a) global) partition by hash(b) partitions 3;
9+
Error 8200 (HY000): Unsupported GLOBAL IndexOption when tidb_enable_global_index is disabled
10+
create table t3(a int not null, b int, primary key(a) nonclustered, unique idx_b(b) global) partition by hash(a) partitions 3;
11+
Error 1503 (HY000): A UNIQUE INDEX must include all columns in the table's partitioning function
12+
create table t (a int primary key nonclustered, b int) partition by hash(b) partitions 3;
13+
Error 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function
14+
create table t (a int, b int, unique key (a)) partition by hash(a) partitions 3;
15+
alter table t partition by hash(b) partitions 3;
16+
Error 1503 (HY000): A UNIQUE INDEX must include all columns in the table's partitioning function
17+
alter table t partition by hash(b) partitions 3 update indexes (a global);
18+
Error 1503 (HY000): A UNIQUE INDEX must include all columns in the table's partitioning function
19+
alter table t add index idxErr (b) global;
20+
Error 8200 (HY000): Unsupported Global IndexOption on non-unique index
21+
alter table t add unique index idxErr (b) global;
22+
Error 1503 (HY000): A UNIQUE INDEX must include all columns in the table's partitioning function
23+
create index idxErr on t (b) global;
24+
Error 8200 (HY000): Unsupported Global IndexOption on non-unique index
25+
create unique index idxErr on t (b) global;
26+
Error 1503 (HY000): A UNIQUE INDEX must include all columns in the table's partitioning function
27+
alter table t remove partitioning;
28+
alter table t add index idxErr (b) global;
29+
Error 8200 (HY000): Unsupported Global Index on non-partitioned table
30+
alter table t add unique index idxErr (b) global;
31+
Error 8200 (HY000): Unsupported Global Index on non-partitioned table
32+
create index idxErr on t (b) global;
33+
Error 8200 (HY000): Unsupported Global Index on non-partitioned table
34+
create unique index idxErr on t (b) global;
35+
Error 8200 (HY000): Unsupported Global Index on non-partitioned table
36+
drop table t;
37+
set tidb_enable_global_index=ON;
38+
create table t (a int, b int, unique index idx(a) global);
39+
Error 8200 (HY000): Unsupported Global Index on non-partitioned table
40+
create table t (a int, b int, index idx(a) global);
41+
Error 8200 (HY000): Unsupported Global Index on non-partitioned table
42+
create table t (a int, b int, index idx(a) global) partition by hash(b) partitions 3;
43+
Error 8200 (HY000): Unsupported GLOBAL IndexOption on non-unique index
44+
create table t (a int not null, b int, primary key(a) nonclustered, unique idx_b(b) global) partition by hash(a) partitions 3;
45+
drop table t;
46+
create table t (a int key global, b int) partition by hash(b) partitions 3;
47+
Error 1503 (HY000): A CLUSTERED INDEX must include all columns in the table's partitioning function
48+
create table t (a int unique, b int) partition by hash(b) partitions 3;
49+
Error 8264 (HY000): Global Index is needed for index 'a', since the unique index is not including all partitioning columns, and GLOBAL is not given as IndexOption
50+
create table t (a int unique key, b int) partition by hash(b) partitions 3;
51+
Error 8264 (HY000): Global Index is needed for index 'a', since the unique index is not including all partitioning columns, and GLOBAL is not given as IndexOption
52+
create table t (a int primary key nonclustered, b int) partition by hash(b) partitions 3;
53+
Error 8264 (HY000): Global Index is needed for index 'PRIMARY', since the unique index is not including all partitioning columns, and GLOBAL is not given as IndexOption
54+
CREATE TABLE `t` (
55+
`a` int(11) NOT NULL,
56+
`b` int(11) DEFAULT NULL,
57+
PRIMARY KEY (`a`) /*T![clustered_index] NONCLUSTERED */ /*T![global_index] GLOBAL */
58+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
59+
PARTITION BY HASH (`b`) PARTITIONS 3;
60+
show create table t;
61+
Table Create Table
62+
t CREATE TABLE `t` (
63+
`a` int(11) NOT NULL,
64+
`b` int(11) DEFAULT NULL,
65+
PRIMARY KEY (`a`) /*T![clustered_index] NONCLUSTERED */ /*T![global_index] GLOBAL */
66+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
67+
PARTITION BY HASH (`b`) PARTITIONS 3
68+
drop table t;
69+
create table t (a int, b int, unique key (a)) partition by hash(a) partitions 3;
70+
alter table t partition by hash(b) partitions 3;
71+
Error 8264 (HY000): Global Index is needed for index 'a', since the unique index is not including all partitioning columns, and GLOBAL is not given as IndexOption
72+
alter table t partition by hash(b) partitions 3 UPDATE INDEXES (a GLOBAL);
73+
alter table t add index idxErr (b) global;
74+
Error 8200 (HY000): Unsupported Global IndexOption on non-unique index
75+
alter table t add unique index idxOK (a) global;
76+
alter table t add unique index idxErr (b) global;
77+
Error 8200 (HY000): Unsupported Global IndexOption on index including all columns in the partitioning expression
78+
create index idxErr on t (b) global;
79+
Error 8200 (HY000): Unsupported Global IndexOption on non-unique index
80+
create unique index idxOK2 on t (a) global;
81+
create unique index idxErr on t (b) global;
82+
Error 8200 (HY000): Unsupported Global IndexOption on index including all columns in the partitioning expression

tests/integrationtest/t/ddl/db_partition.test

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2168,10 +2168,14 @@ create table nt14 (id int not null, lname varchar(30), fname varchar(100) genera
21682168
alter table pt14 exchange partition p0 with table nt14;
21692169

21702170
--echo ## unique index
2171-
create table pt15 (id int not null, unique index uk_id (id) global) partition by hash(id) partitions 1;
2171+
create table pt15 (id int not null, unique index uk_id (id)) partition by hash(id) partitions 1;
21722172
create table nt15 (id int not null, index uk_id (id));
2173-
-- error 1731
2173+
-- error 1736
21742174
alter table pt15 exchange partition p0 with table nt15;
2175+
create table pt15b (id int not null, a int, unique index uk_id (a) global) partition by hash(id) partitions 1;
2176+
create table nt15b (id int not null, a int, unique index uk_id (a));
2177+
-- error 1731
2178+
alter table pt15b exchange partition p0 with table nt15b;
21752179

21762180
--echo ## auto_increment
21772181
create table pt16 (id int not null primary key auto_increment) partition by hash(id) partitions 1;
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
set tidb_enable_global_index=OFF;
2+
-- error 8200
3+
create table t (a int, b int, unique index idx(a) global);
4+
-- error 8200
5+
create table t (a int, b int, index idx(a) global);
6+
-- error 1503
7+
create table t (a int, b int, unique index idx(a) global) partition by hash(b) partitions 3;
8+
-- error 8200
9+
create table t (a int, b int, index idx(a) global) partition by hash(b) partitions 3;
10+
-- error 1503
11+
create table t3(a int not null, b int, primary key(a) nonclustered, unique idx_b(b) global) partition by hash(a) partitions 3;
12+
-- error 1503
13+
create table t (a int primary key nonclustered, b int) partition by hash(b) partitions 3;
14+
create table t (a int, b int, unique key (a)) partition by hash(a) partitions 3;
15+
-- error 1503
16+
alter table t partition by hash(b) partitions 3;
17+
-- error 1503
18+
alter table t partition by hash(b) partitions 3 update indexes (a global);
19+
-- error 8200
20+
alter table t add index idxErr (b) global;
21+
-- error 1503
22+
alter table t add unique index idxErr (b) global;
23+
-- error 8200
24+
create index idxErr on t (b) global;
25+
-- error 1503
26+
create unique index idxErr on t (b) global;
27+
alter table t remove partitioning;
28+
-- error 8200
29+
alter table t add index idxErr (b) global;
30+
-- error 8200
31+
alter table t add unique index idxErr (b) global;
32+
-- error 8200
33+
create index idxErr on t (b) global;
34+
-- error 8200
35+
create unique index idxErr on t (b) global;
36+
drop table t;
37+
38+
set tidb_enable_global_index=ON;
39+
-- error 8200
40+
create table t (a int, b int, unique index idx(a) global);
41+
-- error 8200
42+
create table t (a int, b int, index idx(a) global);
43+
-- error 8200
44+
create table t (a int, b int, index idx(a) global) partition by hash(b) partitions 3;
45+
create table t (a int not null, b int, primary key(a) nonclustered, unique idx_b(b) global) partition by hash(a) partitions 3;
46+
drop table t;
47+
-- error 1503
48+
create table t (a int key global, b int) partition by hash(b) partitions 3;
49+
-- error 8264
50+
create table t (a int unique, b int) partition by hash(b) partitions 3;
51+
-- error 8264
52+
create table t (a int unique key, b int) partition by hash(b) partitions 3;
53+
-- error 8264
54+
create table t (a int primary key nonclustered, b int) partition by hash(b) partitions 3;
55+
CREATE TABLE `t` (
56+
`a` int(11) NOT NULL,
57+
`b` int(11) DEFAULT NULL,
58+
PRIMARY KEY (`a`) /*T![clustered_index] NONCLUSTERED */ /*T![global_index] GLOBAL */
59+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
60+
PARTITION BY HASH (`b`) PARTITIONS 3;
61+
show create table t;
62+
drop table t;
63+
create table t (a int, b int, unique key (a)) partition by hash(a) partitions 3;
64+
-- error 8264
65+
alter table t partition by hash(b) partitions 3;
66+
alter table t partition by hash(b) partitions 3 UPDATE INDEXES (a GLOBAL);
67+
-- error 8200
68+
alter table t add index idxErr (b) global;
69+
alter table t add unique index idxOK (a) global;
70+
-- error 8200
71+
alter table t add unique index idxErr (b) global;
72+
-- error 8200
73+
create index idxErr on t (b) global;
74+
create unique index idxOK2 on t (a) global;
75+
-- error 8200
76+
create unique index idxErr on t (b) global;

0 commit comments

Comments
 (0)