Skip to content

Commit 2c1fb5b

Browse files
committed
ddl:fix create partitioned table with bigint column fail
1 parent 67d7544 commit 2c1fb5b

File tree

3 files changed

+66
-20
lines changed

3 files changed

+66
-20
lines changed

ddl/db_test.go

+16
Original file line numberDiff line numberDiff line change
@@ -1735,6 +1735,22 @@ func (s *testDBSuite) TestCreateTableWithPartition(c *C) {
17351735
partition p1 values less than (to_seconds('2005-01-01')));`)
17361736
s.tk.MustQuery("show create table t26").Check(
17371737
testkit.Rows("t26 CREATE TABLE `t26` (\n `a` date DEFAULT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin\nPARTITION BY RANGE ( to_seconds(`a`) ) (\n PARTITION p0 VALUES LESS THAN (63240134400),\n PARTITION p1 VALUES LESS THAN (63271756800)\n)"))
1738+
s.tk.MustExec(`create table t27 (a bigint unsigned not null)
1739+
partition by range(a) (
1740+
partition p0 values less than (10),
1741+
partition p1 values less than (100),
1742+
partition p2 values less than (1000),
1743+
partition p3 values less than (18446744073709551000),
1744+
partition p4 values less than (18446744073709551614)
1745+
);`)
1746+
s.tk.MustExec(`create table t28 (a bigint unsigned not null)
1747+
partition by range(a) (
1748+
partition p0 values less than (10),
1749+
partition p1 values less than (100),
1750+
partition p2 values less than (1000),
1751+
partition p3 values less than (18446744073709551000 + 1),
1752+
partition p4 values less than (18446744073709551000 + 10)
1753+
);`)
17381754
}
17391755

17401756
func (s *testDBSuite) TestTableDDLWithFloatType(c *C) {

ddl/ddl_api.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -904,7 +904,7 @@ func (d *ddl) CreateTable(ctx sessionctx.Context, s *ast.CreateTableStmt) (err e
904904
return errors.Trace(err)
905905
}
906906

907-
if err = checkCreatePartitionValue(ctx, tbInfo, pi); err != nil {
907+
if err = checkCreatePartitionValue(ctx, tbInfo, pi, cols); err != nil {
908908
return errors.Trace(err)
909909
}
910910

ddl/partition.go

+49-19
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ func checkPartitionFuncType(ctx sessionctx.Context, s *ast.CreateTableStmt, cols
178178

179179
// checkCreatePartitionValue checks whether `less than value` is strictly increasing for each partition.
180180
// Side effect: it may simplify the partition range definition from a constant expression to an integer.
181-
func checkCreatePartitionValue(ctx sessionctx.Context, tblInfo *model.TableInfo, pi *model.PartitionInfo) error {
181+
func checkCreatePartitionValue(ctx sessionctx.Context, tblInfo *model.TableInfo, pi *model.PartitionInfo, cols []*table.Column) error {
182182
defs := pi.Definitions
183183
if len(defs) <= 1 {
184184
return nil
@@ -187,13 +187,14 @@ func checkCreatePartitionValue(ctx sessionctx.Context, tblInfo *model.TableInfo,
187187
if strings.EqualFold(defs[len(defs)-1].LessThan[0], partitionMaxValue) {
188188
defs = defs[:len(defs)-1]
189189
}
190-
var prevRangeValue int64
190+
isUnsignedBigint := FindRangePartitionColTp(cols, pi)
191+
var prevRangeValue interface{}
191192
for i := 0; i < len(defs); i++ {
192193
if strings.EqualFold(defs[i].LessThan[0], partitionMaxValue) {
193194
return errors.Trace(ErrPartitionMaxvalue)
194195
}
195196

196-
currentRangeValue, fromExpr, err := getRangeValue(ctx, tblInfo, defs[i].LessThan[0])
197+
currentRangeValue, fromExpr, err := getRangeValue(ctx, tblInfo, defs[i].LessThan[0], isUnsignedBigint)
197198
if err != nil {
198199
return errors.Trace(err)
199200
}
@@ -207,8 +208,14 @@ func checkCreatePartitionValue(ctx sessionctx.Context, tblInfo *model.TableInfo,
207208
continue
208209
}
209210

210-
if currentRangeValue <= prevRangeValue {
211-
return errors.Trace(ErrRangeNotIncreasing)
211+
if isUnsignedBigint {
212+
if currentRangeValue.(uint64) <= prevRangeValue.(uint64) {
213+
return errors.Trace(ErrRangeNotIncreasing)
214+
}
215+
} else {
216+
if currentRangeValue.(int64) <= prevRangeValue.(int64) {
217+
return errors.Trace(ErrRangeNotIncreasing)
218+
}
212219
}
213220
prevRangeValue = currentRangeValue
214221
}
@@ -217,23 +224,34 @@ func checkCreatePartitionValue(ctx sessionctx.Context, tblInfo *model.TableInfo,
217224

218225
// getRangeValue gets an integer from the range value string.
219226
// The returned boolean value indicates whether the input string is a constant expression.
220-
func getRangeValue(ctx sessionctx.Context, tblInfo *model.TableInfo, str string) (int64, bool, error) {
221-
222-
if value, err := strconv.ParseInt(str, 10, 64); err == nil {
223-
return value, false, nil
224-
}
227+
func getRangeValue(ctx sessionctx.Context, tblInfo *model.TableInfo, str string, ifUnsignedBigint bool) (interface{}, bool, error) {
228+
// Unsigned bigint was converted to uint64 handle.
229+
if ifUnsignedBigint {
230+
if value, err := strconv.ParseUint(str, 10, 64); err == nil {
231+
return value, false, nil
232+
}
225233

226-
// The range value maybe not an integer, it could be a constant expression.
227-
// For example, the following two cases are the same:
228-
// PARTITION p0 VALUES LESS THAN (TO_SECONDS('2004-01-01'))
229-
// PARTITION p0 VALUES LESS THAN (63340531200)
230-
if e, err1 := expression.ParseSimpleExprWithTableInfo(ctx, str, tblInfo); err1 == nil {
231-
res, isNull, err2 := e.EvalInt(ctx, chunk.Row{})
232-
if err2 == nil && isNull == false {
233-
return res, true, nil
234+
if e, err1 := expression.ParseSimpleExprWithTableInfo(ctx, str, tblInfo); err1 == nil {
235+
res, isNull, err2 := e.EvalInt(ctx, chunk.Row{})
236+
if err2 == nil && isNull == false {
237+
return uint64(res), true, nil
238+
}
239+
}
240+
} else {
241+
if value, err := strconv.ParseInt(str, 10, 64); err == nil {
242+
return value, false, nil
243+
}
244+
// The range value maybe not an integer, it could be a constant expression.
245+
// For example, the following two cases are the same:
246+
// PARTITION p0 VALUES LESS THAN (TO_SECONDS('2004-01-01'))
247+
// PARTITION p0 VALUES LESS THAN (63340531200)
248+
if e, err1 := expression.ParseSimpleExprWithTableInfo(ctx, str, tblInfo); err1 == nil {
249+
res, isNull, err2 := e.EvalInt(ctx, chunk.Row{})
250+
if err2 == nil && isNull == false {
251+
return res, true, nil
252+
}
234253
}
235254
}
236-
237255
return 0, false, ErrNotAllowedTypeInPartition.GenByArgs(str)
238256
}
239257

@@ -388,3 +406,15 @@ func checkConstraintIncludePartKey(partkeys []string, constraints map[string]str
388406
}
389407
return true
390408
}
409+
410+
// FindRangePartitionColTp finds the type of the partitioning key column type.
411+
// The returned boolean value indicates whether the partitioning key column type is unsigned bigint type.
412+
func FindRangePartitionColTp(cols []*table.Column, pi *model.PartitionInfo) bool {
413+
for _, col := range cols {
414+
isUnsigned := col.Tp == mysql.TypeLonglong && mysql.HasUnsignedFlag(col.Flag)
415+
if isUnsigned && strings.Contains(strings.ToLower(pi.Expr), col.Name.L) {
416+
return true
417+
}
418+
}
419+
return false
420+
}

0 commit comments

Comments
 (0)