github.com/dolthub/go-mysql-server@v0.18.0/sql/expression/function/greatest_least_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  	"testing"
    19  	"unsafe"
    20  
    21  	"github.com/stretchr/testify/require"
    22  
    23  	"github.com/dolthub/go-mysql-server/sql"
    24  	"github.com/dolthub/go-mysql-server/sql/expression"
    25  	"github.com/dolthub/go-mysql-server/sql/types"
    26  )
    27  
    28  func TestGreatest(t *testing.T) {
    29  	testCases := []struct {
    30  		name     string
    31  		args     []sql.Expression
    32  		expected interface{}
    33  	}{
    34  		{
    35  			"null",
    36  			[]sql.Expression{
    37  				expression.NewLiteral(nil, types.Null),
    38  				expression.NewLiteral(5, types.Int64),
    39  				expression.NewLiteral(1, types.Int64),
    40  			},
    41  			nil,
    42  		},
    43  		{
    44  			"negative and all ints",
    45  			[]sql.Expression{
    46  				expression.NewLiteral(int64(-1), types.Int64),
    47  				expression.NewLiteral(int64(5), types.Int64),
    48  				expression.NewLiteral(int64(1), types.Int64),
    49  			},
    50  			int64(5),
    51  		},
    52  		{
    53  			"string mixed",
    54  			[]sql.Expression{
    55  				expression.NewLiteral(string("9"), types.LongText),
    56  				expression.NewLiteral(int64(5), types.Int64),
    57  				expression.NewLiteral(int64(1), types.Int64),
    58  			},
    59  			float64(9),
    60  		},
    61  		{
    62  			"unconvertible string mixed ignored",
    63  			[]sql.Expression{
    64  				expression.NewLiteral(string("10.5"), types.LongText),
    65  				expression.NewLiteral(string("foobar"), types.Int64),
    66  				expression.NewLiteral(int64(5), types.Int64),
    67  				expression.NewLiteral(int64(1), types.Int64),
    68  			},
    69  			float64(10.5),
    70  		},
    71  		{
    72  			"float mixed",
    73  			[]sql.Expression{
    74  				expression.NewLiteral(float64(10.0), types.Float64),
    75  				expression.NewLiteral(int(5), types.Int64),
    76  				expression.NewLiteral(int(1), types.Int64),
    77  			},
    78  			float64(10.0),
    79  		},
    80  		{
    81  			"all strings",
    82  			[]sql.Expression{
    83  				expression.NewLiteral("aaa", types.LongText),
    84  				expression.NewLiteral("bbb", types.LongText),
    85  				expression.NewLiteral("9999", types.LongText),
    86  				expression.NewLiteral("", types.LongText),
    87  			},
    88  			"bbb",
    89  		},
    90  		{
    91  			"all strings and empty",
    92  			[]sql.Expression{
    93  				expression.NewLiteral("aaa", types.LongText),
    94  				expression.NewLiteral("bbb", types.LongText),
    95  				expression.NewLiteral("9999", types.LongText),
    96  				expression.NewLiteral("", types.LongText),
    97  			},
    98  			"bbb",
    99  		},
   100  		{
   101  			"nulls of a non-null type, char",
   102  			[]sql.Expression{
   103  				expression.NewConvert(expression.NewLiteral("aaa", types.LongText), expression.ConvertToChar),
   104  				expression.NewConvert(expression.NewLiteral(nil, types.Null), expression.ConvertToChar),
   105  			},
   106  			nil,
   107  		},
   108  		{
   109  			"nulls of a non-null type, signed",
   110  			[]sql.Expression{
   111  				expression.NewConvert(expression.NewLiteral(3.14159265359, types.Float64), expression.ConvertToSigned),
   112  				expression.NewConvert(expression.NewLiteral(nil, types.Null), expression.ConvertToSigned),
   113  			},
   114  			nil,
   115  		},
   116  	}
   117  
   118  	for _, tt := range testCases {
   119  		t.Run(tt.name, func(t *testing.T) {
   120  			require := require.New(t)
   121  
   122  			ctx := sql.NewEmptyContext()
   123  			f, err := NewGreatest(tt.args...)
   124  			require.NoError(err)
   125  
   126  			output, err := f.Eval(ctx, nil)
   127  			require.NoError(err)
   128  			require.Equal(tt.expected, output)
   129  		})
   130  	}
   131  }
   132  
   133  func TestGreatestUnsignedOverflow(t *testing.T) {
   134  	require := require.New(t)
   135  	ctx := sql.NewEmptyContext()
   136  
   137  	var x int
   138  	var gr sql.Expression
   139  	var err error
   140  
   141  	switch unsafe.Sizeof(x) {
   142  	case 4:
   143  		gr, err = NewGreatest(expression.NewLiteral(int32(1), types.Int32),
   144  			expression.NewLiteral(uint32(4294967295), types.Uint32),
   145  		)
   146  		require.NoError(err)
   147  	case 8:
   148  		gr, err = NewGreatest(expression.NewLiteral(int64(1), types.Int64),
   149  			expression.NewLiteral(uint64(18446744073709551615), types.Uint64),
   150  		)
   151  		require.NoError(err)
   152  	default:
   153  		// non 32/64 bits??
   154  		return
   155  	}
   156  
   157  	_, err = gr.Eval(ctx, nil)
   158  	require.EqualError(err, "Unsigned integer too big to fit on signed integer")
   159  }
   160  
   161  func TestLeast(t *testing.T) {
   162  	testCases := []struct {
   163  		name     string
   164  		args     []sql.Expression
   165  		expected interface{}
   166  	}{
   167  		{
   168  			"null",
   169  			[]sql.Expression{
   170  				expression.NewLiteral(nil, types.Null),
   171  				expression.NewLiteral(5, types.Int64),
   172  				expression.NewLiteral(1, types.Int64),
   173  			},
   174  			nil,
   175  		},
   176  		{
   177  			"negative and all ints",
   178  			[]sql.Expression{
   179  				expression.NewLiteral(int64(-1), types.Int64),
   180  				expression.NewLiteral(int64(5), types.Int64),
   181  				expression.NewLiteral(int64(1), types.Int64),
   182  			},
   183  			int64(-1),
   184  		},
   185  		{
   186  			"string mixed",
   187  			[]sql.Expression{
   188  				expression.NewLiteral(string("10"), types.LongText),
   189  				expression.NewLiteral(int64(5), types.Int64),
   190  				expression.NewLiteral(int64(1), types.Int64),
   191  			},
   192  			float64(1),
   193  		},
   194  		{
   195  			"unconvertible string mixed ignored",
   196  			[]sql.Expression{
   197  				expression.NewLiteral(string("10.5"), types.LongText),
   198  				expression.NewLiteral(string("foobar"), types.Int64),
   199  				expression.NewLiteral(int64(5), types.Int64),
   200  				expression.NewLiteral(int64(1), types.Int64),
   201  			},
   202  			float64(1),
   203  		},
   204  		{
   205  			"float mixed",
   206  			[]sql.Expression{
   207  				expression.NewLiteral(float64(10.0), types.Float64),
   208  				expression.NewLiteral(int(5), types.Int64),
   209  				expression.NewLiteral(int(1), types.Int64),
   210  			},
   211  			float64(1.0),
   212  		},
   213  		{
   214  			"all strings",
   215  			[]sql.Expression{
   216  				expression.NewLiteral("aaa", types.LongText),
   217  				expression.NewLiteral("bbb", types.LongText),
   218  				expression.NewLiteral("9999", types.LongText),
   219  			},
   220  			"9999",
   221  		},
   222  		{
   223  			"all strings and empty",
   224  			[]sql.Expression{
   225  				expression.NewLiteral("aaa", types.LongText),
   226  				expression.NewLiteral("bbb", types.LongText),
   227  				expression.NewLiteral("9999", types.LongText),
   228  				expression.NewLiteral("", types.LongText),
   229  			},
   230  			"",
   231  		},
   232  	}
   233  
   234  	for _, tt := range testCases {
   235  		t.Run(tt.name, func(t *testing.T) {
   236  			ctx := sql.NewEmptyContext()
   237  			require := require.New(t)
   238  
   239  			f, err := NewLeast(tt.args...)
   240  			require.NoError(err)
   241  
   242  			output, err := f.Eval(ctx, nil)
   243  			require.NoError(err)
   244  			require.Equal(tt.expected, output)
   245  		})
   246  	}
   247  }