From 399c105862e142449e41ac33fa65b178ed627a5a Mon Sep 17 00:00:00 2001 From: crazycs Date: Fri, 18 Oct 2019 15:44:22 +0800 Subject: [PATCH] ddl: fix bug that range columns partition table add partitions failed (#12348) (#12815) --- ddl/db_partition_test.go | 20 ++++++++++++++ ddl/ddl_api.go | 60 ++++++++++++++-------------------------- ddl/partition.go | 14 +++++++++- ddl/table.go | 2 +- 4 files changed, 54 insertions(+), 42 deletions(-) diff --git a/ddl/db_partition_test.go b/ddl/db_partition_test.go index 08a9cb823f156..afd56a76702b3 100644 --- a/ddl/db_partition_test.go +++ b/ddl/db_partition_test.go @@ -170,6 +170,19 @@ func (s *testIntegrationSuite9) TestCreateTableWithPartition(c *C) { );` assertErrorCode(c, tk, sql9, tmysql.ErrPartitionFunctionIsNotAllowed) + assertErrorCode(c, tk, `create TABLE t10 (c1 int,c2 int) partition by range(c1 / c2 ) (partition p0 values less than (2));`, tmysql.ErrPartitionFunctionIsNotAllowed) + _, err = tk.Exec(`CREATE TABLE t9 ( + a INT NOT NULL, + b INT NOT NULL, + c INT NOT NULL + ) + partition by range columns(a) ( + partition p0 values less than (10), + partition p2 values less than (20), + partition p3 values less than (20) + );`) + c.Assert(ddl.ErrRangeNotIncreasing.Equal(err), IsTrue) + assertErrorCode(c, tk, `create TABLE t10 (c1 int,c2 int) partition by range(c1 / c2 ) (partition p0 values less than (2));`, tmysql.ErrPartitionFunctionIsNotAllowed) tk.MustExec(`create TABLE t11 (c1 int,c2 int) partition by range(c1 div c2 ) (partition p0 values less than (2));`) @@ -525,6 +538,13 @@ func (s *testIntegrationSuite5) TestAlterTableAddPartition(c *C) { );`) tk.MustExec(`ALTER TABLE tt5 add partition ( partition p2 values less than (-1) );`) tk.MustExec(`ALTER TABLE tt5 add partition ( partition p3 values less than (5-1) );`) + + // Test add partition for the table partition by range columns. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a datetime) partition by range columns (a) (partition p1 values less than ('2019-06-01'), partition p2 values less than ('2019-07-01'));") + sql := "alter table t add partition ( partition p3 values less than ('2019-07-01'));" + assertErrorCode(c, tk, sql, tmysql.ErrRangeNotIncreasing) + tk.MustExec("alter table t add partition ( partition p3 values less than ('2019-08-01'));") } func (s *testIntegrationSuite6) TestAlterTableDropPartition(c *C) { diff --git a/ddl/ddl_api.go b/ddl/ddl_api.go index 91be4e5fda7da..21a5924cdd4bd 100644 --- a/ddl/ddl_api.go +++ b/ddl/ddl_api.go @@ -1324,11 +1324,7 @@ func buildTableInfoWithCheck(ctx sessionctx.Context, d *ddl, s *ast.CreateTableS if pi != nil { switch pi.Type { case model.PartitionTypeRange: - if len(pi.Columns) == 0 { - err = checkPartitionByRange(ctx, tbInfo, pi, s, cols, newConstraints) - } else { - err = checkPartitionByRangeColumn(ctx, tbInfo, pi, s) - } + err = checkPartitionByRange(ctx, tbInfo, pi, cols, s) case model.PartitionTypeHash: err = checkPartitionByHash(ctx, pi, s, cols, tbInfo) } @@ -1572,12 +1568,8 @@ func checkPartitionByHash(ctx sessionctx.Context, pi *model.PartitionInfo, s *as return checkPartitionFuncType(ctx, s, cols, tbInfo) } -func checkPartitionByRange(ctx sessionctx.Context, tbInfo *model.TableInfo, pi *model.PartitionInfo, s *ast.CreateTableStmt, cols []*table.Column, newConstraints []*ast.Constraint) error { - if err := checkPartitionNameUnique(tbInfo, pi); err != nil { - return err - } - - if err := checkCreatePartitionValue(ctx, tbInfo, pi, cols); err != nil { +func checkPartitionByRange(ctx sessionctx.Context, tbInfo *model.TableInfo, pi *model.PartitionInfo, cols []*table.Column, s *ast.CreateTableStmt) error { + if err := checkPartitionNameUnique(pi); err != nil { return err } @@ -1589,31 +1581,28 @@ func checkPartitionByRange(ctx sessionctx.Context, tbInfo *model.TableInfo, pi * return err } - if err := checkPartitionFuncValid(ctx, tbInfo, s.Partition.Expr); err != nil { - return err - } + if len(pi.Columns) == 0 { + if err := checkCreatePartitionValue(ctx, tbInfo, pi, cols); err != nil { + return err + } - return checkPartitionFuncType(ctx, s, cols, tbInfo) -} + // s maybe nil when add partition. + if s == nil { + return nil + } -func checkPartitionByRangeColumn(ctx sessionctx.Context, tbInfo *model.TableInfo, pi *model.PartitionInfo, s *ast.CreateTableStmt) error { - if err := checkPartitionNameUnique(tbInfo, pi); err != nil { - return err + if err := checkPartitionFuncValid(ctx, tbInfo, s.Partition.Expr); err != nil { + return err + } + return checkPartitionFuncType(ctx, s, cols, tbInfo) } + // Check for range columns partition. if err := checkRangeColumnsPartitionType(tbInfo, pi.Columns); err != nil { return err } - if err := checkRangeColumnsPartitionValue(ctx, tbInfo, pi); err != nil { - return err - } - - if err := checkNoRangePartitions(len(pi.Definitions)); err != nil { - return errors.Trace(err) - } - - return checkAddPartitionTooManyPartitions(uint64(len(pi.Definitions))) + return checkRangeColumnsPartitionValue(ctx, tbInfo, pi) } func checkRangeColumnsPartitionType(tbInfo *model.TableInfo, columns []model.CIStr) error { @@ -1649,8 +1638,9 @@ func checkRangeColumnsPartitionValue(ctx sessionctx.Context, tbInfo *model.Table if len(curr.LessThan) != len(pi.Columns) { return errors.Trace(ast.ErrPartitionColumnList) } + var prev *model.PartitionDefinition for i := 1; i < len(defs); i++ { - prev, curr := curr, &defs[i] + prev, curr = curr, &defs[i] succ, err := checkTwoRangeColumns(ctx, curr, prev, pi, tbInfo) if err != nil { return err @@ -2193,21 +2183,11 @@ func (d *ddl) AddTablePartitions(ctx sessionctx.Context, ident ast.Ident, spec * return errors.Trace(err) } - err = checkAddPartitionTooManyPartitions(uint64(len(meta.Partition.Definitions) + len(partInfo.Definitions))) - if err != nil { - return errors.Trace(err) - } - - err = checkPartitionNameUnique(meta, partInfo) - if err != nil { - return errors.Trace(err) - } - // partInfo contains only the new added partition, we have to combine it with the // old partitions to check all partitions is strictly increasing. tmp := *partInfo tmp.Definitions = append(pi.Definitions, tmp.Definitions...) - err = checkCreatePartitionValue(ctx, meta, &tmp, t.Cols()) + err = checkPartitionByRange(ctx, meta, &tmp, t.Cols(), nil) if err != nil { return errors.Trace(err) } diff --git a/ddl/partition.go b/ddl/partition.go index cea935091c350..14354ec825b74 100644 --- a/ddl/partition.go +++ b/ddl/partition.go @@ -161,7 +161,19 @@ func buildRangePartitionDefinitions(ctx sessionctx.Context, d *ddl, s *ast.Creat return nil } -func checkPartitionNameUnique(tbInfo *model.TableInfo, pi *model.PartitionInfo) error { +func checkPartitionNameUnique(pi *model.PartitionInfo) error { + partNames := make(map[string]struct{}) + newPars := pi.Definitions + for _, newPar := range newPars { + if _, ok := partNames[newPar.Name.L]; ok { + return ErrSameNamePartition.GenWithStackByArgs(newPar.Name) + } + partNames[newPar.Name.L] = struct{}{} + } + return nil +} + +func checkAddPartitionNameUnique(tbInfo *model.TableInfo, pi *model.PartitionInfo) error { partNames := make(map[string]struct{}) if tbInfo.Partition != nil { oldPars := tbInfo.Partition.Definitions diff --git a/ddl/table.go b/ddl/table.go index fca4150c9021f..447cd9fa41316 100644 --- a/ddl/table.go +++ b/ddl/table.go @@ -772,7 +772,7 @@ func onAddTablePartition(t *meta.Meta, job *model.Job) (ver int64, _ error) { return ver, errors.Trace(err) } - err = checkPartitionNameUnique(tblInfo, partInfo) + err = checkAddPartitionNameUnique(tblInfo, partInfo) if err != nil { job.State = model.JobStateCancelled return ver, errors.Trace(err)