Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

types: support sql_mode ALLOW_INVALID_DATES (#9027) #9110

Merged
merged 3 commits into from
Jan 20, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions executor/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -1250,23 +1250,26 @@ func ResetContextOfStmt(ctx sessionctx.Context, s ast.StmtNode) (err error) {
sc.BadNullAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
sc.TruncateAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
sc.DividedByZeroAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
sc.IgnoreZeroInDate = !vars.StrictSQLMode || stmt.IgnoreErr
sc.AllowInvalidDate = vars.SQLMode.HasAllowInvalidDatesMode()
sc.IgnoreZeroInDate = !vars.StrictSQLMode || stmt.IgnoreErr || sc.AllowInvalidDate
sc.Priority = stmt.Priority
case *ast.DeleteStmt:
sc.InDeleteStmt = true
sc.DupKeyAsWarning = stmt.IgnoreErr
sc.BadNullAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
sc.TruncateAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
sc.DividedByZeroAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
sc.IgnoreZeroInDate = !vars.StrictSQLMode || stmt.IgnoreErr
sc.AllowInvalidDate = vars.SQLMode.HasAllowInvalidDatesMode()
sc.IgnoreZeroInDate = !vars.StrictSQLMode || stmt.IgnoreErr || sc.AllowInvalidDate
sc.Priority = stmt.Priority
case *ast.InsertStmt:
sc.InInsertStmt = true
sc.DupKeyAsWarning = stmt.IgnoreErr
sc.BadNullAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
sc.TruncateAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
sc.DividedByZeroAsWarning = !vars.StrictSQLMode || stmt.IgnoreErr
sc.IgnoreZeroInDate = !vars.StrictSQLMode || stmt.IgnoreErr
sc.AllowInvalidDate = vars.SQLMode.HasAllowInvalidDatesMode()
sc.IgnoreZeroInDate = !vars.StrictSQLMode || stmt.IgnoreErr || sc.AllowInvalidDate
sc.Priority = stmt.Priority
case *ast.CreateTableStmt, *ast.AlterTableStmt:
// Make sure the sql_mode is strict when checking column default value.
Expand All @@ -1287,6 +1290,7 @@ func ResetContextOfStmt(ctx sessionctx.Context, s ast.StmtNode) (err error) {
// Return warning for truncate error in selection.
sc.TruncateAsWarning = true
sc.IgnoreZeroInDate = true
sc.AllowInvalidDate = vars.SQLMode.HasAllowInvalidDatesMode()
if opts := stmt.SelectStmtOpts; opts != nil {
sc.Priority = opts.Priority
sc.NotFillCache = !opts.SQLCache
Expand All @@ -1295,13 +1299,15 @@ func ResetContextOfStmt(ctx sessionctx.Context, s ast.StmtNode) (err error) {
case *ast.ShowStmt:
sc.IgnoreTruncate = true
sc.IgnoreZeroInDate = true
sc.AllowInvalidDate = vars.SQLMode.HasAllowInvalidDatesMode()
if stmt.Tp == ast.ShowWarnings || stmt.Tp == ast.ShowErrors {
sc.InShowWarning = true
sc.SetWarnings(vars.StmtCtx.GetWarnings())
}
default:
sc.IgnoreTruncate = true
sc.IgnoreZeroInDate = true
sc.AllowInvalidDate = vars.SQLMode.HasAllowInvalidDatesMode()
}
vars.PreparedParams = vars.PreparedParams[:0]
if !vars.InRestrictedSQL {
Expand Down
37 changes: 37 additions & 0 deletions executor/insert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
package executor_test

import (
"fmt"

. "github.com/pingcap/check"
"github.com/pingcap/parser/terror"
"github.com/pingcap/tidb/table"
Expand Down Expand Up @@ -174,3 +176,38 @@ func (s *testSuite) TestInsertZeroYear(c *C) {
`2000`,
))
}

func (s *testSuite) TestAllowInvalidDates(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec(`use test`)
tk.MustExec(`drop table if exists t1, t2, t3, t4;`)
tk.MustExec(`create table t1(d date);`)
tk.MustExec(`create table t2(d datetime);`)
tk.MustExec(`create table t3(d date);`)
tk.MustExec(`create table t4(d datetime);`)

runWithMode := func(mode string) {
inputs := []string{"0000-00-00", "2019-00-00", "2019-01-00", "2019-00-01", "2019-02-31"}
results := testkit.Rows(`0 0 0`, `2019 0 0`, `2019 1 0`, `2019 0 1`, `2019 2 31`)
oldMode := tk.MustQuery(`select @@sql_mode`).Rows()[0][0]
defer func() {
tk.MustExec(fmt.Sprintf(`set sql_mode='%s'`, oldMode))
}()

tk.MustExec(`truncate t1;truncate t2;truncate t3;truncate t4;`)
tk.MustExec(fmt.Sprintf(`set sql_mode='%s';`, mode))
for _, input := range inputs {
tk.MustExec(fmt.Sprintf(`insert into t1 values ('%s')`, input))
tk.MustExec(fmt.Sprintf(`insert into t2 values ('%s')`, input))
}
tk.MustQuery(`select year(d), month(d), day(d) from t1;`).Check(results)
tk.MustQuery(`select year(d), month(d), day(d) from t2;`).Check(results)
tk.MustExec(`insert t3 select d from t1;`)
tk.MustQuery(`select year(d), month(d), day(d) from t3;`).Check(results)
tk.MustExec(`insert t4 select d from t2;`)
tk.MustQuery(`select year(d), month(d), day(d) from t4;`).Check(results)
}

runWithMode("STRICT_TRANS_TABLES,ALLOW_INVALID_DATES")
runWithMode("ALLOW_INVALID_DATES")
}
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ require (
github.com/pkg/errors v0.8.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v0.8.0
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5 // indirect
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5
github.com/prometheus/common v0.0.0-20180426121432-d811d2e9bf89 // indirect
github.com/prometheus/procfs v0.0.0-20180408092902-8b1c2da0d56d // indirect
github.com/sirupsen/logrus v0.0.0-20170323161349-3bcb09397d6d
Expand All @@ -80,3 +80,5 @@ require (
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v2 v2.2.1 // indirect
)

replace github.com/pingcap/parser => github.com/bobotu/parser v0.0.0-20190118022514-3c1c12e6a756
6 changes: 2 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ github.com/beorn7/perks v0.0.0-20160229213445-3ac7bf7a47d1 h1:OnJHjoVbY69GG4gclp
github.com/beorn7/perks v0.0.0-20160229213445-3ac7bf7a47d1/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/blacktear23/go-proxyprotocol v0.0.0-20171102103907-62e368e1c470 h1:AAFU1eDJHimRQvJGBBnhO0Cm4oe7V2GG3CLtiQk/6wg=
github.com/blacktear23/go-proxyprotocol v0.0.0-20171102103907-62e368e1c470/go.mod h1:VKt7CNAQxpFpSDz3sXyj9hY/GbVsQCr0sB3w59nE7lU=
github.com/bobotu/parser v0.0.0-20190118022514-3c1c12e6a756 h1:utTf9C0tbBZKkFWWINh7VjGcdt9EmO1VQvFMxrTg360=
github.com/bobotu/parser v0.0.0-20190118022514-3c1c12e6a756/go.mod h1:rtt+tpWlmShJj1sAXi+9oAScwFAWwM8HnLfNOSPqEig=
github.com/cockroachdb/cmux v0.0.0-20170110192607-30d10be49292 h1:dzj1/xcivGjNPwwifh/dWTczkwcuqsXXFHY1X/TZMtw=
github.com/cockroachdb/cmux v0.0.0-20170110192607-30d10be49292/go.mod h1:qRiX68mZX1lGBkTWyp3CLcenw9I94W2dLeRvMzcn9N4=
github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58 h1:hHWif/4GirK3P5uvCyyj941XSVIQDzuJhbEguCICdPE=
Expand Down Expand Up @@ -92,8 +94,6 @@ github.com/pingcap/goleveldb v0.0.0-20171020084629-8d44bfdf1030 h1:XJLuW0lsP7vAt
github.com/pingcap/goleveldb v0.0.0-20171020084629-8d44bfdf1030/go.mod h1:O17XtbryoCJhkKGbT62+L2OlrniwqiGLSqrmdHCMzZw=
github.com/pingcap/kvproto v0.0.0-20181109035735-8e3f33ac4929 h1:NAq95+VGsS2G7SjzZ5LP9iUlCMNAs13QUzbNY3G90v8=
github.com/pingcap/kvproto v0.0.0-20181109035735-8e3f33ac4929/go.mod h1:0gwbe1F2iBIjuQ9AH0DbQhL+Dpr5GofU8fgYyXk+ykk=
github.com/pingcap/parser v0.0.0-20190107034620-db064135d7b0 h1:t/xlCk9karOvR8xrq7da4FAGLo3IHhbDeSTcA6taiUc=
github.com/pingcap/parser v0.0.0-20190107034620-db064135d7b0/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA=
github.com/pingcap/parser v0.0.0-20190116142258-00e692951ce1 h1:fis1l2hPX1piYENHn5B9sMmpbUURp8l2IJJpKHP1aUk=
github.com/pingcap/parser v0.0.0-20190116142258-00e692951ce1/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA=
github.com/pingcap/pd v2.1.0-rc.4+incompatible h1:/buwGk04aHO5odk/+O8ZOXGs4qkUjYTJ2UpCJXna8NE=
Expand All @@ -120,8 +120,6 @@ github.com/spaolacci/murmur3 v0.0.0-20150829172844-0d12bf811670 h1:hKP4ACPoBBCnB
github.com/spaolacci/murmur3 v0.0.0-20150829172844-0d12bf811670/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/tiancaiamao/parser v0.0.0-20190116115114-e2ff6aa2040c h1:Jca3Kh29wy4T8etEUU+/SWbYoQHFqDJIzS0kIjuoCXU=
github.com/tiancaiamao/parser v0.0.0-20190116115114-e2ff6aa2040c/go.mod h1:vqvanuOAAZ9O2rVI51fUrA9P3nV7HoILjLby0/OKOqA=
github.com/twinj/uuid v0.0.0-20150629100731-70cac2bcd273 h1:YqFyfcgqxQqjpRr0SEG0Z555J/3kPqDL/xmRyeAaX/0=
github.com/twinj/uuid v0.0.0-20150629100731-70cac2bcd273/go.mod h1:mMgcE1RHFUFqe5AfiwlINXisXfDGro23fWdPUfOMjRY=
github.com/uber/jaeger-client-go v2.8.0+incompatible h1:7DGH8Hqk6PirD+GE+bvCf0cLnspLuae7N1NcwMeQcyg=
Expand Down
1 change: 1 addition & 0 deletions sessionctx/stmtctx/stmtctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ type StatementContext struct {
PadCharToFullLength bool
BatchCheck bool
InNullRejectCheck bool
AllowInvalidDate bool

// mu struct holds variables that change during execution.
mu struct {
Expand Down
28 changes: 16 additions & 12 deletions types/time.go
Original file line number Diff line number Diff line change
Expand Up @@ -474,18 +474,20 @@ func (t *Time) FromPackedUint(packed uint64) error {
// FIXME: See https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_zero_in_date
func (t *Time) check(sc *stmtctx.StatementContext) error {
allowZeroInDate := false
allowInvalidDate := false
// We should avoid passing sc as nil here as far as possible.
if sc != nil {
allowZeroInDate = sc.IgnoreZeroInDate
allowInvalidDate = sc.AllowInvalidDate
}
var err error
switch t.Type {
case mysql.TypeTimestamp:
err = checkTimestampType(sc, t.Time)
case mysql.TypeDatetime:
err = checkDatetimeType(t.Time, allowZeroInDate)
err = checkDatetimeType(t.Time, allowZeroInDate, allowInvalidDate)
case mysql.TypeDate:
err = checkDateType(t.Time, allowZeroInDate)
err = checkDateType(t.Time, allowZeroInDate, allowInvalidDate)
}
return errors.Trace(err)
}
Expand Down Expand Up @@ -1341,7 +1343,7 @@ func TimeFromDays(num int64) Time {
}
}

func checkDateType(t MysqlTime, allowZeroInDate bool) error {
func checkDateType(t MysqlTime, allowZeroInDate, allowInvalidDate bool) error {
year, month, day := t.Year(), t.Month(), t.Day()
if year == 0 && month == 0 && day == 0 {
return nil
Expand All @@ -1355,7 +1357,7 @@ func checkDateType(t MysqlTime, allowZeroInDate bool) error {
return errors.Trace(err)
}

if err := checkMonthDay(year, month, day); err != nil {
if err := checkMonthDay(year, month, day, allowInvalidDate); err != nil {
return errors.Trace(err)
}

Expand All @@ -1374,17 +1376,19 @@ func checkDateRange(t MysqlTime) error {
return nil
}

func checkMonthDay(year, month, day int) error {
func checkMonthDay(year, month, day int, allowInvalidDate bool) error {
if month < 0 || month > 12 {
return errors.Trace(ErrInvalidTimeFormat.GenWithStackByArgs(month))
}

maxDay := 31
if month > 0 {
maxDay = maxDaysInMonth[month-1]
}
if month == 2 && year%4 != 0 {
maxDay = 28
if !allowInvalidDate {
if month > 0 {
maxDay = maxDaysInMonth[month-1]
}
if month == 2 && year%4 != 0 {
maxDay = 28
}
}

if day < 0 || day > maxDay {
Expand Down Expand Up @@ -1424,8 +1428,8 @@ func checkTimestampType(sc *stmtctx.StatementContext, t MysqlTime) error {
return nil
}

func checkDatetimeType(t MysqlTime, allowZeroInDate bool) error {
if err := checkDateType(t, allowZeroInDate); err != nil {
func checkDatetimeType(t MysqlTime, allowZeroInDate, allowInvalidDate bool) error {
if err := checkDateType(t, allowZeroInDate, allowInvalidDate); err != nil {
return errors.Trace(err)
}

Expand Down
7 changes: 7 additions & 0 deletions vendor/github.com/pingcap/parser/mysql/const.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ github.com/pingcap/kvproto/pkg/tikvpb
github.com/pingcap/kvproto/pkg/pdpb
github.com/pingcap/kvproto/pkg/raft_serverpb
github.com/pingcap/kvproto/pkg/eraftpb
# github.com/pingcap/parser v0.0.0-20190116142258-00e692951ce1
# github.com/pingcap/parser v0.0.0-20190116142258-00e692951ce1 => github.com/bobotu/parser v0.0.0-20190118022514-3c1c12e6a756
github.com/pingcap/parser/auth
github.com/pingcap/parser/model
github.com/pingcap/parser/mysql
Expand Down