github.com/dolthub/go-mysql-server@v0.18.0/sql/types/strings_test.go (about)

     1  // Copyright 2022 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 types
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"reflect"
    21  	"strings"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/dolthub/vitess/go/sqltypes"
    26  	"github.com/dolthub/vitess/go/vt/proto/query"
    27  	"github.com/stretchr/testify/assert"
    28  	"github.com/stretchr/testify/require"
    29  
    30  	"github.com/dolthub/go-mysql-server/sql"
    31  )
    32  
    33  func TestStringCompare(t *testing.T) {
    34  	tests := []struct {
    35  		typ         sql.StringType
    36  		val1        interface{}
    37  		val2        interface{}
    38  		expectedCmp int
    39  	}{
    40  		{MustCreateBinary(sqltypes.Binary, 10), nil, 0, 1},
    41  		{MustCreateStringWithDefaults(sqltypes.Text, 10), 0, nil, -1},
    42  		{MustCreateStringWithDefaults(sqltypes.VarChar, 10), nil, nil, 0},
    43  
    44  		{MustCreateStringWithDefaults(sqltypes.VarChar, 10), 0, 1, -1},
    45  		{MustCreateStringWithDefaults(sqltypes.VarChar, 10), []byte{0}, true, -1},
    46  		{MustCreateStringWithDefaults(sqltypes.VarChar, 10), false, 1, -1},
    47  		{MustCreateStringWithDefaults(sqltypes.VarChar, 10), 1, 0, 1},
    48  		{MustCreateStringWithDefaults(sqltypes.VarChar, 10), true, "false", -1},
    49  		{MustCreateStringWithDefaults(sqltypes.VarChar, 10), 1, false, 1},
    50  		{MustCreateStringWithDefaults(sqltypes.VarChar, 10), 1, 1, 0},
    51  		{MustCreateStringWithDefaults(sqltypes.VarChar, 10), true, 1, 0},
    52  		{MustCreateStringWithDefaults(sqltypes.VarChar, 10), "True", true, 1},
    53  		{MustCreateStringWithDefaults(sqltypes.VarChar, 10), false, true, -1},
    54  		{MustCreateStringWithDefaults(sqltypes.VarChar, 10), "0x12345de", "0xed54321", -1},
    55  		{MustCreateStringWithDefaults(sqltypes.VarChar, 10), "0xed54321", "0x12345de", 1},
    56  		{MustCreateStringWithDefaults(sqltypes.VarChar, 10), []byte("254"), 254, 0},
    57  		{MustCreateStringWithDefaults(sqltypes.VarChar, 10), []byte("254"), 254.5, -1},
    58  
    59  		// Sanity checks that behavior is consistent
    60  		{MustCreateBinary(sqltypes.Binary, 10), 0, 1, -1},
    61  		{MustCreateBinary(sqltypes.Binary, 10), []byte{0}, true, -1},
    62  		{MustCreateBinary(sqltypes.Binary, 10), false, 1, -1},
    63  		{MustCreateBinary(sqltypes.Binary, 10), []byte("254"), 254, 0},
    64  		{MustCreateBinary(sqltypes.Blob, 10), 0, 1, -1},
    65  		{MustCreateBinary(sqltypes.Blob, 10), []byte{0}, true, -1},
    66  		{MustCreateBinary(sqltypes.Blob, 10), false, 1, -1},
    67  		{MustCreateBinary(sqltypes.Blob, 10), []byte("254"), 254, 0},
    68  		{MustCreateStringWithDefaults(sqltypes.Char, 10), 0, 1, -1},
    69  		{MustCreateStringWithDefaults(sqltypes.Char, 10), []byte{0}, true, -1},
    70  		{MustCreateStringWithDefaults(sqltypes.Char, 10), false, 1, -1},
    71  		{MustCreateStringWithDefaults(sqltypes.Char, 10), []byte("254"), 254, 0},
    72  		{MustCreateStringWithDefaults(sqltypes.Text, 10), 0, 1, -1},
    73  		{MustCreateStringWithDefaults(sqltypes.Text, 10), []byte{0}, true, -1},
    74  		{MustCreateStringWithDefaults(sqltypes.Text, 10), false, 1, -1},
    75  		{MustCreateStringWithDefaults(sqltypes.Text, 10), []byte("254"), 254, 0},
    76  		{MustCreateBinary(sqltypes.VarBinary, 10), []byte{0}, true, -1},
    77  		{MustCreateBinary(sqltypes.VarBinary, 10), false, 1, -1},
    78  		{MustCreateBinary(sqltypes.VarBinary, 10), 0, 1, -1},
    79  		{MustCreateBinary(sqltypes.VarBinary, 10), []byte("254"), 254, 0},
    80  	}
    81  
    82  	for _, test := range tests {
    83  		t.Run(fmt.Sprintf("%v %v", test.val1, test.val2), func(t *testing.T) {
    84  			cmp, err := test.typ.Compare(test.val1, test.val2)
    85  			require.NoError(t, err)
    86  			assert.Equal(t, test.expectedCmp, cmp)
    87  		})
    88  	}
    89  }
    90  
    91  func TestStringCreateBlob(t *testing.T) {
    92  	tests := []struct {
    93  		baseType     query.Type
    94  		length       int64
    95  		expectedType StringType
    96  		expectedErr  bool
    97  	}{
    98  		{sqltypes.Binary, 10,
    99  			StringType{sqltypes.Binary, 10, 10, sql.Collation_binary}, false},
   100  		{sqltypes.Blob, 10,
   101  			StringType{sqltypes.Blob, TinyTextBlobMax, TinyTextBlobMax, sql.Collation_binary}, false},
   102  		{sqltypes.Char, 10,
   103  			StringType{sqltypes.Binary, 10, 10, sql.Collation_binary}, false},
   104  		{sqltypes.Text, 10,
   105  			StringType{sqltypes.Blob, TinyTextBlobMax, TinyTextBlobMax, sql.Collation_binary}, false},
   106  		{sqltypes.VarBinary, 10,
   107  			StringType{sqltypes.VarBinary, 10, 10, sql.Collation_binary}, false},
   108  		{sqltypes.VarChar, 10,
   109  			StringType{sqltypes.VarBinary, 10, 10, sql.Collation_binary}, false},
   110  	}
   111  
   112  	for _, test := range tests {
   113  		t.Run(fmt.Sprintf("%v %v", test.baseType, test.length), func(t *testing.T) {
   114  			typ, err := CreateBinary(test.baseType, test.length)
   115  			if test.expectedErr {
   116  				assert.Error(t, err)
   117  			} else {
   118  				require.NoError(t, err)
   119  				assert.Equal(t, test.expectedType, typ)
   120  			}
   121  		})
   122  	}
   123  }
   124  
   125  func TestStringCreateBlobInvalidBaseTypes(t *testing.T) {
   126  	tests := []struct {
   127  		baseType     query.Type
   128  		length       int64
   129  		expectedType StringType
   130  		expectedErr  bool
   131  	}{
   132  		{sqltypes.Bit, 10, StringType{}, true},
   133  		{sqltypes.Date, 10, StringType{}, true},
   134  		{sqltypes.Datetime, 10, StringType{}, true},
   135  		{sqltypes.Decimal, 10, StringType{}, true},
   136  		{sqltypes.Enum, 10, StringType{}, true},
   137  		{sqltypes.Expression, 10, StringType{}, true},
   138  		{sqltypes.Float32, 10, StringType{}, true},
   139  		{sqltypes.Float64, 10, StringType{}, true},
   140  		{sqltypes.Geometry, 10, StringType{}, true},
   141  		{sqltypes.Int16, 10, StringType{}, true},
   142  		{sqltypes.Int24, 10, StringType{}, true},
   143  		{sqltypes.Int32, 10, StringType{}, true},
   144  		{sqltypes.Int64, 10, StringType{}, true},
   145  		{sqltypes.Int8, 10, StringType{}, true},
   146  		{sqltypes.Null, 10, StringType{}, true},
   147  		{sqltypes.Set, 10, StringType{}, true},
   148  		{sqltypes.Time, 10, StringType{}, true},
   149  		{sqltypes.Timestamp, 10, StringType{}, true},
   150  		{sqltypes.TypeJSON, 10, StringType{}, true},
   151  		{sqltypes.Uint16, 10, StringType{}, true},
   152  		{sqltypes.Uint24, 10, StringType{}, true},
   153  		{sqltypes.Uint32, 10, StringType{}, true},
   154  		{sqltypes.Uint64, 10, StringType{}, true},
   155  		{sqltypes.Uint8, 10, StringType{}, true},
   156  		{sqltypes.Year, 10, StringType{}, true},
   157  	}
   158  
   159  	for _, test := range tests {
   160  		t.Run(fmt.Sprintf("%v %v", test.baseType, test.length), func(t *testing.T) {
   161  			typ, err := CreateBinary(test.baseType, test.length)
   162  			if test.expectedErr {
   163  				assert.Error(t, err)
   164  			} else {
   165  				require.NoError(t, err)
   166  				assert.Equal(t, test.expectedType, typ)
   167  			}
   168  		})
   169  	}
   170  }
   171  
   172  func TestStringCreateString(t *testing.T) {
   173  	tests := []struct {
   174  		baseType             query.Type
   175  		length               int64
   176  		collation            sql.CollationID
   177  		expectedType         StringType
   178  		expectedMaxTextBytes uint32
   179  		expectedErr          bool
   180  	}{
   181  		{sqltypes.Binary, 10, sql.Collation_binary,
   182  			StringType{sqltypes.Binary, 10, 10, sql.Collation_binary},
   183  			10, false},
   184  		{sqltypes.Blob, 10, sql.Collation_binary,
   185  			StringType{sqltypes.Blob, TinyTextBlobMax, TinyTextBlobMax, sql.Collation_binary},
   186  			TinyTextBlobMax, false},
   187  		{sqltypes.Char, 10, sql.Collation_Default,
   188  			StringType{sqltypes.Char, 10, 40, sql.Collation_Default},
   189  			40, false},
   190  		{sqltypes.Text, 10, sql.Collation_Default,
   191  			StringType{sqltypes.Text, TinyTextBlobMax / sql.Collation_Default.CharacterSet().MaxLength(), TinyTextBlobMax, sql.Collation_Default},
   192  			uint32(TinyTextBlobMax * sql.Collation_Default.CharacterSet().MaxLength()), false},
   193  		{sqltypes.Text, 1000, sql.Collation_Default,
   194  			StringType{sqltypes.Text, TextBlobMax / sql.Collation_Default.CharacterSet().MaxLength(), TextBlobMax, sql.Collation_Default},
   195  			uint32(TextBlobMax * sql.Collation_Default.CharacterSet().MaxLength()), false},
   196  		{sqltypes.Text, 1000000, sql.Collation_Default,
   197  			StringType{sqltypes.Text, MediumTextBlobMax / sql.Collation_Default.CharacterSet().MaxLength(), MediumTextBlobMax, sql.Collation_Default},
   198  			uint32(MediumTextBlobMax * sql.Collation_Default.CharacterSet().MaxLength()), false},
   199  		{sqltypes.Text, LongTextBlobMax, sql.Collation_Default,
   200  			StringType{sqltypes.Text, LongTextBlobMax / sql.Collation_Default.CharacterSet().MaxLength(), LongTextBlobMax, sql.Collation_Default},
   201  			uint32(LongTextBlobMax), false},
   202  		{sqltypes.VarBinary, 10, sql.Collation_binary,
   203  			StringType{sqltypes.VarBinary, 10, 10, sql.Collation_binary},
   204  			10, false},
   205  		{sqltypes.VarChar, 10, sql.Collation_Default,
   206  			StringType{sqltypes.VarChar, 10, 40, sql.Collation_Default},
   207  			40, false},
   208  		{sqltypes.Char, 10, sql.Collation_binary,
   209  			StringType{sqltypes.Binary, 10, 10, sql.Collation_binary},
   210  			10, false},
   211  		{sqltypes.Text, 10, sql.Collation_binary,
   212  			StringType{sqltypes.Blob, TinyTextBlobMax, TinyTextBlobMax, sql.Collation_binary},
   213  			TinyTextBlobMax, false},
   214  		{sqltypes.VarChar, 10, sql.Collation_binary,
   215  			StringType{sqltypes.VarBinary, 10, 10, sql.Collation_binary},
   216  			10, false},
   217  
   218  		// Out of bounds error cases
   219  		{sqltypes.Binary, charBinaryMax + 1, sql.Collation_binary, StringType{}, 0, true},
   220  		{sqltypes.Blob, LongTextBlobMax + 1, sql.Collation_binary, StringType{}, 0, true},
   221  		{sqltypes.Char, charBinaryMax + 1, sql.Collation_Default, StringType{}, 0, true},
   222  		{sqltypes.Text, LongTextBlobMax + 1, sql.Collation_Default, StringType{}, 0, true},
   223  
   224  		// JSON strings can also come in over the wire as VARBINARY types, and JSON allows a much larger length limit (1GB).
   225  		{sqltypes.VarBinary, MaxJsonFieldByteLength + 1, sql.Collation_binary, StringType{}, 0, true},
   226  		{sqltypes.VarChar, varcharVarbinaryMax + 1, sql.Collation_Default, StringType{}, 0, true},
   227  
   228  		// Default collation is not valid for these types
   229  		{sqltypes.Binary, 10, sql.Collation_Default, StringType{}, 0, true},
   230  		{sqltypes.Blob, 10, sql.Collation_Default, StringType{}, 0, true},
   231  		{sqltypes.VarBinary, 10, sql.Collation_Default, StringType{}, 0, true},
   232  	}
   233  
   234  	ctx := sql.NewContext(
   235  		context.Background(),
   236  		sql.WithSession(sql.NewBaseSession()),
   237  	)
   238  
   239  	for _, test := range tests {
   240  		t.Run(fmt.Sprintf("%v %v %v", test.baseType, test.length, test.collation), func(t *testing.T) {
   241  			typ, err := CreateString(test.baseType, test.length, test.collation)
   242  			if test.expectedErr {
   243  				assert.Error(t, err)
   244  			} else {
   245  				require.NoError(t, err)
   246  				assert.Equal(t, test.expectedType, typ)
   247  				assert.Equal(t, test.expectedMaxTextBytes, typ.MaxTextResponseByteLength(ctx))
   248  			}
   249  		})
   250  	}
   251  }
   252  
   253  func TestStringCreateStringInvalidBaseTypes(t *testing.T) {
   254  	tests := []struct {
   255  		baseType     query.Type
   256  		length       int64
   257  		collation    sql.CollationID
   258  		expectedType StringType
   259  		expectedErr  bool
   260  	}{
   261  		{sqltypes.Bit, 10, sql.Collation_Default, StringType{}, true},
   262  		{sqltypes.Date, 10, sql.Collation_Default, StringType{}, true},
   263  		{sqltypes.Datetime, 10, sql.Collation_Default, StringType{}, true},
   264  		{sqltypes.Decimal, 10, sql.Collation_Default, StringType{}, true},
   265  		{sqltypes.Enum, 10, sql.Collation_Default, StringType{}, true},
   266  		{sqltypes.Expression, 10, sql.Collation_Default, StringType{}, true},
   267  		{sqltypes.Float32, 10, sql.Collation_Default, StringType{}, true},
   268  		{sqltypes.Float64, 10, sql.Collation_Default, StringType{}, true},
   269  		{sqltypes.Geometry, 10, sql.Collation_Default, StringType{}, true},
   270  		{sqltypes.Int16, 10, sql.Collation_Default, StringType{}, true},
   271  		{sqltypes.Int24, 10, sql.Collation_Default, StringType{}, true},
   272  		{sqltypes.Int32, 10, sql.Collation_Default, StringType{}, true},
   273  		{sqltypes.Int64, 10, sql.Collation_Default, StringType{}, true},
   274  		{sqltypes.Int8, 10, sql.Collation_Default, StringType{}, true},
   275  		{sqltypes.Null, 10, sql.Collation_Default, StringType{}, true},
   276  		{sqltypes.Set, 10, sql.Collation_Default, StringType{}, true},
   277  		{sqltypes.Time, 10, sql.Collation_Default, StringType{}, true},
   278  		{sqltypes.Timestamp, 10, sql.Collation_Default, StringType{}, true},
   279  		{sqltypes.TypeJSON, 10, sql.Collation_Default, StringType{}, true},
   280  		{sqltypes.Uint16, 10, sql.Collation_Default, StringType{}, true},
   281  		{sqltypes.Uint24, 10, sql.Collation_Default, StringType{}, true},
   282  		{sqltypes.Uint32, 10, sql.Collation_Default, StringType{}, true},
   283  		{sqltypes.Uint64, 10, sql.Collation_Default, StringType{}, true},
   284  		{sqltypes.Uint8, 10, sql.Collation_Default, StringType{}, true},
   285  		{sqltypes.Year, 10, sql.Collation_Default, StringType{}, true},
   286  	}
   287  
   288  	for _, test := range tests {
   289  		t.Run(fmt.Sprintf("%v %v %v", test.baseType, test.length, test.collation), func(t *testing.T) {
   290  			typ, err := CreateString(test.baseType, test.length, test.collation)
   291  			if test.expectedErr {
   292  				assert.Error(t, err)
   293  			} else {
   294  				require.NoError(t, err)
   295  				assert.Equal(t, test.expectedType, typ)
   296  			}
   297  		})
   298  	}
   299  }
   300  
   301  func TestStringConvert(t *testing.T) {
   302  	tests := []struct {
   303  		typ         sql.StringType
   304  		val         interface{}
   305  		expectedVal interface{}
   306  		expectedErr bool
   307  	}{
   308  		{MustCreateBinary(sqltypes.Binary, 3), nil, nil, false},
   309  		{MustCreateBinary(sqltypes.Blob, 3), nil, nil, false},
   310  		{MustCreateStringWithDefaults(sqltypes.Char, 7), nil, nil, false},
   311  		{MustCreateStringWithDefaults(sqltypes.Text, 7), nil, nil, false},
   312  		{MustCreateBinary(sqltypes.VarBinary, 3), nil, nil, false},
   313  		{MustCreateStringWithDefaults(sqltypes.VarChar, 7), nil, nil, false},
   314  
   315  		{MustCreateBinary(sqltypes.Binary, 4), []byte{'1'}, []byte{'1', 0, 0, 0}, false},
   316  		{MustCreateBinary(sqltypes.Blob, 4), []byte{'1'}, []byte{'1'}, false},
   317  		{MustCreateStringWithDefaults(sqltypes.Char, 7), "abcde", "abcde", false},
   318  		{MustCreateStringWithDefaults(sqltypes.Text, 7), "abcde", "abcde", false},
   319  		{MustCreateBinary(sqltypes.VarBinary, 7), "abcde", []byte("abcde"), false},
   320  		{MustCreateStringWithDefaults(sqltypes.VarChar, 7), "abcde", "abcde", false},
   321  
   322  		{MustCreateStringWithDefaults(sqltypes.Char, 4), int(1), "1", false},
   323  		{MustCreateStringWithDefaults(sqltypes.Text, 4), int8(2), "2", false},
   324  		{MustCreateStringWithDefaults(sqltypes.VarChar, 4), int16(3), "3", false},
   325  		{MustCreateStringWithDefaults(sqltypes.Char, 4), int32(4), "4", false},
   326  		{MustCreateStringWithDefaults(sqltypes.Text, 4), int64(5), "5", false},
   327  		{MustCreateStringWithDefaults(sqltypes.VarChar, 4), uint(10), "10", false},
   328  		{MustCreateStringWithDefaults(sqltypes.Char, 4), uint8(11), "11", false},
   329  		{MustCreateStringWithDefaults(sqltypes.Text, 4), uint16(12), "12", false},
   330  		{MustCreateStringWithDefaults(sqltypes.VarChar, 4), uint32(13), "13", false},
   331  		{MustCreateStringWithDefaults(sqltypes.Char, 4), uint64(14), "14", false},
   332  		{MustCreateStringWithDefaults(sqltypes.Text, 4), float32(9.875), "9.875", false},
   333  		{MustCreateStringWithDefaults(sqltypes.VarChar, 7), float64(11583.5), "11583.5", false},
   334  		{MustCreateStringWithDefaults(sqltypes.Char, 4), []byte("abcd"), "abcd", false},
   335  		{MustCreateStringWithDefaults(sqltypes.VarChar, 40), time.Date(2019, 12, 12, 12, 12, 12, 0, time.UTC), "2019-12-12 12:12:12", false},
   336  
   337  		{MustCreateBinary(sqltypes.Binary, 3), "abcd", nil, true},
   338  		{MustCreateBinary(sqltypes.Blob, 3), strings.Repeat("0", TinyTextBlobMax+1), nil, true},
   339  		{MustCreateStringWithDefaults(sqltypes.Char, 3), "abcd", nil, true},
   340  		{MustCreateStringWithDefaults(sqltypes.Text, 3),
   341  			strings.Repeat("𒁏", int(TinyTextBlobMax/sql.Collation_Default.CharacterSet().MaxLength())+1),
   342  			nil, true},
   343  		{MustCreateBinary(sqltypes.VarBinary, 3), []byte{01, 02, 03, 04}, nil, true},
   344  		{MustCreateStringWithDefaults(sqltypes.VarChar, 3), []byte("abcd"), nil, true},
   345  		{MustCreateStringWithDefaults(sqltypes.Char, 20), JSONDocument{Val: nil}, "null", false},
   346  	}
   347  
   348  	for _, test := range tests {
   349  		t.Run(fmt.Sprintf("%v %v %v", test.typ, test.val, test.expectedVal), func(t *testing.T) {
   350  			val, _, err := test.typ.Convert(test.val)
   351  			if test.expectedErr {
   352  				assert.Error(t, err)
   353  			} else {
   354  				require.NoError(t, err)
   355  				assert.Equal(t, test.expectedVal, val)
   356  				if val != nil {
   357  					assert.Equal(t, test.typ.ValueType(), reflect.TypeOf(val))
   358  				}
   359  			}
   360  		})
   361  	}
   362  }
   363  
   364  func TestStringString(t *testing.T) {
   365  	tests := []struct {
   366  		typ         sql.Type
   367  		expectedStr string
   368  	}{
   369  		{MustCreateBinary(sqltypes.Binary, 10), "binary(10)"},
   370  		{MustCreateBinary(sqltypes.Binary, charBinaryMax), fmt.Sprintf("binary(%v)", charBinaryMax)},
   371  		{MustCreateBinary(sqltypes.Blob, 0), "tinyblob"},
   372  		{MustCreateBinary(sqltypes.Blob, TinyTextBlobMax-1), "tinyblob"},
   373  		{MustCreateBinary(sqltypes.Blob, TinyTextBlobMax), "tinyblob"},
   374  		{MustCreateBinary(sqltypes.Blob, TinyTextBlobMax+1), "blob"},
   375  		{MustCreateBinary(sqltypes.Blob, TextBlobMax-1), "blob"},
   376  		{MustCreateBinary(sqltypes.Blob, TextBlobMax), "blob"},
   377  		{MustCreateBinary(sqltypes.Blob, TextBlobMax+1), "mediumblob"},
   378  		{MustCreateBinary(sqltypes.Blob, MediumTextBlobMax-1), "mediumblob"},
   379  		{MustCreateBinary(sqltypes.Blob, MediumTextBlobMax), "mediumblob"},
   380  		{MustCreateBinary(sqltypes.Blob, MediumTextBlobMax+1), "longblob"},
   381  		{MustCreateBinary(sqltypes.Blob, LongTextBlobMax), "longblob"},
   382  		{MustCreateString(sqltypes.Char, 10, sql.Collation_Default), "char(10)"},
   383  		{MustCreateString(sqltypes.Char, charBinaryMax, sql.Collation_Default), fmt.Sprintf("char(%v)", charBinaryMax)},
   384  		{MustCreateString(sqltypes.Text, 0, sql.Collation_Default), "tinytext"},
   385  		{MustCreateString(sqltypes.Text, TinyTextBlobMax, sql.Collation_Default), "tinytext"},
   386  		{MustCreateString(sqltypes.Text, TinyTextBlobMax+1, sql.Collation_Default), "text"},
   387  		{MustCreateString(sqltypes.Text, TextBlobMax, sql.Collation_Default), "text"},
   388  		{MustCreateString(sqltypes.Text, TextBlobMax+1, sql.Collation_Default), "mediumtext"},
   389  		{MustCreateString(sqltypes.Text, MediumTextBlobMax, sql.Collation_Default), "mediumtext"},
   390  		{MustCreateString(sqltypes.Text, MediumTextBlobMax+1, sql.Collation_Default), "longtext"},
   391  		{MustCreateString(sqltypes.Text, LongTextBlobMax-1, sql.Collation_Default), "longtext"},
   392  		{MustCreateString(sqltypes.Text, LongTextBlobMax, sql.Collation_Default), "longtext"},
   393  		{MustCreateBinary(sqltypes.VarBinary, 10), "varbinary(10)"},
   394  		{MustCreateBinary(sqltypes.VarBinary, varcharVarbinaryMax), fmt.Sprintf("varbinary(%v)", varcharVarbinaryMax)},
   395  		{MustCreateString(sqltypes.VarChar, 10, sql.Collation_Default), "varchar(10)"},
   396  		{MustCreateString(sqltypes.VarChar, varcharVarbinaryMax, sql.Collation_Default),
   397  			fmt.Sprintf("varchar(%v)", varcharVarbinaryMax)},
   398  		{MustCreateString(sqltypes.Char, 10, sql.Collation_Default.CharacterSet().BinaryCollation()),
   399  			fmt.Sprintf("char(10) COLLATE %v", sql.Collation_Default.CharacterSet().BinaryCollation())},
   400  		{MustCreateString(sqltypes.Char, 10, sql.Collation_utf16_general_ci), "char(10) CHARACTER SET utf16 COLLATE utf16_general_ci"},
   401  		{MustCreateString(sqltypes.Text, 10, sql.Collation_ascii_general_ci), "tinytext CHARACTER SET ascii COLLATE ascii_general_ci"},
   402  		{MustCreateString(sqltypes.VarChar, 10, sql.Collation_latin1_bin), "varchar(10) CHARACTER SET latin1 COLLATE latin1_bin"},
   403  	}
   404  
   405  	for _, test := range tests {
   406  		t.Run(fmt.Sprintf("%v %v", test.typ, test.expectedStr), func(t *testing.T) {
   407  			str := test.typ.String()
   408  			assert.Equal(t, test.expectedStr, str)
   409  		})
   410  	}
   411  }