Skip to content

Commit 25c8215

Browse files
kennytmsre-bot
authored andcommitted
[3.0] ddl: error or skip unsupported partition-related DDLs (#10672) (#11373)
1 parent 1adf63e commit 25c8215

File tree

7 files changed

+151
-66
lines changed

7 files changed

+151
-66
lines changed

ddl/db_integration_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1613,17 +1613,17 @@ func (s *testIntegrationSuite3) TestAlterAlgorithm(c *C) {
16131613
s.tk.MustExec("alter table t rename index idx_c to idx_c1, ALGORITHM=DEFAULT")
16141614

16151615
// partition.
1616-
s.assertAlterWarnExec(c, "alter table t truncate partition p1, ALGORITHM=COPY")
1617-
s.assertAlterErrorExec(c, "alter table t truncate partition p2, ALGORITHM=INPLACE")
1618-
s.tk.MustExec("alter table t truncate partition p3, ALGORITHM=INSTANT")
1616+
s.assertAlterWarnExec(c, "alter table t ALGORITHM=COPY, truncate partition p1")
1617+
s.assertAlterErrorExec(c, "alter table t ALGORITHM=INPLACE, truncate partition p2")
1618+
s.tk.MustExec("alter table t ALGORITHM=INSTANT, truncate partition p3")
16191619

16201620
s.assertAlterWarnExec(c, "alter table t add partition (partition p4 values less than (2002)), ALGORITHM=COPY")
16211621
s.assertAlterErrorExec(c, "alter table t add partition (partition p5 values less than (3002)), ALGORITHM=INPLACE")
16221622
s.tk.MustExec("alter table t add partition (partition p6 values less than (4002)), ALGORITHM=INSTANT")
16231623

1624-
s.assertAlterWarnExec(c, "alter table t drop partition p4, ALGORITHM=COPY")
1625-
s.assertAlterErrorExec(c, "alter table t drop partition p5, ALGORITHM=INPLACE")
1626-
s.tk.MustExec("alter table t drop partition p6, ALGORITHM=INSTANT")
1624+
s.assertAlterWarnExec(c, "alter table t ALGORITHM=COPY, drop partition p4")
1625+
s.assertAlterErrorExec(c, "alter table t ALGORITHM=INPLACE, drop partition p5")
1626+
s.tk.MustExec("alter table t ALGORITHM=INSTANT, drop partition p6")
16271627

16281628
// Table options
16291629
s.assertAlterWarnExec(c, "alter table t comment = 'test', ALGORITHM=COPY")

ddl/db_partition_test.go

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323

2424
. "github.com/pingcap/check"
2525
"github.com/pingcap/errors"
26+
"github.com/pingcap/parser/ast"
2627
"github.com/pingcap/parser/model"
2728
tmysql "github.com/pingcap/parser/mysql"
2829
"github.com/pingcap/parser/terror"
@@ -324,14 +325,18 @@ create table log_message_1 (
324325
cases := []testCase{
325326
{
326327
"create table t (id int) partition by range columns (id);",
327-
ddl.ErrPartitionsMustBeDefined,
328+
ast.ErrPartitionsMustBeDefined,
328329
},
329330
{
330331
"create table t (id int) partition by range columns (id) (partition p0 values less than (1, 2));",
331-
ddl.ErrPartitionColumnList,
332+
ast.ErrPartitionColumnList,
332333
},
333334
{
334335
"create table t (a int) partition by range columns (b) (partition p0 values less than (1, 2));",
336+
ast.ErrPartitionColumnList,
337+
},
338+
{
339+
"create table t (a int) partition by range columns (b) (partition p0 values less than (1));",
335340
ddl.ErrFieldNotFoundPart,
336341
},
337342
{
@@ -371,7 +376,10 @@ create table log_message_1 (
371376
}
372377
for i, t := range cases {
373378
_, err := tk.Exec(t.sql)
374-
c.Assert(t.err.Equal(err), IsTrue, Commentf("case %d fail, sql = %s", i, t.sql))
379+
c.Assert(t.err.Equal(err), IsTrue, Commentf(
380+
"case %d fail, sql = `%s`\nexpected error = `%v`\n actual error = `%v`",
381+
i, t.sql, t.err, err,
382+
))
375383
}
376384

377385
tk.MustExec("create table t1 (a int, b char(3)) partition by range columns (a, b) (" +
@@ -496,6 +504,15 @@ func (s *testIntegrationSuite5) TestAlterTableAddPartition(c *C) {
496504
);`
497505
assertErrorCode(c, tk, sql7, tmysql.ErrSameNamePartition)
498506

507+
sql8 := "alter table table3 add partition (partition p6);"
508+
assertErrorCode(c, tk, sql8, tmysql.ErrPartitionRequiresValues)
509+
510+
sql9 := "alter table table3 add partition (partition p7 values in (2018));"
511+
assertErrorCode(c, tk, sql9, tmysql.ErrPartitionWrongValues)
512+
513+
sql10 := "alter table table3 add partition partitions 4;"
514+
assertErrorCode(c, tk, sql10, tmysql.ErrPartitionsMustBeDefined)
515+
499516
tk.MustExec("alter table table3 add partition (partition p3 values less than (2001 + 10))")
500517

501518
// less than value can be negative or expression.
@@ -813,7 +830,7 @@ func (s *testIntegrationSuite6) TestTruncatePartitionAndDropTable(c *C) {
813830
tk.MustExec("drop table if exists t5;")
814831
tk.MustExec("set @@session.tidb_enable_table_partition=1;")
815832
tk.MustExec(`create table t5(
816-
id int, name varchar(50),
833+
id int, name varchar(50),
817834
purchased date
818835
)
819836
partition by range( year(purchased) ) (
@@ -1472,3 +1489,34 @@ func (s *testIntegrationSuite4) TestPartitionErrorCode(c *C) {
14721489
_, err = tk.Exec("alter table t_part coalesce partition 4;")
14731490
c.Assert(ddl.ErrCoalesceOnlyOnHashPartition.Equal(err), IsTrue)
14741491
}
1492+
1493+
func (s *testIntegrationSuite3) TestUnsupportedPartitionManagementDDLs(c *C) {
1494+
tk := testkit.NewTestKit(c, s.store)
1495+
tk.MustExec("use test;")
1496+
tk.MustExec("drop table if exists test_1465;")
1497+
tk.MustExec(`
1498+
create table test_1465 (a int)
1499+
partition by range(a) (
1500+
partition p1 values less than (10),
1501+
partition p2 values less than (20),
1502+
partition p3 values less than (30)
1503+
);
1504+
`)
1505+
1506+
_, err := tk.Exec("alter table test_1465 truncate partition p1, p2")
1507+
c.Assert(err, ErrorMatches, ".*can't run multi schema change")
1508+
_, err = tk.Exec("alter table test_1465 drop partition p1, p2")
1509+
c.Assert(err, ErrorMatches, ".*can't run multi schema change")
1510+
1511+
_, err = tk.Exec("alter table test_1465 partition by hash(a)")
1512+
c.Assert(err, ErrorMatches, ".*alter table partition is unsupported")
1513+
}
1514+
1515+
func (s *testIntegrationSuite8) TestTruncateTableWithPartition(c *C) {
1516+
tk := testkit.NewTestKit(c, s.store)
1517+
tk.MustExec("use test;")
1518+
tk.MustExec("drop table if exists test_4414;")
1519+
tk.MustExec("create table test_4414(a int, b int) partition by hash(a) partitions 10;")
1520+
tk.MustExec("truncate table test_4414;")
1521+
tk.MustQuery("select * from test_4414 partition (p0)").Check(testkit.Rows())
1522+
}

ddl/ddl.go

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,6 @@ var (
194194

195195
// ErrNotAllowedTypeInPartition returns not allowed type error when creating table partiton with unsupport expression type.
196196
ErrNotAllowedTypeInPartition = terror.ClassDDL.New(codeErrFieldTypeNotAllowedAsPartitionField, mysql.MySQLErrName[mysql.ErrFieldTypeNotAllowedAsPartitionField])
197-
// ErrPartitionsMustBeDefined returns each partition must be defined.
198-
ErrPartitionsMustBeDefined = terror.ClassDDL.New(codePartitionsMustBeDefined, "For RANGE partitions each partition must be defined")
199197
// ErrPartitionMgmtOnNonpartitioned returns it's not a partition table.
200198
ErrPartitionMgmtOnNonpartitioned = terror.ClassDDL.New(codePartitionMgmtOnNonpartitioned, "Partition management on a not partitioned table is not possible")
201199
// ErrDropPartitionNonExistent returns error in list of partition.
@@ -206,14 +204,10 @@ var (
206204
ErrRangeNotIncreasing = terror.ClassDDL.New(codeRangeNotIncreasing, "VALUES LESS THAN value must be strictly increasing for each partition")
207205
// ErrPartitionMaxvalue returns maxvalue can only be used in last partition definition.
208206
ErrPartitionMaxvalue = terror.ClassDDL.New(codePartitionMaxvalue, "MAXVALUE can only be used in last partition definition")
209-
// ErrTooManyValues returns cannot have more than one value for this type of partitioning.
210-
ErrTooManyValues = terror.ClassDDL.New(codeErrTooManyValues, mysql.MySQLErrName[mysql.ErrTooManyValues])
211207
//ErrDropLastPartition returns cannot remove all partitions, use drop table instead.
212208
ErrDropLastPartition = terror.ClassDDL.New(codeDropLastPartition, mysql.MySQLErrName[mysql.ErrDropLastPartition])
213209
//ErrTooManyPartitions returns too many partitions were defined.
214210
ErrTooManyPartitions = terror.ClassDDL.New(codeTooManyPartitions, mysql.MySQLErrName[mysql.ErrTooManyPartitions])
215-
//ErrNoParts returns no partition were defined.
216-
ErrNoParts = terror.ClassDDL.New(codeNoParts, mysql.MySQLErrName[mysql.ErrNoParts])
217211
//ErrPartitionFunctionIsNotAllowed returns this partition function is not allowed.
218212
ErrPartitionFunctionIsNotAllowed = terror.ClassDDL.New(codePartitionFunctionIsNotAllowed, mysql.MySQLErrName[mysql.ErrPartitionFunctionIsNotAllowed])
219213
// ErrPartitionFuncNotAllowed returns partition function returns the wrong type.
@@ -235,8 +229,6 @@ var (
235229
ErrTableCantHandleFt = terror.ClassDDL.New(codeErrTableCantHandleFt, mysql.MySQLErrName[mysql.ErrTableCantHandleFt])
236230
// ErrFieldNotFoundPart returns an error when 'partition by columns' are not found in table columns.
237231
ErrFieldNotFoundPart = terror.ClassDDL.New(codeFieldNotFoundPart, mysql.MySQLErrName[mysql.ErrFieldNotFoundPart])
238-
// ErrPartitionColumnList returns "Inconsistency in usage of column lists for partitioning".
239-
ErrPartitionColumnList = terror.ClassDDL.New(codePartitionColumnList, mysql.MySQLErrName[mysql.ErrPartitionColumnList])
240232
)
241233

242234
// DDL is responsible for updating schema in data store and maintaining in-memory InfoSchema cache.
@@ -750,6 +742,14 @@ const (
750742
codeFieldNotFoundPart = terror.ErrCode(mysql.ErrFieldNotFoundPart)
751743
codePartitionColumnList = terror.ErrCode(mysql.ErrPartitionColumnList)
752744
codeOnlyOnRangeListPartition = terror.ErrCode(mysql.ErrOnlyOnRangeListPartition)
745+
codePartitionRequiresValues = terror.ErrCode(mysql.ErrPartitionRequiresValues)
746+
codePartitionWrongNoPart = terror.ErrCode(mysql.ErrPartitionWrongNoPart)
747+
codePartitionWrongNoSubpart = terror.ErrCode(mysql.ErrPartitionWrongNoSubpart)
748+
codePartitionWrongValues = terror.ErrCode(mysql.ErrPartitionWrongValues)
749+
codeRowSinglePartitionField = terror.ErrCode(mysql.ErrRowSinglePartitionField)
750+
codeSubpartition = terror.ErrCode(mysql.ErrSubpartition)
751+
codeSystemVersioningWrongPartitions = terror.ErrCode(mysql.ErrSystemVersioningWrongPartitions)
752+
codeWrongPartitionTypeExpectedSystemTime = terror.ErrCode(mysql.ErrWrongPartitionTypeExpectedSystemTime)
753753
)
754754

755755
func init() {
@@ -813,6 +813,14 @@ func init() {
813813
codeInvalidDefaultValue: mysql.ErrInvalidDefault,
814814
codeErrGeneratedColumnRefAutoInc: mysql.ErrGeneratedColumnRefAutoInc,
815815
codeOnlyOnRangeListPartition: mysql.ErrOnlyOnRangeListPartition,
816+
codePartitionRequiresValues: mysql.ErrPartitionRequiresValues,
817+
codePartitionWrongNoPart: mysql.ErrPartitionWrongNoPart,
818+
codePartitionWrongNoSubpart: mysql.ErrPartitionWrongNoSubpart,
819+
codePartitionWrongValues: mysql.ErrPartitionWrongValues,
820+
codeRowSinglePartitionField: mysql.ErrRowSinglePartitionField,
821+
codeSubpartition: mysql.ErrSubpartition,
822+
codeSystemVersioningWrongPartitions: mysql.ErrSystemVersioningWrongPartitions,
823+
codeWrongPartitionTypeExpectedSystemTime: mysql.ErrWrongPartitionTypeExpectedSystemTime,
816824
}
817825
terror.ErrClassToMySQLCodes[terror.ClassDDL] = ddlMySQLErrCodes
818826
}

ddl/ddl_api.go

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,12 +1583,12 @@ func checkRangeColumnsPartitionValue(ctx sessionctx.Context, tbInfo *model.Table
15831583
// Range columns partition key supports multiple data types with integer、datetime、string.
15841584
defs := pi.Definitions
15851585
if len(defs) < 1 {
1586-
return errors.Trace(ErrPartitionsMustBeDefined)
1586+
return ast.ErrPartitionsMustBeDefined.GenWithStackByArgs("RANGE")
15871587
}
15881588

15891589
curr := &defs[0]
15901590
if len(curr.LessThan) != len(pi.Columns) {
1591-
return errors.Trace(ErrPartitionColumnList)
1591+
return errors.Trace(ast.ErrPartitionColumnList)
15921592
}
15931593
for i := 1; i < len(defs); i++ {
15941594
prev, curr := curr, &defs[i]
@@ -1605,7 +1605,7 @@ func checkRangeColumnsPartitionValue(ctx sessionctx.Context, tbInfo *model.Table
16051605

16061606
func checkTwoRangeColumns(ctx sessionctx.Context, curr, prev *model.PartitionDefinition, pi *model.PartitionInfo, tbInfo *model.TableInfo) (bool, error) {
16071607
if len(curr.LessThan) != len(pi.Columns) {
1608-
return false, errors.Trace(ErrPartitionColumnList)
1608+
return false, errors.Trace(ast.ErrPartitionColumnList)
16091609
}
16101610
for i := 0; i < len(pi.Columns); i++ {
16111611
// Special handling for MAXVALUE.
@@ -1803,8 +1803,7 @@ func resolveAlterTableSpec(ctx sessionctx.Context, specs []*ast.AlterTableSpec)
18031803
validSpecs = append(validSpecs, spec)
18041804
}
18051805

1806-
if len(validSpecs) != 1 {
1807-
// TODO: Hanlde len(validSpecs) == 0.
1806+
if len(validSpecs) > 1 {
18081807
// Now we only allow one schema changing at the same time.
18091808
return nil, errRunMultiSchemaChanges
18101809
}
@@ -1891,6 +1890,9 @@ func (d *ddl) AlterTable(ctx sessionctx.Context, ident ast.Ident, specs []*ast.A
18911890
err = ErrUnsupportedModifyPrimaryKey.GenWithStackByArgs("drop")
18921891
case ast.AlterTableRenameIndex:
18931892
err = d.RenameIndex(ctx, ident, spec)
1893+
case ast.AlterTablePartition:
1894+
// Prevent silent succeed if user executes ALTER TABLE x PARTITION BY ...
1895+
err = errors.New("alter table partition is unsupported")
18941896
case ast.AlterTableOption:
18951897
for i, opt := range spec.Options {
18961898
switch opt.Tp {
@@ -2118,10 +2120,6 @@ func (d *ddl) AddTablePartitions(ctx sessionctx.Context, ident ast.Ident, spec *
21182120
if pi == nil {
21192121
return errors.Trace(ErrPartitionMgmtOnNonpartitioned)
21202122
}
2121-
// We don't support add hash type partition now.
2122-
if meta.Partition.Type == model.PartitionTypeHash {
2123-
return errors.Trace(ErrUnsupportedAddPartition)
2124-
}
21252123

21262124
partInfo, err := buildPartitionInfo(meta, d, spec)
21272125
if err != nil {
@@ -2177,20 +2175,28 @@ func (d *ddl) CoalescePartitions(ctx sessionctx.Context, ident ast.Ident, spec *
21772175
return errors.Trace(ErrPartitionMgmtOnNonpartitioned)
21782176
}
21792177

2180-
// Coalesce partition can only be used on hash/key partitions.
2181-
if meta.Partition.Type == model.PartitionTypeRange {
2182-
return errors.Trace(ErrCoalesceOnlyOnHashPartition)
2183-
}
2184-
2178+
switch meta.Partition.Type {
21852179
// We don't support coalesce partitions hash type partition now.
2186-
if meta.Partition.Type == model.PartitionTypeHash {
2180+
case model.PartitionTypeHash:
21872181
return errors.Trace(ErrUnsupportedCoalescePartition)
2182+
2183+
// Key type partition cannot be constructed currently, ignoring it for now.
2184+
case model.PartitionTypeKey:
2185+
2186+
// Coalesce partition can only be used on hash/key partitions.
2187+
default:
2188+
return errors.Trace(ErrCoalesceOnlyOnHashPartition)
21882189
}
21892190

21902191
return errors.Trace(err)
21912192
}
21922193

21932194
func (d *ddl) TruncateTablePartition(ctx sessionctx.Context, ident ast.Ident, spec *ast.AlterTableSpec) error {
2195+
// TODO: Support truncate multiple partitions
2196+
if len(spec.PartitionNames) != 1 {
2197+
return errRunMultiSchemaChanges
2198+
}
2199+
21942200
is := d.infoHandle.Get()
21952201
schema, ok := is.SchemaByName(ident.Schema)
21962202
if !ok {
@@ -2206,7 +2212,7 @@ func (d *ddl) TruncateTablePartition(ctx sessionctx.Context, ident ast.Ident, sp
22062212
}
22072213

22082214
var pid int64
2209-
pid, err = tables.FindPartitionByName(meta, spec.Name)
2215+
pid, err = tables.FindPartitionByName(meta, spec.PartitionNames[0].L)
22102216
if err != nil {
22112217
return errors.Trace(err)
22122218
}
@@ -2228,6 +2234,11 @@ func (d *ddl) TruncateTablePartition(ctx sessionctx.Context, ident ast.Ident, sp
22282234
}
22292235

22302236
func (d *ddl) DropTablePartition(ctx sessionctx.Context, ident ast.Ident, spec *ast.AlterTableSpec) error {
2237+
// TODO: Support drop multiple partitions
2238+
if len(spec.PartitionNames) != 1 {
2239+
return errRunMultiSchemaChanges
2240+
}
2241+
22312242
is := d.infoHandle.Get()
22322243
schema, ok := is.SchemaByName(ident.Schema)
22332244
if !ok {
@@ -2241,7 +2252,9 @@ func (d *ddl) DropTablePartition(ctx sessionctx.Context, ident ast.Ident, spec *
22412252
if meta.GetPartitionInfo() == nil {
22422253
return errors.Trace(ErrPartitionMgmtOnNonpartitioned)
22432254
}
2244-
err = checkDropTablePartition(meta, spec.Name)
2255+
2256+
partName := spec.PartitionNames[0].L
2257+
err = checkDropTablePartition(meta, partName)
22452258
if err != nil {
22462259
return errors.Trace(err)
22472260
}
@@ -2251,7 +2264,7 @@ func (d *ddl) DropTablePartition(ctx sessionctx.Context, ident ast.Ident, spec *
22512264
TableID: meta.ID,
22522265
Type: model.ActionDropTablePartition,
22532266
BinlogInfo: &model.HistoryInfo{},
2254-
Args: []interface{}{spec.Name},
2267+
Args: []interface{}{partName},
22552268
}
22562269

22572270
err = d.doDDLJob(ctx, job)
@@ -3266,9 +3279,15 @@ func validateCommentLength(vars *variable.SessionVars, comment string, maxLen in
32663279
}
32673280

32683281
func buildPartitionInfo(meta *model.TableInfo, d *ddl, spec *ast.AlterTableSpec) (*model.PartitionInfo, error) {
3269-
if meta.Partition.Type == model.PartitionTypeRange && len(spec.PartDefinitions) == 0 {
3270-
return nil, errors.Trace(ErrPartitionsMustBeDefined)
3282+
if meta.Partition.Type == model.PartitionTypeRange {
3283+
if len(spec.PartDefinitions) == 0 {
3284+
return nil, ast.ErrPartitionsMustBeDefined.GenWithStackByArgs(meta.Partition.Type)
3285+
}
3286+
} else {
3287+
// we don't support ADD PARTITION for all other partition types yet.
3288+
return nil, errors.Trace(ErrUnsupportedAddPartition)
32713289
}
3290+
32723291
part := &model.PartitionInfo{
32733292
Type: meta.Partition.Type,
32743293
Expr: meta.Partition.Expr,
@@ -3281,14 +3300,21 @@ func buildPartitionInfo(meta *model.TableInfo, d *ddl, spec *ast.AlterTableSpec)
32813300
return nil, err
32823301
}
32833302
for ith, def := range spec.PartDefinitions {
3303+
if err := def.Clause.Validate(part.Type, len(part.Columns)); err != nil {
3304+
return nil, err
3305+
}
3306+
// For RANGE partition only VALUES LESS THAN should be possible.
3307+
clause := def.Clause.(*ast.PartitionDefinitionClauseLessThan)
3308+
3309+
comment, _ := def.Comment()
32843310
piDef := model.PartitionDefinition{
32853311
Name: def.Name,
32863312
ID: genIDs[ith],
3287-
Comment: def.Comment,
3313+
Comment: comment,
32883314
}
32893315

32903316
buf := new(bytes.Buffer)
3291-
for _, expr := range def.LessThan {
3317+
for _, expr := range clause.Exprs {
32923318
expr.Format(buf)
32933319
piDef.LessThan = append(piDef.LessThan, buf.String())
32943320
buf.Reset()

0 commit comments

Comments
 (0)