Skip to content

Commit

Permalink
ddl: Only warn of subpartitions, still allow first level partitioning (
Browse files Browse the repository at this point in the history
…#41207) (#43887)

close #41198, close #41200
  • Loading branch information
ti-chi-bot authored Aug 2, 2023
1 parent df3fa99 commit 14d1167
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 13 deletions.
48 changes: 47 additions & 1 deletion ddl/db_partition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -398,14 +398,60 @@ func TestCreateTableWithHashPartition(t *testing.T) {
PARTITION p0 VALUES LESS THAN (100),
PARTITION p1 VALUES LESS THAN (200),
PARTITION p2 VALUES LESS THAN MAXVALUE)`)
tk.MustGetErrCode("select * from t_sub partition (p0)", errno.ErrPartitionClauseOnNonpartitioned)
tk.MustQuery(`show warnings`).Check(testkit.Rows("Warning 8200 Unsupported subpartitioning, only using RANGE partitioning"))
tk.MustQuery("select * from t_sub partition (p0)").Check(testkit.Rows())
tk.MustQuery("show create table t_sub").Check(testkit.Rows("" +
"t_sub CREATE TABLE `t_sub` (\n" +
" `a` int(11) DEFAULT NULL,\n" +
" `b` varchar(128) DEFAULT NULL\n" +
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n" +
"PARTITION BY RANGE (`a`)\n" +
"(PARTITION `p0` VALUES LESS THAN (100),\n" +
" PARTITION `p1` VALUES LESS THAN (200),\n" +
" PARTITION `p2` VALUES LESS THAN (MAXVALUE))"))

// Fix create partition table using extract() function as partition key.
tk.MustExec("create table t2 (a date, b datetime) partition by hash (EXTRACT(YEAR_MONTH FROM a)) partitions 7")
tk.MustExec("create table t3 (a int, b int) partition by hash(ceiling(a-b)) partitions 10")
tk.MustExec("create table t4 (a int, b int) partition by hash(floor(a-b)) partitions 10")
}

func TestSubPartitioning(t *testing.T) {
store := testkit.CreateMockStore(t, mockstore.WithDDLChecker())

tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec(`create table t (a int) partition by range (a) subpartition by hash (a) subpartitions 2 (partition pMax values less than (maxvalue))`)
tk.MustQuery(`show warnings`).Check(testkit.Rows("Warning 8200 Unsupported subpartitioning, only using RANGE partitioning"))
tk.MustQuery(`show create table t`).Check(testkit.Rows("" +
"t CREATE TABLE `t` (\n" +
" `a` int(11) DEFAULT NULL\n" +
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n" +
"PARTITION BY RANGE (`a`)\n" +
"(PARTITION `pMax` VALUES LESS THAN (MAXVALUE))"))
tk.MustExec(`drop table t`)

tk.MustExec(`create table t (a int) partition by list (a) subpartition by key (a) subpartitions 2 (partition pMax values in (1,3,4))`)
tk.MustQuery(`show warnings`).Check(testkit.Rows("Warning 8200 Unsupported subpartitioning, only using LIST partitioning"))
tk.MustQuery(`show create table t`).Check(testkit.Rows("" +
"t CREATE TABLE `t` (\n" +
" `a` int(11) DEFAULT NULL\n" +
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin\n" +
"PARTITION BY LIST (`a`)\n" +
"(PARTITION `pMax` VALUES IN (1,3,4))"))
tk.MustExec(`drop table t`)

tk.MustContainErrMsg(`create table t (a int) partition by hash (a) partitions 2 subpartition by key (a) subpartitions 2`, "[ddl:1500]It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning")
tk.MustExec(`create table t (a int) partition by key (a) partitions 2 subpartition by hash (a) subpartitions 2`)
tk.MustQuery(`show warnings`).Check(testkit.Rows("Warning 8200 Unsupported partition type KEY, treat as normal table"))
tk.MustExec(`drop table t`)

tk.MustContainErrMsg(`CREATE TABLE t ( col1 INT NOT NULL, col2 INT NOT NULL, col3 INT NOT NULL, col4 INT NOT NULL, primary KEY (col1,col3) ) PARTITION BY HASH(col1) PARTITIONS 4 SUBPARTITION BY HASH(col3) SUBPARTITIONS 2`,
"[ddl:1500]It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning")
tk.MustExec(`CREATE TABLE t ( col1 INT NOT NULL, col2 INT NOT NULL, col3 INT NOT NULL, col4 INT NOT NULL, primary KEY (col1,col3) ) PARTITION BY KEY(col1) PARTITIONS 4 SUBPARTITION BY KEY(col3) SUBPARTITIONS 2`)
tk.MustQuery(`show warnings`).Check(testkit.Rows("Warning 8200 Unsupported partition type KEY, treat as normal table"))
}

func TestCreateTableWithRangeColumnPartition(t *testing.T) {
store := testkit.CreateMockStore(t, mockstore.WithDDLChecker())

Expand Down
27 changes: 15 additions & 12 deletions ddl/partition.go
Original file line number Diff line number Diff line change
Expand Up @@ -452,27 +452,30 @@ func buildTablePartitionInfo(ctx sessionctx.Context, s *ast.PartitionOptions, tb
var enable bool
switch s.Tp {
case model.PartitionTypeRange:
if s.Sub == nil {
enable = true
}
case model.PartitionTypeHash:
// Partition by hash is enabled by default.
// Note that linear hash is simply ignored, and creates non-linear hash.
if s.Linear {
ctx.GetSessionVars().StmtCtx.AppendWarning(dbterror.ErrUnsupportedCreatePartition.GenWithStack("LINEAR HASH is not supported, using non-linear HASH instead"))
}
if s.Sub == nil {
enable = true
}
enable = true
case model.PartitionTypeList:
// Partition by list is enabled only when tidb_enable_list_partition is 'ON'.
enable = ctx.GetSessionVars().EnableListTablePartition
case model.PartitionTypeKey:
// Partition by key is not supported until v7.1.
case model.PartitionTypeHash:
if s.Sub != nil {
return ast.ErrSubpartition
}
// Note that linear hash is simply ignored, and creates non-linear hash/key.
if s.Linear {
ctx.GetSessionVars().StmtCtx.AppendWarning(dbterror.ErrUnsupportedCreatePartition.GenWithStack(fmt.Sprintf("LINEAR %s is not supported, using non-linear %s instead", s.Tp.String(), s.Tp.String())))
}
enable = true
}

if !enable {
ctx.GetSessionVars().StmtCtx.AppendWarning(dbterror.ErrUnsupportedCreatePartition.GenWithStack(fmt.Sprintf("Unsupported partition type %v, treat as normal table", s.Tp)))
return nil
}
if s.Sub != nil {
ctx.GetSessionVars().StmtCtx.AppendWarning(dbterror.ErrUnsupportedCreatePartition.GenWithStack(fmt.Sprintf("Unsupported subpartitioning, only using %v partitioning", s.Tp)))
}

pi := &model.PartitionInfo{
Type: s.Tp,
Expand Down
78 changes: 78 additions & 0 deletions table/tables/partition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,84 @@ func TestIssue31629(t *testing.T) {
}
}

func TestKeyPartitionTableMixed(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("create database partitiondb2")
defer tk.MustExec("drop database partitiondb2")
tk.MustExec("use partitiondb2")
// SHOW CREATE TABLE
tk.MustExec("CREATE TABLE tkey1 (col1 INT NOT NULL, col2 DATE NOT NULL,col3 INT NOT NULL, col4 INT NOT NULL, UNIQUE KEY (col3))" +
" PARTITION BY KEY(col3)" +
"(PARTITION `p0`," +
"PARTITION `p1`," +
"PARTITION `p2`," +
"PARTITION `p3`)")
tk.MustQuery(`show warnings`).Check(testkit.Rows("Warning 8200 Unsupported partition type KEY, treat as normal table"))
tk.MustQuery("show create table tkey1").Check(testkit.Rows("tkey1 CREATE TABLE `tkey1` (\n" +
" `col1` int(11) NOT NULL,\n" +
" `col2` date NOT NULL,\n" +
" `col3` int(11) NOT NULL,\n" +
" `col4` int(11) NOT NULL,\n" +
" UNIQUE KEY `col3` (`col3`)\n" +
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin"))
}

func TestKeyPartitionWithDifferentCharsets(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("create database partitiondb4")
defer tk.MustExec("drop database partitiondb4")
tk.MustExec("use partitiondb4")

tk.MustExec("CREATE TABLE tkey29 (" +
"col1 INT NOT NULL," +
"col2 DATE NOT NULL," +
"col3 VARCHAR(12) NOT NULL," +
"col4 INT NOT NULL," +
"UNIQUE KEY (col3)" +
") CHARSET=utf8mb4 COLLATE=utf8mb4_bin " +
"PARTITION BY KEY(col3) " +
"PARTITIONS 4")
// ignore tail spaces
err := tk.ExecToErr("INSERT INTO tkey29 VALUES(1, '2023-02-22', 'linpin', 1), (1, '2023-02-22', 'linpin ', 5)")
require.Regexp(t, "Duplicate entry 'linpin ' for key 'tkey29.col3'", err)
// case sensitive
tk.MustExec("INSERT INTO tkey29 VALUES(3, '2023-02-22', 'abc', 1), (4, '2023-02-22', 'ABC ', 5)")

tk.MustExec("CREATE TABLE tkey30 (" +
"col1 INT NOT NULL," +
"col2 DATE NOT NULL," +
"col3 VARCHAR(12) NOT NULL," +
"col4 INT NOT NULL," +
"UNIQUE KEY (col3)" +
") CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci " +
"PARTITION BY KEY(col3) " +
"PARTITIONS 4")
tk.MustQuery(`show warnings`).Check(testkit.Rows("Warning 8200 Unsupported partition type KEY, treat as normal table"))
// case insensitive
err = tk.ExecToErr("INSERT INTO tkey30 VALUES(1, '2023-02-22', 'linpin', 1), (1, '2023-02-22', 'LINPIN', 5)")
require.Regexp(t, "Duplicate entry 'LINPIN' for key 'tkey30.col3'", err)
// ignore tail spaces
err = tk.ExecToErr("INSERT INTO tkey30 VALUES(1, '2023-02-22', 'linpin', 1), (1, '2023-02-22', 'LINPIN ', 5)")
require.Regexp(t, "Duplicate entry 'LINPIN ' for key 'tkey30.col3'", err)

tk.MustExec("CREATE TABLE tkey31 (" +
"col1 INT NOT NULL," +
"col2 DATE NOT NULL," +
"col3 VARCHAR(12) NOT NULL," +
"col4 INT NOT NULL," +
"UNIQUE KEY (col3)" +
") CHARSET=gbk COLLATE=gbk_chinese_ci " +
"PARTITION BY KEY(col3) " +
"PARTITIONS 4")
tk.MustQuery(`show warnings`).Check(testkit.Rows("Warning 8200 Unsupported partition type KEY, treat as normal table"))
err = tk.ExecToErr("INSERT INTO tkey31 VALUES(1, '2023-02-22', '刘德华', 1), (1, '2023-02-22', '刘德华 ', 5)")
require.Regexp(t, "Duplicate entry '刘德华 ' for key 'tkey31.col3'", err)
tk.MustExec("INSERT INTO tkey31 VALUES(1, '2023-02-22', '刘德华', 1), (5, '2023-02-22', '张学友', 5),(6, '2023-02-22', '艾伦', 6), (7, '2023-02-22', '宁采臣', 7)")
tk.MustContainErrMsg("SELECT * FROM tkey31 partition(p0)", "[planner:1747]PARTITION () clause on non partitioned table")
}

func TestIssue31721(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
Expand Down

0 comments on commit 14d1167

Please sign in to comment.