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

expression: QUARTER/DATE_FORMAT compatibility with mysql for 0/0.0 values #12488

Merged
merged 63 commits into from
Nov 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
22ce5bf
Better 'querter' compatibility with mysql
ekalinin Sep 29, 2019
a2d95a3
expression: moved special 0 case from builtinCastIntAsTimeSig to Pars…
ekalinin Oct 1, 2019
39adb3f
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 1, 2019
5fb4926
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 3, 2019
c8f753c
Better 'querter' compatibility with mysql
ekalinin Sep 29, 2019
cb46879
expression: moved special 0 case from builtinCastIntAsTimeSig to Pars…
ekalinin Oct 1, 2019
ed242d7
Better 'querter' compatibility with mysql
ekalinin Sep 29, 2019
c5593bb
expression: moved special 0 case from builtinCastIntAsTimeSig to Pars…
ekalinin Oct 1, 2019
6e1d841
Merge branch 'mysql-compat-quarter' of github.com:ekalinin/tidb into …
ekalinin Oct 3, 2019
97bf1ca
expression: DATE_FORMAT compat with mysql for 0/0.0
ekalinin Oct 3, 2019
1b06019
expression: DATE_FORMAT compat with mysql for 0/0.0 (fixed comment)
ekalinin Oct 3, 2019
419935c
Merge branch 'master' into mysql-compat-quarter
zz-jason Oct 8, 2019
430cceb
expression: moved special case for 0.0 from builtinCastDecimalAsTimeS…
ekalinin Oct 8, 2019
7229e00
expression: DATE_FORMAT compat with mysql for 0 format mask
ekalinin Oct 8, 2019
398f5bb
expression: restored origin formating
ekalinin Oct 8, 2019
733fee1
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 9, 2019
a0d975f
expression: added special case for 0 into builtinCastRealAsTimeSig
ekalinin Oct 10, 2019
a99ad63
Merge branch 'mysql-compat-quarter' of github.com:ekalinin/tidb into …
ekalinin Oct 10, 2019
1b33438
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 10, 2019
4e81ace
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 11, 2019
c163898
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 11, 2019
a2248a8
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 11, 2019
b53eafb
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 12, 2019
58a7f09
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 13, 2019
79bf904
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 14, 2019
d313c6a
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 14, 2019
068816a
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 14, 2019
6723c9c
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 14, 2019
54cd4a0
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 14, 2019
3113798
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 14, 2019
2f2d1ce
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 15, 2019
fa343eb
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 16, 2019
7b4e0ba
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 17, 2019
91df796
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 17, 2019
e43d754
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 18, 2019
002ff85
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 18, 2019
63c0753
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 18, 2019
16a670a
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 20, 2019
e86c56c
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 21, 2019
f23500a
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 21, 2019
5eeeaea
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 21, 2019
c63b7ac
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 22, 2019
477361e
Merge branch 'master' into mysql-compat-quarter
XuHuaiyu Oct 23, 2019
ebd4921
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 23, 2019
931c4ab
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 23, 2019
57f04b6
Merge branch 'mysql-compat-quarter' of github.com:ekalinin/tidb into …
ekalinin Oct 23, 2019
9bfb59f
expression: fixes after review
ekalinin Oct 23, 2019
b091309
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 24, 2019
c017edd
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 25, 2019
771a588
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 28, 2019
f0a919d
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 29, 2019
ea22676
expression: fixed 0.0* in ParseTimeFromFloatString
ekalinin Oct 29, 2019
b544b8f
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 30, 2019
ef613ee
Merge branch 'master' into mysql-compat-quarter
ekalinin Oct 31, 2019
3a0ec2b
Merge branch 'master' into mysql-compat-quarter
ekalinin Nov 1, 2019
23b2bc2
Merge branch 'master' into mysql-compat-quarter
ekalinin Nov 1, 2019
8a0858b
Merge branch 'master' into mysql-compat-quarter
ekalinin Nov 5, 2019
7e9a3ce
Merge branch 'master' into mysql-compat-quarter
ekalinin Nov 6, 2019
c3a8e8a
Merge branch 'master' into mysql-compat-quarter
sre-bot Nov 9, 2019
23604d5
Merge branch 'master' into mysql-compat-quarter
ekalinin Nov 9, 2019
58d3439
Merge branch 'master' into mysql-compat-quarter
ekalinin Nov 9, 2019
6c691e7
Merge branch 'master' into mysql-compat-quarter
sykp241095 Nov 9, 2019
7986ec6
Merge branch 'master' into mysql-compat-quarter
ngaut Nov 9, 2019
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
7 changes: 6 additions & 1 deletion expression/builtin_cast.go
Original file line number Diff line number Diff line change
Expand Up @@ -823,8 +823,13 @@ func (b *builtinCastRealAsTimeSig) evalTime(row chunk.Row) (types.Time, bool, er
if isNull || err != nil {
return types.Time{}, true, err
}
// MySQL compatibility: 0 should not be converted to null, see #11203
fv := strconv.FormatFloat(val, 'f', -1, 64)
ekalinin marked this conversation as resolved.
Show resolved Hide resolved
if fv == "0" {
return types.Time{}, false, nil
}
sc := b.ctx.GetSessionVars().StmtCtx
res, err := types.ParseTime(sc, strconv.FormatFloat(val, 'f', -1, 64), b.tp.Tp, int8(b.tp.Decimal))
res, err := types.ParseTime(sc, fv, b.tp.Tp, int8(b.tp.Decimal))
if err != nil {
return types.Time{}, true, handleInvalidTimeError(b.ctx, err)
}
Expand Down
30 changes: 27 additions & 3 deletions expression/builtin_time.go
Original file line number Diff line number Diff line change
Expand Up @@ -791,13 +791,28 @@ func (b *builtinDateFormatSig) evalString(row chunk.Row) (string, bool, error) {
if isNull || err != nil {
return "", isNull, handleInvalidTimeError(b.ctx, err)
}
if t.InvalidZero() {
return "", true, handleInvalidTimeError(b.ctx, types.ErrIncorrectDatetimeValue.GenWithStackByArgs(t.String()))
}
formatMask, isNull, err := b.args[1].EvalString(b.ctx, row)
if isNull || err != nil {
return "", isNull, err
}
// MySQL compatibility, #11203
// If format mask is 0 then return 0 without warnings
if formatMask == "0" {
return "0", false, nil
}

if t.InvalidZero() {
// MySQL compatibility, #11203
// 0 | 0.0 should be converted to null without warnings
n, isNullInt, errInt := b.args[0].EvalInt(b.ctx, row)
isOriginalIntOrDecimalZero := n == 0 && !isNullInt && errInt == nil
// Args like "0000-00-00", "0000-00-00 00:00:00" set Fsp to 6
isOriginalStringZero := t.Fsp > 0
if isOriginalIntOrDecimalZero && !isOriginalStringZero {
return "", true, nil
}
return "", true, handleInvalidTimeError(b.ctx, types.ErrIncorrectDatetimeValue.GenWithStackByArgs(t.String()))
}

res, err := t.DateFormat(formatMask)
return res, isNull, err
Expand Down Expand Up @@ -5544,6 +5559,15 @@ func (b *builtinQuarterSig) evalInt(row chunk.Row) (int64, bool, error) {
}

if date.IsZero() {
// MySQL compatibility, #11203
// 0 | 0.0 should be converted to 0 value (not null)
n, err := date.ToNumber().ToInt()
isOriginalIntOrDecimalZero := err == nil && n == 0
// Args like "0000-00-00", "0000-00-00 00:00:00" set Fsp to 6
ekalinin marked this conversation as resolved.
Show resolved Hide resolved
isOriginalStringZero := date.Fsp > 0
if isOriginalIntOrDecimalZero && !isOriginalStringZero {
return 0, false, nil
}
return 0, true, handleInvalidTimeError(b.ctx, types.ErrIncorrectDatetimeValue.GenWithStackByArgs(date.String()))
}

Expand Down
22 changes: 20 additions & 2 deletions expression/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1282,8 +1282,16 @@ func (s *testIntegrationSuite2) TestTimeBuiltin(c *C) {
// for quarter
result = tk.MustQuery(`select quarter("2012-00-20"), quarter("2012-01-21"), quarter("2012-03-22"), quarter("2012-05-23"), quarter("2012-08-24"), quarter("2012-09-25"), quarter("2012-11-26"), quarter("2012-12-27");`)
result.Check(testkit.Rows("0 1 1 2 3 3 4 4"))
result = tk.MustQuery(`select quarter("2012-14-20"), quarter("0000-00-00"), quarter("aa"), quarter(null), quarter(11), quarter(12.99);`)
result.Check(testkit.Rows("<nil> <nil> <nil> <nil> <nil> <nil>"))
result = tk.MustQuery(`select quarter("2012-14-20"), quarter("aa"), quarter(null), quarter(11), quarter(12.99);`)
result.Check(testkit.Rows("<nil> <nil> <nil> <nil> <nil>"))
result = tk.MustQuery(`select quarter("0000-00-00"), quarter("0000-00-00 00:00:00");`)
result.Check(testkit.Rows("<nil> <nil>"))
tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|",
"Warning|1292|Incorrect datetime value: '0000-00-00 00:00:00.000000'",
"Warning|1292|Incorrect datetime value: '0000-00-00 00:00:00.000000'"))
result = tk.MustQuery(`select quarter(0), quarter(0.0), quarter(0e1), quarter(0.00);`)
result.Check(testkit.Rows("0 0 0 0"))
tk.MustQuery("show warnings").Check(testkit.Rows())

// for from_days
result = tk.MustQuery(`select from_days(0), from_days(-199), from_days(1111), from_days(120), from_days(1), from_days(1111111), from_days(9999999), from_days(22222);`)
Expand Down Expand Up @@ -1634,6 +1642,16 @@ func (s *testIntegrationSuite2) TestTimeBuiltin(c *C) {
result.Check(testkit.Rows("Friday November 13 2015 10:20:19 AM 15"))
result = tk.MustQuery(`SELECT DATE_FORMAT('0000-00-00', '%W %M %e %Y %r %y');`)
result.Check(testkit.Rows("<nil>"))
tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|",
"Warning|1292|Incorrect datetime value: '0000-00-00 00:00:00.000000'"))
result = tk.MustQuery(`SELECT DATE_FORMAT('0', '%W %M %e %Y %r %y'), DATE_FORMAT('0.0', '%W %M %e %Y %r %y'), DATE_FORMAT(0, 0);`)
result.Check(testkit.Rows("<nil> <nil> 0"))
tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|",
"Warning|1292|invalid time format: '0'",
"Warning|1292|invalid time format: '0.0'"))
result = tk.MustQuery(`SELECT DATE_FORMAT(0, '%W %M %e %Y %r %y'), DATE_FORMAT(0.0, '%W %M %e %Y %r %y');`)
result.Check(testkit.Rows("<nil> <nil>"))
tk.MustQuery("show warnings").Check(testkit.Rows())

// for yearweek
result = tk.MustQuery(`select yearweek("2014-12-27"), yearweek("2014-29-27"), yearweek("2014-00-27"), yearweek("2014-12-27 12:38:32"), yearweek("2014-12-27 12:38:32.1111111"), yearweek("2014-12-27 12:90:32"), yearweek("2014-12-27 89:38:32.1111111");`)
Expand Down
8 changes: 8 additions & 0 deletions types/time.go
Original file line number Diff line number Diff line change
Expand Up @@ -1355,6 +1355,10 @@ func ParseTime(sc *stmtctx.StatementContext, str string, tp byte, fsp int8) (Tim

// ParseTimeFromFloatString is similar to ParseTime, except that it's used to parse a float converted string.
func ParseTimeFromFloatString(sc *stmtctx.StatementContext, str string, tp byte, fsp int8) (Time, error) {
// MySQL compatibility: 0.0 should not be converted to null, see #11203
if len(str) >= 3 && str[:3] == "0.0" {
return Time{Time: ZeroTime, Type: tp}, nil
}
return parseTime(sc, str, tp, fsp, true)
}

Expand Down Expand Up @@ -1395,6 +1399,10 @@ func ParseDate(sc *stmtctx.StatementContext, str string) (Time, error) {
// ParseTimeFromNum parses a formatted int64,
// returns the value which type is tp.
func ParseTimeFromNum(sc *stmtctx.StatementContext, num int64, tp byte, fsp int8) (Time, error) {
// MySQL compatibility: 0 should not be converted to null, see #11203
if num == 0 {
return Time{Time: ZeroTime, Type: tp}, nil
}
fsp, err := CheckFsp(int(fsp))
if err != nil {
return Time{Time: ZeroTime, Type: tp}, errors.Trace(err)
Expand Down