Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
7c6be64
add day tests, move log tests out of broken tests section
angelamayxie Nov 13, 2025
cbfb02c
add more tests, clean ups
angelamayxie Nov 13, 2025
1b24b75
new value for zeroTime, update tests, add more datetime function test…
angelamayxie Nov 13, 2025
0d42aa0
add query test for 0000-01-01 timestamp
angelamayxie Nov 13, 2025
bce68e6
day function has been fixed
angelamayxie Nov 13, 2025
9a812be
making more progress on getting tests to pass
angelamayxie Nov 14, 2025
76cb5d0
fix monthname
angelamayxie Nov 14, 2025
ed696d2
fix week, modify getDate to use evaluated value
angelamayxie Nov 14, 2025
8acd85d
fix weekday, add warnings to getDatePart
angelamayxie Nov 14, 2025
2330e41
fix weekofyear
angelamayxie Nov 14, 2025
ae3a154
fix yearweek, update test case for quarter
angelamayxie Nov 14, 2025
713f050
fix int values for extract week
angelamayxie Nov 14, 2025
50a441f
update quarter zero timestamp test
angelamayxie Nov 14, 2025
f449846
fix to_days function
angelamayxie Nov 14, 2025
700dd84
fix quarter
angelamayxie Nov 14, 2025
e839a23
update time function tests
angelamayxie Nov 14, 2025
50099a5
update zeroTime value in tests
angelamayxie Nov 14, 2025
ccedfeb
[ga-format-pr] Run ./format_repo.sh to fix formatting
angelamayxie Nov 14, 2025
855df22
simplify microsecond function
angelamayxie Nov 14, 2025
abfb060
Merge branch 'main' of https://github.com/dolthub/go-mysql-server int…
angelamayxie Nov 14, 2025
b207193
update and add more tests
angelamayxie Nov 14, 2025
069ac91
Merge branch 'angela/date_functions' of https://github.com/dolthub/go…
angelamayxie Nov 14, 2025
f235adf
[ga-format-pr] Run ./format_repo.sh to fix formatting
angelamayxie Nov 14, 2025
da0a99d
update microseconds test to be less flaky
angelamayxie Nov 15, 2025
82e17dd
Merge branch 'angela/date_functions' of https://github.com/dolthub/go…
angelamayxie Nov 15, 2025
06b56ec
add extract tests
angelamayxie Nov 17, 2025
fd6b865
add more extract tests
angelamayxie Nov 17, 2025
4638265
fix extract functions
angelamayxie Nov 17, 2025
e4f775b
fix date function
angelamayxie Nov 17, 2025
2047b55
add mysql dialect tag
angelamayxie Nov 17, 2025
8d1d4b4
fix more time functions
angelamayxie Nov 17, 2025
ed21f64
fix missing
angelamayxie Nov 17, 2025
718eb86
update date function to allow for zero time
angelamayxie Nov 17, 2025
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
712 changes: 702 additions & 10 deletions enginetest/queries/function_queries.go

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions enginetest/queries/insert_queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -2349,6 +2349,26 @@ var InsertScripts = []ScriptTest{
},
},
},
{
Name: "inserting zero date",
Dialect: "mysql",
SetUpScript: []string{
"create table t(d date)",
"insert into t values ('0000-00-00')",
"create table t2(d datetime)",
"insert into t2 values ('0000-00-00')",
},
Assertions: []ScriptTestAssertion{
{
Query: "select * from t",
Expected: []sql.Row{{types.ZeroTime}},
},
{
Query: "select * from t2",
Expected: []sql.Row{{types.ZeroTime}},
},
},
},
}

var InsertDuplicateKeyKeyless = []ScriptTest{
Expand Down
7 changes: 0 additions & 7 deletions enginetest/queries/queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -8352,13 +8352,6 @@ from typestable`,
},
},
},
{
// TODO: This goes past MySQL's range
Query: "select dayname('0000-00-00')",
Expected: []sql.Row{
{"Saturday"},
},
},
{
Query: "select * from mytable order by dayname(i)",
Expected: []sql.Row{
Expand Down
6 changes: 3 additions & 3 deletions enginetest/queries/script_queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -6175,10 +6175,10 @@ CREATE TABLE tab3 (
"0",
float64(0),
float64(0),
time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC),
time.Date(0, 0, 0, 0, 0, 0, 0, time.UTC),
types.Timespan(0),
time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC),
time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC),
time.Date(0, 0, 0, 0, 0, 0, 0, time.UTC),
time.Date(0, 0, 0, 0, 0, 0, 0, time.UTC),
0,
"",
"",
Expand Down
2 changes: 1 addition & 1 deletion enginetest/queries/update_queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -1011,7 +1011,7 @@ var UpdateErrorScripts = []ScriptTest{
},
}

var ZeroTime = time.Date(0000, time.January, 1, 0, 0, 0, 0, time.UTC)
var ZeroTime = time.Date(0000, 0, 0, 0, 0, 0, 0, time.UTC)
var Jan1Noon = time.Date(2000, time.January, 1, 12, 0, 0, 0, time.UTC)
var Dec15_1_30 = time.Date(2023, time.December, 15, 1, 30, 0, 0, time.UTC)
var Oct2Midnight = time.Date(2020, time.October, 2, 0, 0, 0, 0, time.UTC)
Expand Down
13 changes: 13 additions & 0 deletions sql/expression/arithmetic.go
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,13 @@ func convertValueToType(ctx *sql.Context, typ sql.Type, val interface{}, isTimeT
// the value is interpreted as 0, but we need to match the type of the other valid value
// to avoid additional conversion, the nil value is handled in each operation
}
if types.IsTime(typ) {
time, ok := cval.(time.Time)
if !ok || time.Equal(types.ZeroTime) {
ctx.Warn(1292, "Incorrect datetime value: '%s'", val)
return nil
}
}
return cval
}

Expand All @@ -462,6 +469,9 @@ func convertTimeTypeToString(val interface{}) interface{} {
}

func plus(lval, rval interface{}) (interface{}, error) {
if lval == nil || rval == nil {
return nil, nil
}
switch l := lval.(type) {
case uint8:
switch r := rval.(type) {
Expand Down Expand Up @@ -536,6 +546,9 @@ func plus(lval, rval interface{}) (interface{}, error) {
}

func minus(lval, rval interface{}) (interface{}, error) {
if lval == nil || rval == nil {
return nil, nil
}
switch l := lval.(type) {
case uint8:
switch r := rval.(type) {
Expand Down
3 changes: 3 additions & 0 deletions sql/expression/function/days.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ func (t *ToDays) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
return nil, nil
}
d := date.(time.Time)
if d.Equal(types.ZeroTime) {
return nil, nil
}

// Using zeroTime.Sub(date) doesn't work because it overflows time.Duration
// so we need to calculate the number of days manually
Expand Down
5 changes: 4 additions & 1 deletion sql/expression/function/days_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ func TestToDays(t *testing.T) {
arg: expression.NewLiteral("-10", types.Int32),
exp: nil,
},

{
arg: expression.NewLiteral("0", types.Int32),
exp: nil,
},
{
arg: expression.NewLiteral("0000-00-00", types.Text),
exp: nil,
Expand Down
66 changes: 40 additions & 26 deletions sql/expression/function/extract.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func (td *Extract) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {

switch unit {
case "DAY":
return dateTime.Day(), nil
return day(dateTime), nil
case "HOUR":
return dateTime.Hour(), nil
case "MINUTE":
Expand All @@ -124,57 +124,66 @@ func (td *Extract) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
case "MICROSECOND":
return dateTime.Nanosecond() / 1000, nil
case "QUARTER":
return (int(dateTime.Month())-1)/3 + 1, nil
return quarter(dateTime), nil
case "MONTH":
return int(dateTime.Month()), nil
return month(dateTime), nil
case "WEEK":
date, err := getDate(ctx, expression.UnaryExpression{Child: td.RightChild}, row)
if err != nil {
return nil, err
}
yyyy, ok := year(date).(int32)
yyyy, ok := year(dateTime).(int)
if !ok {
return nil, sql.ErrInvalidArgumentDetails.New("WEEK", "invalid year")
}
mm, ok := month(date).(int32)
mm, ok := month(dateTime).(int)
if !ok {
return nil, sql.ErrInvalidArgumentDetails.New("WEEK", "invalid month")
}
dd, ok := day(date).(int32)
dd, ok := day(dateTime).(int)
if !ok {
return nil, sql.ErrInvalidArgumentDetails.New("WEEK", "invalid day")
}
yearForWeek, week := calcWeek(yyyy, mm, dd, weekBehaviourYear)
if yearForWeek < yyyy {
yr := int32(yyyy)
yearForWeek, week := calcWeek(yr, int32(mm), int32(dd), weekBehaviourYear)
if yearForWeek < yr {
week = 0
} else if yearForWeek > yyyy {
} else if yearForWeek > yr {
week = 53
}
return int(week), nil
case "YEAR":
return dateTime.Year(), nil
return year(dateTime), nil
case "DAY_HOUR":
dd := dateTime.Day() * 1_00
dd, ok := day(dateTime).(int)
if !ok {
return nil, sql.ErrInvalidArgumentDetails.New("DAY_HOUR", "invalid day")
}
hh := dateTime.Hour()
return dd + hh, nil
return (dd * 1_00) + hh, nil
case "DAY_MINUTE":
dd := dateTime.Day() * 1_00_00
dd, ok := day(dateTime).(int)
if !ok {
return nil, sql.ErrInvalidArgumentDetails.New("DAY_MINUTE", "invalid day")
}
hh := dateTime.Hour() * 1_00
mm := dateTime.Minute()
return dd + hh + mm, nil
return (dd * 1_00_00) + hh + mm, nil
case "DAY_SECOND":
dd := dateTime.Day() * 1_00_00_00
dd, ok := day(dateTime).(int)
if !ok {
return nil, sql.ErrInvalidArgumentDetails.New("DAY_SECOND", "invalid day")
}
hh := dateTime.Hour() * 1_00_00
mm := dateTime.Minute() * 1_00
ss := dateTime.Second()
return dd + hh + mm + ss, nil
return (dd * 1_00_00_00) + hh + mm + ss, nil
case "DAY_MICROSECOND":
dd := dateTime.Day() * 1_00_00_00_000000
dd, ok := day(dateTime).(int)
if !ok {
return nil, sql.ErrInvalidArgumentDetails.New("DAY_MICROSECOND", "invalid day")
}
hh := dateTime.Hour() * 1_00_00_000000
mm := dateTime.Minute() * 1_00_000000
ss := dateTime.Second() * 1_000000
mmmmmm := dateTime.Nanosecond() / 1000
return dd + hh + mm + ss + mmmmmm, nil
return (dd * 1_00_00_00_000000) + hh + mm + ss + mmmmmm, nil
case "HOUR_MINUTE":
hh := dateTime.Hour() * 1_00
mm := dateTime.Minute()
Expand Down Expand Up @@ -204,10 +213,15 @@ func (td *Extract) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
mmmmmm := dateTime.Nanosecond() / 1000
return ss + mmmmmm, nil
case "YEAR_MONTH":
yyyy := dateTime.Year() * 1_00
dateTime.Month()
mm := int(dateTime.Month())
return yyyy + mm, nil
yyyy, ok := year(dateTime).(int)
if !ok {
return nil, sql.ErrInvalidArgumentDetails.New("YEAR_MONTH", "invalid year")
}
mm, ok := month(dateTime).(int)
if !ok {
return nil, sql.ErrInvalidArgumentDetails.New("YEAR_MONTH", "invalid month")
}
return (yyyy * 1_00) + mm, nil
default:
return nil, fmt.Errorf("invalid time unit")
}
Expand Down
2 changes: 1 addition & 1 deletion sql/expression/function/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,6 @@ var BuiltIns = []sql.Function{
sql.Function0{Name: "uuid", Fn: NewUUIDFunc},
sql.Function0{Name: "uuid_short", Fn: NewUUIDShortFunc},
sql.FunctionN{Name: "uuid_to_bin", Fn: NewUUIDToBin},
sql.FunctionN{Name: "week", Fn: NewWeek},
sql.Function1{Name: "values", Fn: NewValues},
sql.Function1{Name: "validate_password_strength", Fn: NewValidatePasswordStrength},
sql.Function1{Name: "variance", Fn: func(e sql.Expression) sql.Expression { return aggregation.NewVarPop(e) }},
Expand All @@ -338,6 +337,7 @@ var BuiltIns = []sql.Function{
sql.Function1{Name: "vector_to_string", Fn: vector.NewVectorToString},
sql.Function1{Name: "from_vector", Fn: vector.NewVectorToString},
sql.Function1{Name: "vec_totext", Fn: vector.NewVectorToString},
sql.FunctionN{Name: "week", Fn: NewWeek},
sql.Function1{Name: "weekday", Fn: NewWeekday},
sql.Function1{Name: "weekofyear", Fn: NewWeekOfYear},
sql.Function1{Name: "year", Fn: NewYear},
Expand Down
Loading
Loading