Skip to content

Commit

Permalink
partition: fix split and scatter region for truncate partition (#43271)
Browse files Browse the repository at this point in the history
close #43028, close #43174
  • Loading branch information
jiyfhust authored May 12, 2023
1 parent bc98c8d commit 3e4538d
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 20 deletions.
33 changes: 33 additions & 0 deletions ddl/db_partition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1537,6 +1537,39 @@ func TestAlterTableTruncatePartitionByListColumns(t *testing.T) {
tk.MustQuery("select * from t").Check(testkit.Rows())
}

func TestAlterTableTruncatePartitionPreSplitRegion(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
atomic.StoreUint32(&ddl.EnableSplitTableRegion, 1)
tk.MustExec("set @@global.tidb_scatter_region=1;")
tk.MustExec("use test;")

tk.MustExec("drop table if exists t1;")
tk.MustExec(`CREATE TABLE t1 (id int, c varchar(128), key c(c)) partition by range (id) (
partition p0 values less than (10),
partition p1 values less than MAXVALUE)`)
re := tk.MustQuery("show table t1 regions")
rows := re.Rows()
require.Len(t, rows, 2)
tk.MustExec(`alter table t1 truncate partition p0`)
re = tk.MustQuery("show table t1 regions")
rows = re.Rows()
require.Len(t, rows, 2)

tk.MustExec("drop table if exists t2;")
tk.MustExec(`CREATE TABLE t2(id bigint(20) NOT NULL AUTO_INCREMENT, PRIMARY KEY (id) NONCLUSTERED) SHARD_ROW_ID_BITS=4 PRE_SPLIT_REGIONS=3 PARTITION BY RANGE (id) (
PARTITION p1 VALUES LESS THAN (10),
PARTITION p2 VALUES LESS THAN (20),
PARTITION p3 VALUES LESS THAN (MAXVALUE))`)
re = tk.MustQuery("show table t2 regions")
rows = re.Rows()
require.Len(t, rows, 24)
tk.MustExec(`alter table t2 truncate partition p3`)
re = tk.MustQuery("show table t2 regions")
rows = re.Rows()
require.Len(t, rows, 24)
}

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

Expand Down
50 changes: 30 additions & 20 deletions ddl/ddl_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -4232,30 +4232,35 @@ func (d *ddl) TruncateTablePartition(ctx sessionctx.Context, ident ast.Ident, sp
return errors.Trace(dbterror.ErrPartitionMgmtOnNonpartitioned)
}

var pids []int64
if spec.OnAllPartitions {
pids = make([]int64, len(meta.GetPartitionInfo().Definitions))
for i, def := range meta.GetPartitionInfo().Definitions {
pids[i] = def.ID
getTruncatedParts := func(pi *model.PartitionInfo) (*model.PartitionInfo, error) {
if spec.OnAllPartitions {
return pi.Clone(), nil
}
} else {
var defs []model.PartitionDefinition
// MySQL allows duplicate partition names in truncate partition
// so we filter them out through a hash
pidMap := make(map[int64]bool)
posMap := make(map[int]bool)
for _, name := range spec.PartitionNames {
pid, err := tables.FindPartitionByName(meta, name.L)
if err != nil {
return errors.Trace(err)
pos := pi.FindPartitionDefinitionByName(name.L)
if pos < 0 {
return nil, errors.Trace(table.ErrUnknownPartition.GenWithStackByArgs(name.L, ident.Name.O))
}
if _, ok := posMap[pos]; !ok {
defs = append(defs, pi.Definitions[pos])
posMap[pos] = true
}
pidMap[pid] = true
}
// linter makezero does not handle changing pids to zero length,
// so create a new var and then assign to pids...
newPids := make([]int64, 0, len(pidMap))
for pid := range pidMap {
newPids = append(newPids, pid)
}
pids = newPids
pi = pi.Clone()
pi.Definitions = defs
return pi, nil
}
pi, err := getTruncatedParts(meta.GetPartitionInfo())
if err != nil {
return err
}
pids := make([]int64, 0, len(pi.Definitions))
for i := range pi.Definitions {
pids = append(pids, pi.Definitions[i].ID)
}

job := &model.Job{
Expand All @@ -4269,11 +4274,16 @@ func (d *ddl) TruncateTablePartition(ctx sessionctx.Context, ident ast.Ident, sp
}

err = d.DoDDLJob(ctx, job)
err = d.callHookOnChanged(job, err)
if err != nil {
return errors.Trace(err)
}
err = d.callHookOnChanged(job, err)
return errors.Trace(err)
if _, tb, err := d.getSchemaAndTableByIdent(ctx, ident); err == nil {
if p, err := getTruncatedParts(tb.Meta().GetPartitionInfo()); err == nil {
d.preSplitAndScatter(ctx, tb.Meta(), p)
}
}
return nil
}

func (d *ddl) DropTablePartition(ctx sessionctx.Context, ident ast.Ident, spec *ast.AlterTableSpec) error {
Expand Down

0 comments on commit 3e4538d

Please sign in to comment.