github.com/dolthub/go-mysql-server@v0.18.0/sql/expression/function/time_test.go (about)

     1  // Copyright 2020-2021 Dolthub, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package function
    16  
    17  import (
    18  	"fmt"
    19  	"testing"
    20  	"time"
    21  
    22  	"github.com/stretchr/testify/assert"
    23  	"github.com/stretchr/testify/require"
    24  
    25  	"github.com/dolthub/go-mysql-server/sql"
    26  	"github.com/dolthub/go-mysql-server/sql/expression"
    27  	"github.com/dolthub/go-mysql-server/sql/types"
    28  )
    29  
    30  const (
    31  	tsDate     = 1258882545 // Sunday, November 22, 2009 10:35:45 PM GMT+01:00
    32  	stringDate = "2007-01-02 14:15:16"
    33  )
    34  
    35  // TODO: look over all of the "invalid type" tests later, ignoring them for now since they're unlikely to be hit
    36  func TestTime_Year(t *testing.T) {
    37  	ctx := sql.NewEmptyContext()
    38  	f := NewYear(expression.NewGetField(0, types.LongText, "foo", false))
    39  
    40  	testCases := []struct {
    41  		name     string
    42  		row      sql.Row
    43  		expected interface{}
    44  		err      bool
    45  	}{
    46  		{"invalid type", sql.NewRow([]byte{0, 1, 2}), nil, false},
    47  		{"date as string", sql.NewRow(stringDate), int32(2007), false},
    48  		{"date as time", sql.NewRow(time.Now()), int32(time.Now().UTC().Year()), false},
    49  	}
    50  
    51  	for _, tt := range testCases {
    52  		t.Run(tt.name, func(t *testing.T) {
    53  			require := require.New(t)
    54  			val, err := f.Eval(ctx, tt.row)
    55  			if tt.err {
    56  				require.Error(err)
    57  			} else {
    58  				require.NoError(err)
    59  				require.Equal(tt.expected, val)
    60  			}
    61  		})
    62  	}
    63  }
    64  
    65  func TestTime_Month(t *testing.T) {
    66  	ctx := sql.NewEmptyContext()
    67  	f := NewMonth(expression.NewGetField(0, types.LongText, "foo", false))
    68  
    69  	testCases := []struct {
    70  		name     string
    71  		row      sql.Row
    72  		expected interface{}
    73  		err      bool
    74  	}{
    75  		{"null date", sql.NewRow(nil), nil, false},
    76  		{"invalid type", sql.NewRow([]byte{0, 1, 2}), nil, false},
    77  		{"date as string", sql.NewRow(stringDate), int32(1), false},
    78  		{"date as time", sql.NewRow(time.Now()), int32(time.Now().UTC().Month()), false},
    79  	}
    80  
    81  	for _, tt := range testCases {
    82  		t.Run(tt.name, func(t *testing.T) {
    83  			require := require.New(t)
    84  			val, err := f.Eval(ctx, tt.row)
    85  			if tt.err {
    86  				require.Error(err)
    87  			} else {
    88  				require.NoError(err)
    89  				require.Equal(tt.expected, val)
    90  			}
    91  		})
    92  	}
    93  }
    94  
    95  func TestTime_Quarter(t *testing.T) {
    96  	ctx := sql.NewEmptyContext()
    97  	f := NewQuarter(expression.NewGetField(0, types.LongText, "foo", false))
    98  
    99  	testCases := []struct {
   100  		name     string
   101  		row      sql.Row
   102  		expected interface{}
   103  		err      bool
   104  	}{
   105  		{
   106  			name:     "null date",
   107  			row:      sql.NewRow(nil),
   108  			expected: nil,
   109  		},
   110  		{
   111  			name:     "1",
   112  			row:      sql.NewRow(1),
   113  			expected: nil,
   114  		},
   115  		{
   116  			name:     "1.1",
   117  			row:      sql.NewRow(1.1),
   118  			expected: nil,
   119  		},
   120  		{
   121  			name:     "invalid type",
   122  			row:      sql.NewRow([]byte{0, 1, 2}),
   123  			expected: nil,
   124  		},
   125  		{
   126  			name:     "date as string",
   127  			row:      sql.NewRow(stringDate),
   128  			expected: int32(1),
   129  		},
   130  		{
   131  			name:     "another date as string",
   132  			row:      sql.NewRow("2008-08-01"),
   133  			expected: int32(3),
   134  		},
   135  		{
   136  			name:     "january",
   137  			row:      sql.NewRow("2008-01-01"),
   138  			expected: int32(1),
   139  		},
   140  		{
   141  			name:     "february",
   142  			row:      sql.NewRow("2008-02-01"),
   143  			expected: int32(1),
   144  		},
   145  		{
   146  			name:     "march",
   147  			row:      sql.NewRow("2008-03-01"),
   148  			expected: int32(1),
   149  		},
   150  		{
   151  			name:     "april",
   152  			row:      sql.NewRow("2008-04-01"),
   153  			expected: int32(2),
   154  		},
   155  		{
   156  			name:     "may",
   157  			row:      sql.NewRow("2008-05-01"),
   158  			expected: int32(2),
   159  		},
   160  		{
   161  			name:     "june",
   162  			row:      sql.NewRow("2008-06-01"),
   163  			expected: int32(2),
   164  		},
   165  		{
   166  			name:     "july",
   167  			row:      sql.NewRow("2008-07-01"),
   168  			expected: int32(3),
   169  		},
   170  		{
   171  			name:     "august",
   172  			row:      sql.NewRow("2008-08-01"),
   173  			expected: int32(3),
   174  		},
   175  		{
   176  			name:     "septemeber",
   177  			row:      sql.NewRow("2008-09-01"),
   178  			expected: int32(3),
   179  		},
   180  		{
   181  			name:     "october",
   182  			row:      sql.NewRow("2008-10-01"),
   183  			expected: int32(4),
   184  		},
   185  		{
   186  			name:     "november",
   187  			row:      sql.NewRow("2008-11-01"),
   188  			expected: int32(4),
   189  		},
   190  		{
   191  			name:     "december",
   192  			row:      sql.NewRow("2008-12-01"),
   193  			expected: int32(4),
   194  		},
   195  		{
   196  			name:     "date as time",
   197  			row:      sql.NewRow(time.Now()),
   198  			expected: int32((time.Now().UTC().Month()-1)/3 + 1),
   199  		},
   200  	}
   201  
   202  	for _, tt := range testCases {
   203  		t.Run(tt.name, func(t *testing.T) {
   204  			require := require.New(t)
   205  			val, err := f.Eval(ctx, tt.row)
   206  			if tt.err {
   207  				require.Error(err)
   208  			} else {
   209  				require.NoError(err)
   210  				require.Equal(tt.expected, val)
   211  			}
   212  		})
   213  	}
   214  }
   215  
   216  func TestTime_Day(t *testing.T) {
   217  	ctx := sql.NewEmptyContext()
   218  	f := NewDay(expression.NewGetField(0, types.LongText, "foo", false))
   219  
   220  	testCases := []struct {
   221  		name     string
   222  		row      sql.Row
   223  		expected interface{}
   224  		err      bool
   225  	}{
   226  		{"null date", sql.NewRow(nil), nil, false},
   227  		{"invalid type", sql.NewRow([]byte{0, 1, 2}), nil, false},
   228  		{"date as string", sql.NewRow(stringDate), int32(2), false},
   229  		{"date as time", sql.NewRow(time.Now()), int32(time.Now().UTC().Day()), false},
   230  	}
   231  
   232  	for _, tt := range testCases {
   233  		t.Run(tt.name, func(t *testing.T) {
   234  			require := require.New(t)
   235  			val, err := f.Eval(ctx, tt.row)
   236  			if tt.err {
   237  				require.Error(err)
   238  			} else {
   239  				require.NoError(err)
   240  				require.Equal(tt.expected, val)
   241  			}
   242  		})
   243  	}
   244  }
   245  
   246  func TestTime_Weekday(t *testing.T) {
   247  	ctx := sql.NewEmptyContext()
   248  	f := NewWeekday(expression.NewGetField(0, types.LongText, "foo", false))
   249  
   250  	testCases := []struct {
   251  		name     string
   252  		row      sql.Row
   253  		expected interface{}
   254  		err      bool
   255  	}{
   256  		{"null date", sql.NewRow(nil), nil, false},
   257  		{"invalid type", sql.NewRow([]byte{0, 1, 2}), nil, false},
   258  		{"date as string", sql.NewRow(stringDate), int32(1), false},
   259  		{"date as time", sql.NewRow(time.Now()), int32(time.Now().UTC().Weekday()+6) % 7, false},
   260  	}
   261  
   262  	for _, tt := range testCases {
   263  		t.Run(tt.name, func(t *testing.T) {
   264  			require := require.New(t)
   265  			val, err := f.Eval(ctx, tt.row)
   266  			if tt.err {
   267  				require.Error(err)
   268  			} else {
   269  				require.NoError(err)
   270  				require.Equal(tt.expected, val)
   271  			}
   272  		})
   273  	}
   274  }
   275  
   276  func TestTime_Hour(t *testing.T) {
   277  	ctx := sql.NewEmptyContext()
   278  	f := NewHour(expression.NewGetField(0, types.LongText, "foo", false))
   279  
   280  	testCases := []struct {
   281  		name     string
   282  		row      sql.Row
   283  		expected interface{}
   284  		err      bool
   285  	}{
   286  		{"null date", sql.NewRow(nil), nil, false},
   287  		{"invalid type", sql.NewRow([]byte{0, 1, 2}), nil, false},
   288  		{"date as string", sql.NewRow(stringDate), int32(14), false},
   289  		{"date as time", sql.NewRow(time.Now()), int32(time.Now().UTC().Hour()), false},
   290  	}
   291  
   292  	for _, tt := range testCases {
   293  		t.Run(tt.name, func(t *testing.T) {
   294  			require := require.New(t)
   295  			val, err := f.Eval(ctx, tt.row)
   296  			if tt.err {
   297  				require.Error(err)
   298  			} else {
   299  				require.NoError(err)
   300  				require.Equal(tt.expected, val)
   301  			}
   302  		})
   303  	}
   304  }
   305  
   306  func TestTime_Minute(t *testing.T) {
   307  	ctx := sql.NewEmptyContext()
   308  	f := NewMinute(expression.NewGetField(0, types.LongText, "foo", false))
   309  
   310  	testCases := []struct {
   311  		name     string
   312  		row      sql.Row
   313  		expected interface{}
   314  		err      bool
   315  	}{
   316  		{"null date", sql.NewRow(nil), nil, false},
   317  		{"invalid type", sql.NewRow([]byte{0, 1, 2}), nil, false},
   318  		{"date as string", sql.NewRow(stringDate), int32(15), false},
   319  		{"date as time", sql.NewRow(time.Now()), int32(time.Now().UTC().Minute()), false},
   320  	}
   321  
   322  	for _, tt := range testCases {
   323  		t.Run(tt.name, func(t *testing.T) {
   324  			require := require.New(t)
   325  			val, err := f.Eval(ctx, tt.row)
   326  			if tt.err {
   327  				require.Error(err)
   328  			} else {
   329  				require.NoError(err)
   330  				require.Equal(tt.expected, val)
   331  			}
   332  		})
   333  	}
   334  }
   335  
   336  func TestTime_Second(t *testing.T) {
   337  	ctx := sql.NewEmptyContext()
   338  	f := NewSecond(expression.NewGetField(0, types.LongText, "foo", false))
   339  
   340  	testCases := []struct {
   341  		name     string
   342  		row      sql.Row
   343  		expected interface{}
   344  		err      bool
   345  	}{
   346  		{"null date", sql.NewRow(nil), nil, false},
   347  		{"invalid type", sql.NewRow([]byte{0, 1, 2}), nil, false},
   348  		{"date as string", sql.NewRow(stringDate), int32(16), false},
   349  		{"date as time", sql.NewRow(time.Now()), int32(time.Now().UTC().Second()), false},
   350  	}
   351  
   352  	for _, tt := range testCases {
   353  		t.Run(tt.name, func(t *testing.T) {
   354  			require := require.New(t)
   355  			val, err := f.Eval(ctx, tt.row)
   356  			if tt.err {
   357  				require.Error(err)
   358  			} else {
   359  				require.NoError(err)
   360  				require.Equal(tt.expected, val)
   361  			}
   362  		})
   363  	}
   364  }
   365  
   366  func TestTime_Microsecond(t *testing.T) {
   367  	ctx := sql.NewEmptyContext()
   368  	f := NewMicrosecond(expression.NewGetField(0, types.LongText, "foo", false))
   369  	currTime := time.Now()
   370  
   371  	testCases := []struct {
   372  		name     string
   373  		row      sql.Row
   374  		expected interface{}
   375  		err      bool
   376  	}{
   377  		{"null date", sql.NewRow(nil), nil, false},
   378  		{"invalid type", sql.NewRow([]byte{0, 1, 2}), nil, true},
   379  		{"date as string", sql.NewRow(stringDate), uint64(0), false},
   380  		{"date as time", sql.NewRow(currTime), uint64(currTime.Nanosecond()) / uint64(time.Microsecond), false},
   381  	}
   382  
   383  	for _, tt := range testCases {
   384  		t.Run(tt.name, func(t *testing.T) {
   385  			require := require.New(t)
   386  			val, err := f.Eval(ctx, tt.row)
   387  			if tt.err {
   388  				require.Error(err)
   389  			} else {
   390  				require.NoError(err)
   391  				require.Equal(tt.expected, val)
   392  			}
   393  		})
   394  	}
   395  }
   396  
   397  func TestTime_DayOfWeek(t *testing.T) {
   398  	ctx := sql.NewEmptyContext()
   399  	f := NewDayOfWeek(expression.NewGetField(0, types.LongText, "foo", false))
   400  
   401  	testCases := []struct {
   402  		name     string
   403  		row      sql.Row
   404  		expected interface{}
   405  		err      bool
   406  	}{
   407  		{"null date", sql.NewRow(nil), nil, false},
   408  		{"invalid type", sql.NewRow([]byte{0, 1, 2}), nil, false},
   409  		{"date as string", sql.NewRow(stringDate), int32(3), false},
   410  		{"date as time", sql.NewRow(time.Now()), int32(time.Now().UTC().Weekday() + 1), false},
   411  	}
   412  
   413  	for _, tt := range testCases {
   414  		t.Run(tt.name, func(t *testing.T) {
   415  			require := require.New(t)
   416  			val, err := f.Eval(ctx, tt.row)
   417  			if tt.err {
   418  				require.Error(err)
   419  			} else {
   420  				require.NoError(err)
   421  				require.Equal(tt.expected, val)
   422  			}
   423  		})
   424  	}
   425  }
   426  
   427  func TestTime_DayOfYear(t *testing.T) {
   428  	ctx := sql.NewEmptyContext()
   429  	f := NewDayOfYear(expression.NewGetField(0, types.LongText, "foo", false))
   430  
   431  	testCases := []struct {
   432  		name     string
   433  		row      sql.Row
   434  		expected interface{}
   435  		err      bool
   436  	}{
   437  		{"null date", sql.NewRow(nil), nil, false},
   438  		{"invalid type", sql.NewRow([]byte{0, 1, 2}), nil, false},
   439  		{"date as string", sql.NewRow(stringDate), int32(2), false},
   440  		{"date as time", sql.NewRow(time.Now()), int32(time.Now().UTC().YearDay()), false},
   441  	}
   442  
   443  	for _, tt := range testCases {
   444  		t.Run(tt.name, func(t *testing.T) {
   445  			require := require.New(t)
   446  			val, err := f.Eval(ctx, tt.row)
   447  			if tt.err {
   448  				require.Error(err)
   449  			} else {
   450  				require.NoError(err)
   451  				require.Equal(tt.expected, val)
   452  			}
   453  		})
   454  	}
   455  }
   456  
   457  func TestTime_WeekOfYear(t *testing.T) {
   458  	ctx := sql.NewEmptyContext()
   459  	f := NewWeekOfYear(expression.NewGetField(0, types.LongText, "foo", false))
   460  	currTime := time.Now()
   461  	_, week := currTime.ISOWeek()
   462  
   463  	testCases := []struct {
   464  		name     string
   465  		row      sql.Row
   466  		expected interface{}
   467  		err      bool
   468  	}{
   469  		{"null date", sql.NewRow(nil), nil, false},
   470  		{"invalid type", sql.NewRow([]byte{0, 1, 2}), int32(1), true},
   471  		{"date as string", sql.NewRow(stringDate), 1, false},
   472  		{"date as time", sql.NewRow(currTime), week, false},
   473  	}
   474  
   475  	for _, tt := range testCases {
   476  		t.Run(tt.name, func(t *testing.T) {
   477  			require := require.New(t)
   478  			val, err := f.Eval(ctx, tt.row)
   479  			if tt.err {
   480  				require.Error(err)
   481  			} else {
   482  				require.NoError(err)
   483  				require.Equal(tt.expected, val)
   484  			}
   485  		})
   486  	}
   487  }
   488  
   489  func TestYearWeek(t *testing.T) {
   490  	ctx := sql.NewEmptyContext()
   491  	f, err := NewYearWeek(expression.NewGetField(0, types.LongText, "foo", false))
   492  	require.NoError(t, err)
   493  
   494  	testCases := []struct {
   495  		name     string
   496  		row      sql.Row
   497  		expected interface{}
   498  		err      bool
   499  	}{
   500  		{"null date", sql.NewRow(nil), nil, false},
   501  		{"invalid type", sql.NewRow([]byte{0, 1, 2}), nil, false},
   502  		{"date as string", sql.NewRow(stringDate), int32(200653), false},
   503  	}
   504  
   505  	for _, tt := range testCases {
   506  		t.Run(tt.name, func(t *testing.T) {
   507  			require := require.New(t)
   508  			val, err := f.Eval(ctx, tt.row)
   509  			if tt.err {
   510  				require.Error(err)
   511  			} else {
   512  				require.NoError(err)
   513  				require.Equal(tt.expected, val)
   514  			}
   515  		})
   516  	}
   517  }
   518  
   519  func TestCalcDaynr(t *testing.T) {
   520  	require.EqualValues(t, calcDaynr(0, 0, 0), 0)
   521  	require.EqualValues(t, calcDaynr(9999, 12, 31), 3652424)
   522  	require.EqualValues(t, calcDaynr(1970, 1, 1), 719528)
   523  	require.EqualValues(t, calcDaynr(2006, 12, 16), 733026)
   524  	require.EqualValues(t, calcDaynr(10, 1, 2), 3654)
   525  	require.EqualValues(t, calcDaynr(2008, 2, 20), 733457)
   526  }
   527  
   528  func TestCalcWeek(t *testing.T) {
   529  	_, w := calcWeek(2008, 2, 20, weekMode(0))
   530  
   531  	_, w = calcWeek(2008, 2, 20, weekMode(1))
   532  	require.EqualValues(t, w, 8)
   533  
   534  	_, w = calcWeek(2008, 12, 31, weekMode(1))
   535  	require.EqualValues(t, w, 53)
   536  }
   537  
   538  func TestUTCTimestamp(t *testing.T) {
   539  	date := time.Date(2018, time.December, 2, 16, 25, 0, 0, time.Local)
   540  	testNowFunc := func() time.Time {
   541  		return date
   542  	}
   543  
   544  	var ctx *sql.Context
   545  	err := sql.RunWithNowFunc(testNowFunc, func() error {
   546  		ctx = sql.NewEmptyContext()
   547  		return nil
   548  	})
   549  	require.NoError(t, err)
   550  
   551  	tests := []struct {
   552  		args      []sql.Expression
   553  		result    time.Time
   554  		expectErr bool
   555  	}{
   556  		{
   557  			args:      nil,
   558  			result:    date,
   559  			expectErr: false,
   560  		},
   561  		{
   562  			args:      []sql.Expression{expression.NewLiteral(0, types.Int8)},
   563  			result:    date,
   564  			expectErr: false,
   565  		},
   566  		{
   567  			args:      []sql.Expression{expression.NewLiteral(0, types.Int64)},
   568  			result:    date,
   569  			expectErr: false,
   570  		},
   571  		{
   572  			args:      []sql.Expression{expression.NewLiteral(6, types.Uint8)},
   573  			result:    date,
   574  			expectErr: false,
   575  		},
   576  		{
   577  			args:      []sql.Expression{expression.NewLiteral(7, types.Int8)},
   578  			result:    time.Time{},
   579  			expectErr: true,
   580  		},
   581  		{
   582  			args:      []sql.Expression{expression.NewLiteral(-1, types.Int8)},
   583  			result:    time.Time{},
   584  			expectErr: true,
   585  		},
   586  		{
   587  			args:      []sql.Expression{expression.NewConvert(expression.NewLiteral("2020-10-10 01:02:03", types.Text), expression.ConvertToDatetime)},
   588  			result:    time.Time{},
   589  			expectErr: true,
   590  		},
   591  	}
   592  
   593  	for _, test := range tests {
   594  		t.Run(fmt.Sprint(test.args), func(t *testing.T) {
   595  			ut, err := NewUTCTimestamp(test.args...)
   596  			if !test.expectErr {
   597  				require.NoError(t, err)
   598  				val, err := ut.Eval(ctx, nil)
   599  				require.NoError(t, err)
   600  				assert.Equal(t, test.result.UTC(), val)
   601  			} else {
   602  				assert.Error(t, err)
   603  			}
   604  		})
   605  	}
   606  }
   607  
   608  func TestDate(t *testing.T) {
   609  	ctx := sql.NewEmptyContext()
   610  	f := NewDate(expression.NewGetField(0, types.LongText, "foo", false))
   611  
   612  	testCases := []struct {
   613  		name     string
   614  		row      sql.Row
   615  		expected interface{}
   616  		err      bool
   617  	}{
   618  		{"null date", sql.NewRow(nil), nil, false},
   619  		{"invalid type", sql.NewRow([]byte{0, 1, 2}), nil, false},
   620  		{"date as string", sql.NewRow(stringDate), "2007-01-02", false},
   621  		{"date as time", sql.NewRow(time.Now().UTC()), time.Now().UTC().Format("2006-01-02"), false},
   622  	}
   623  
   624  	for _, tt := range testCases {
   625  		t.Run(tt.name, func(t *testing.T) {
   626  			require := require.New(t)
   627  			val, err := f.Eval(ctx, tt.row)
   628  			if tt.err {
   629  				require.Error(err)
   630  			} else {
   631  				require.NoError(err)
   632  				require.Equal(tt.expected, val)
   633  			}
   634  		})
   635  	}
   636  }
   637  
   638  func TestNow(t *testing.T) {
   639  	f, _ := NewNow(expression.NewGetField(0, types.LongText, "foo", false))
   640  	date := time.Date(
   641  		2021,      // year
   642  		1,         // month
   643  		1,         // day
   644  		8,         // hour
   645  		30,        // min
   646  		15,        // sec
   647  		123456789, // nsec
   648  		time.UTC,  // location (UTC)
   649  	)
   650  
   651  	testCases := []struct {
   652  		name     string
   653  		row      sql.Row
   654  		expected interface{}
   655  		err      bool
   656  	}{
   657  		{"null date", sql.NewRow(nil), nil, true},
   658  		{"different int type", sql.NewRow(int8(0)), time.Date(date.Year(), date.Month(), date.Day(), date.Hour(), date.Minute(), date.Second(), 0, time.UTC), false},
   659  		{"precision of -1", sql.NewRow(-1), nil, true},
   660  		{"precision of 0", sql.NewRow(0), time.Date(date.Year(), date.Month(), date.Day(), date.Hour(), date.Minute(), date.Second(), 0, time.UTC), false},
   661  		{"precision of 1", sql.NewRow(1), time.Date(date.Year(), date.Month(), date.Day(), date.Hour(), date.Minute(), date.Second(), 100000000, time.UTC), false},
   662  		{"precision of 2", sql.NewRow(2), time.Date(date.Year(), date.Month(), date.Day(), date.Hour(), date.Minute(), date.Second(), 120000000, time.UTC), false},
   663  		{"precision of 3", sql.NewRow(3), time.Date(date.Year(), date.Month(), date.Day(), date.Hour(), date.Minute(), date.Second(), 123000000, time.UTC), false},
   664  		{"precision of 4", sql.NewRow(4), time.Date(date.Year(), date.Month(), date.Day(), date.Hour(), date.Minute(), date.Second(), 123400000, time.UTC), false},
   665  		{"precision of 5", sql.NewRow(5), time.Date(date.Year(), date.Month(), date.Day(), date.Hour(), date.Minute(), date.Second(), 123450000, time.UTC), false},
   666  		{"precision of 6", sql.NewRow(6), time.Date(date.Year(), date.Month(), date.Day(), date.Hour(), date.Minute(), date.Second(), 123456000, time.UTC), false},
   667  		{"precision of 7 which is too high", sql.NewRow(7), nil, true},
   668  		{"incorrect type", sql.NewRow("notanint"), nil, true},
   669  	}
   670  
   671  	for _, tt := range testCases {
   672  		t.Run(tt.name, func(t *testing.T) {
   673  			sql.RunWithNowFunc(func() time.Time {
   674  				return date
   675  			}, func() error {
   676  				ctx := sql.NewEmptyContext()
   677  				require := require.New(t)
   678  				val, err := f.Eval(ctx, tt.row)
   679  				if tt.err {
   680  					require.Error(err)
   681  				} else {
   682  					require.NoError(err)
   683  					require.Equal(tt.expected, val)
   684  				}
   685  				return nil
   686  			})
   687  		})
   688  	}
   689  }
   690  
   691  // TestSysdate tests the SYSDATE() function, which should generally behave identically to NOW(), but unlike NOW(),
   692  // SYSDATE() should always return the exact current time, and not the cached query start time. That behavior is
   693  // tested in the enginetests, instead of these unit tests.
   694  func TestSysdate(t *testing.T) {
   695  	f, _ := NewSysdate(expression.NewGetField(0, types.LongText, "foo", false))
   696  	date := time.Date(
   697  		2021,      // year
   698  		1,         // month
   699  		1,         // day
   700  		8,         // hour
   701  		30,        // min
   702  		15,        // sec
   703  		123456789, // nsec
   704  		time.UTC,  // location (UTC)
   705  	)
   706  
   707  	testCases := []struct {
   708  		name     string
   709  		row      sql.Row
   710  		expected interface{}
   711  		err      bool
   712  	}{
   713  		{"null date", sql.NewRow(nil), nil, true},
   714  		{"different int type", sql.NewRow(int8(0)), time.Date(date.Year(), date.Month(), date.Day(), date.Hour(), date.Minute(), date.Second(), 0, time.UTC), false},
   715  		{"precision of -1", sql.NewRow(-1), nil, true},
   716  		{"precision of 0", sql.NewRow(0), time.Date(date.Year(), date.Month(), date.Day(), date.Hour(), date.Minute(), date.Second(), 0, time.UTC), false},
   717  		{"precision of 1", sql.NewRow(1), time.Date(date.Year(), date.Month(), date.Day(), date.Hour(), date.Minute(), date.Second(), 100000000, time.UTC), false},
   718  		{"precision of 2", sql.NewRow(2), time.Date(date.Year(), date.Month(), date.Day(), date.Hour(), date.Minute(), date.Second(), 120000000, time.UTC), false},
   719  		{"precision of 3", sql.NewRow(3), time.Date(date.Year(), date.Month(), date.Day(), date.Hour(), date.Minute(), date.Second(), 123000000, time.UTC), false},
   720  		{"precision of 4", sql.NewRow(4), time.Date(date.Year(), date.Month(), date.Day(), date.Hour(), date.Minute(), date.Second(), 123400000, time.UTC), false},
   721  		{"precision of 5", sql.NewRow(5), time.Date(date.Year(), date.Month(), date.Day(), date.Hour(), date.Minute(), date.Second(), 123450000, time.UTC), false},
   722  		{"precision of 6", sql.NewRow(6), time.Date(date.Year(), date.Month(), date.Day(), date.Hour(), date.Minute(), date.Second(), 123456000, time.UTC), false},
   723  		{"precision of 7 which is too high", sql.NewRow(7), nil, true},
   724  		{"incorrect type", sql.NewRow("notanint"), nil, true},
   725  	}
   726  
   727  	for _, tt := range testCases {
   728  		t.Run(tt.name, func(t *testing.T) {
   729  			sql.RunWithNowFunc(func() time.Time {
   730  				return date
   731  			}, func() error {
   732  				ctx := sql.NewEmptyContext()
   733  				require := require.New(t)
   734  				val, err := f.Eval(ctx, tt.row)
   735  				if tt.err {
   736  					require.Error(err)
   737  				} else {
   738  					require.NoError(err)
   739  					require.Equal(tt.expected, val)
   740  				}
   741  				return nil
   742  			})
   743  		})
   744  	}
   745  }
   746  
   747  func TestTime(t *testing.T) {
   748  	ctx := sql.NewEmptyContext()
   749  	f := NewTime(expression.NewGetField(0, types.LongText, "foo", false))
   750  
   751  	testCases := []struct {
   752  		name     string
   753  		row      sql.Row
   754  		expected interface{}
   755  		err      bool
   756  	}{
   757  		{"null date", sql.NewRow(nil), nil, false},
   758  		{"invalid type", sql.NewRow([]byte{0, 1, 2}), nil, false},
   759  		{"time as string", sql.NewRow(stringDate), "14:15:16", false},
   760  	}
   761  
   762  	for _, tt := range testCases {
   763  		t.Run(tt.name, func(t *testing.T) {
   764  			require := require.New(t)
   765  			val, err := f.Eval(ctx, tt.row)
   766  			if tt.err {
   767  				require.Error(err)
   768  			} else {
   769  				require.NoError(err)
   770  				if v, ok := val.(types.Timespan); ok {
   771  					require.Equal(tt.expected, v.String())
   772  				} else {
   773  					require.Equal(tt.expected, val)
   774  				}
   775  			}
   776  		})
   777  	}
   778  }
   779  
   780  func TestTime_DayName(t *testing.T) {
   781  	ctx := sql.NewEmptyContext()
   782  	f := NewDayName(expression.NewGetField(0, types.LongText, "foo", false))
   783  
   784  	testCases := []struct {
   785  		name     string
   786  		row      sql.Row
   787  		expected interface{}
   788  		err      bool
   789  	}{
   790  		{"null date", sql.NewRow(nil), nil, false},
   791  		{"invalid type", sql.NewRow([]byte{0, 1, 2}), nil, false},
   792  		{"time as string", sql.NewRow(stringDate), "Tuesday", false},
   793  	}
   794  
   795  	for _, tt := range testCases {
   796  		t.Run(tt.name, func(t *testing.T) {
   797  			require := require.New(t)
   798  			val, err := f.Eval(ctx, tt.row)
   799  			if tt.err {
   800  				require.Error(err)
   801  			} else {
   802  				require.NoError(err)
   803  				if v, ok := val.(types.Timespan); ok {
   804  					require.Equal(tt.expected, v.String())
   805  				} else {
   806  					require.Equal(tt.expected, val)
   807  				}
   808  			}
   809  		})
   810  	}
   811  }
   812  
   813  func TestTime_MonthName(t *testing.T) {
   814  	ctx := sql.NewEmptyContext()
   815  	f := NewMonthName(expression.NewGetField(0, types.LongText, "foo", false))
   816  
   817  	testCases := []struct {
   818  		name     string
   819  		row      sql.Row
   820  		expected interface{}
   821  		err      bool
   822  	}{
   823  		{"null date", sql.NewRow(nil), nil, false},
   824  		{"invalid type", sql.NewRow([]byte{0, 1, 2}), nil, true},
   825  		{"time as string", sql.NewRow(stringDate), "January", false},
   826  	}
   827  
   828  	for _, tt := range testCases {
   829  		t.Run(tt.name, func(t *testing.T) {
   830  			require := require.New(t)
   831  			val, err := f.Eval(ctx, tt.row)
   832  			if tt.err {
   833  				require.Error(err)
   834  			} else {
   835  				require.NoError(err)
   836  				if v, ok := val.(types.Timespan); ok {
   837  					require.Equal(tt.expected, v.String())
   838  				} else {
   839  					require.Equal(tt.expected, val)
   840  				}
   841  			}
   842  		})
   843  	}
   844  }