From 61b4ff23213de3da2eb152a83b04ed63328ef2ad Mon Sep 17 00:00:00 2001 From: lysu Date: Tue, 7 Aug 2018 16:39:54 +0800 Subject: [PATCH] ddl: add fsp checking for time/timestamp/datetime column definition (#7294) --- ddl/db_test.go | 22 ++++++++++++++++++++++ ddl/ddl_api.go | 20 ++++++++++++-------- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/ddl/db_test.go b/ddl/db_test.go index c792ee8260..65fc9bd81a 100644 --- a/ddl/db_test.go +++ b/ddl/db_test.go @@ -1739,6 +1739,28 @@ func (s *testDBSuite) TestTableDDLWithFloatType(c *C) { s.mustExec(c, "drop table t") } +func (s *testDBSuite) TestTableDDLWithTimeType(c *C) { + s.tk.MustExec("use test") + s.tk.MustExec("drop table if exists t") + s.testErrorCode(c, "create table t (a time(7))", tmysql.ErrTooBigPrecision) + s.testErrorCode(c, "create table t (a datetime(7))", tmysql.ErrTooBigPrecision) + s.testErrorCode(c, "create table t (a timestamp(7))", tmysql.ErrTooBigPrecision) + _, err := s.tk.Exec("create table t (a time(-1))") + c.Assert(err, NotNil) + s.mustExec(c, "create table t (a datetime)") + s.testErrorCode(c, "alter table t add column b time(7)", tmysql.ErrTooBigPrecision) + s.testErrorCode(c, "alter table t add column b datetime(7)", tmysql.ErrTooBigPrecision) + s.testErrorCode(c, "alter table t add column b timestamp(7)", tmysql.ErrTooBigPrecision) + s.testErrorCode(c, "alter table t modify column a time(7)", tmysql.ErrTooBigPrecision) + s.testErrorCode(c, "alter table t modify column a datetime(7)", tmysql.ErrTooBigPrecision) + s.testErrorCode(c, "alter table t modify column a timestamp(7)", tmysql.ErrTooBigPrecision) + s.testErrorCode(c, "alter table t change column a aa time(7)", tmysql.ErrTooBigPrecision) + s.testErrorCode(c, "alter table t change column a aa datetime(7)", tmysql.ErrTooBigPrecision) + s.testErrorCode(c, "alter table t change column a aa timestamp(7)", tmysql.ErrTooBigPrecision) + s.mustExec(c, "alter table t change column a aa timestamp(0)") + s.mustExec(c, "drop table t") +} + func (s *testDBSuite) TestTruncateTable(c *C) { tk := testkit.NewTestKit(c, s.store) tk.MustExec("use test") diff --git a/ddl/ddl_api.go b/ddl/ddl_api.go index 5ae069cb02..613d4a42a6 100644 --- a/ddl/ddl_api.go +++ b/ddl/ddl_api.go @@ -597,23 +597,27 @@ func checkTooManyColumns(colDefs []*ast.ColumnDef) error { return nil } -// checkPointTypeColumns checks multiple decimal/float/double columns. -func checkPointTypeColumns(colDefs []*ast.ColumnDef) error { +// checkColumnsAttributes checks attributes for multiple columns. +func checkColumnsAttributes(colDefs []*ast.ColumnDef) error { for _, colDef := range colDefs { - if err := checkPointTypeColumn(colDef.Name.OrigColName(), colDef.Tp); err != nil { + if err := checkColumnAttributes(colDef.Name.OrigColName(), colDef.Tp); err != nil { return errors.Trace(err) } } return nil } -// checkPointTypeColumn checks a decimal/float/double column. -func checkPointTypeColumn(colName string, tp *types.FieldType) error { +// checkColumnAttributes check attributes for single column. +func checkColumnAttributes(colName string, tp *types.FieldType) error { switch tp.Tp { case mysql.TypeNewDecimal, mysql.TypeDouble, mysql.TypeFloat: if tp.Flen < tp.Decimal { return types.ErrMBiggerThanD.GenByArgs(colName) } + case mysql.TypeDatetime, mysql.TypeDuration, mysql.TypeTimestamp: + if tp.Decimal != types.UnspecifiedFsp && (tp.Decimal < types.MinFsp || tp.Decimal > types.MaxFsp) { + return types.ErrTooBigPrecision.GenByArgs(tp.Decimal, colName, types.MaxFsp) + } } return nil } @@ -871,7 +875,7 @@ func (d *ddl) CreateTable(ctx sessionctx.Context, s *ast.CreateTableStmt) (err e return errors.Trace(err) } - if err = checkPointTypeColumns(colDefs); err != nil { + if err = checkColumnsAttributes(colDefs); err != nil { return errors.Trace(err) } @@ -1193,7 +1197,7 @@ func (d *ddl) AddColumn(ctx sessionctx.Context, ti ast.Ident, spec *ast.AlterTab } colName := specNewColumn.Name.Name.O - if err = checkPointTypeColumn(colName, specNewColumn.Tp); err != nil { + if err = checkColumnAttributes(colName, specNewColumn.Tp); err != nil { return errors.Trace(err) } @@ -1569,7 +1573,7 @@ func (d *ddl) getModifiableColumnJob(ctx sessionctx.Context, ident ast.Ident, or return nil, errors.Trace(errUnsupportedModifyColumn) } - if err = checkPointTypeColumn(specNewColumn.Name.OrigColName(), specNewColumn.Tp); err != nil { + if err = checkColumnAttributes(specNewColumn.Name.OrigColName(), specNewColumn.Tp); err != nil { return nil, errors.Trace(err) }