Skip to content
This repository was archived by the owner on Jan 28, 2021. It is now read-only.

Varchar type #775

Merged
merged 2 commits into from
Jul 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 7 additions & 0 deletions sql/expression/function/nullif_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ func TestNullIf(t *testing.T) {
)
require.Equal(t, sql.Text, f.Type())

var3 := sql.VarChar(3)
f = NewNullIf(
expression.NewGetField(0, var3, "ex1", true),
expression.NewGetField(1, var3, "ex2", true),
)
require.Equal(t, var3, f.Type())

for _, tc := range testCases {
v, err := f.Eval(sql.NewEmptyContext(), sql.NewRow(tc.ex1, tc.ex2))
require.NoError(t, err)
Expand Down
2 changes: 2 additions & 0 deletions sql/expression/literal.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ type Literal struct {

// NewLiteral creates a new Literal expression.
func NewLiteral(value interface{}, fieldType sql.Type) *Literal {
// TODO(juanjux): we should probably check here if the type is sql.VarChar and the
// Capacity of the Type and the length of the value, but this can't return an error
return &Literal{
value: value,
fieldType: fieldType,
Expand Down
2 changes: 1 addition & 1 deletion sql/expression/tuple_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package expression
import (
"testing"

"github.com/stretchr/testify/require"
"github.com/src-d/go-mysql-server/sql"
"github.com/stretchr/testify/require"
)

func TestTuple(t *testing.T) {
Expand Down
72 changes: 68 additions & 4 deletions sql/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,13 @@ var (
// ErrConvertingToTime is thrown when a value cannot be converted to a Time
ErrConvertingToTime = errors.NewKind("value %q can't be converted to time.Time")

// ErrVarCharTruncation is thrown when a value is textually longer than the destination capacity
ErrVarCharTruncation = errors.NewKind("string value of %q is longer than destination capacity %d")

// ErrValueNotNil is thrown when a value that was expected to be nil, is not
ErrValueNotNil = errors.NewKind("value not nil: %#v")

// ErrNotTuple is retuned when the value is not a tuple.
// ErrNotTuple is returned when the value is not a tuple.
ErrNotTuple = errors.NewKind("value of type %T is not a tuple")

// ErrInvalidColumnNumber is returned when a tuple has an invalid number of
Expand Down Expand Up @@ -215,6 +218,11 @@ func Array(underlying Type) Type {
return arrayT{underlying}
}

// VarChar returns a new VarChar type of the given length.
func VarChar(length int) Type {
return varCharT{length: length}
}

// MysqlTypeToType gets the column type using the mysql type
func MysqlTypeToType(sql query.Type) (Type, error) {
switch sql {
Expand Down Expand Up @@ -244,7 +252,11 @@ func MysqlTypeToType(sql query.Type) (Type, error) {
return Timestamp, nil
case sqltypes.Date:
return Date, nil
case sqltypes.Text, sqltypes.VarChar:
case sqltypes.Text:
return Text, nil
case sqltypes.VarChar:
// Since we can't get the size of the sqltypes.VarChar to instantiate a
// specific VarChar(length) type we return a Text here
return Text, nil
case sqltypes.Bit:
return Boolean, nil
Expand Down Expand Up @@ -550,6 +562,51 @@ func (t dateT) Compare(a, b interface{}) (int, error) {
return 0, nil
}

type varCharT struct {
length int
}

func (t varCharT) Capacity() int { return t.length }

func (t varCharT) String() string { return fmt.Sprintf("VARCHAR(%d)", t.length) }

// Type implements Type interface
func (t varCharT) Type() query.Type {
return sqltypes.VarChar
}

// SQL implements Type interface
func (t varCharT) SQL(v interface{}) (sqltypes.Value, error) {
if v == nil {
return sqltypes.MakeTrusted(sqltypes.VarChar, nil), nil
}

v, err := t.Convert(v)
if err != nil {
return sqltypes.Value{}, err
}

return sqltypes.MakeTrusted(sqltypes.VarChar, []byte(v.(string))), nil
}

// Convert implements Type interface
func (t varCharT) Convert(v interface{}) (interface{}, error) {
val, err := cast.ToStringE(v)
if err != nil {
return nil, ErrConvertToSQL.New(t)
}

if len(val) > t.length {
return nil, ErrVarCharTruncation.New(val, t.length)
}
return val, nil
}

// Compare implements Type interface.
func (t varCharT) Compare(a interface{}, b interface{}) (int, error) {
return strings.Compare(a.(string), b.(string)), nil
}

type textT struct{}

func (t textT) String() string { return "TEXT" }
Expand Down Expand Up @@ -928,7 +985,12 @@ func IsDecimal(t Type) bool {

// IsText checks if t is a text type.
func IsText(t Type) bool {
return t == Text || t == Blob || t == JSON
return t == Text || t == Blob || t == JSON || IsVarChar(t)
}

func IsVarChar(t Type) bool {
_, ok := t.(varCharT)
return ok
}

// IsTuple checks if t is a tuple type.
Expand Down Expand Up @@ -982,7 +1044,9 @@ func MySQLTypeName(t Type) string {
return "DATETIME"
case sqltypes.Date:
return "DATE"
case sqltypes.Text, sqltypes.VarChar:
case sqltypes.VarChar:
return "VARCHAR"
case sqltypes.Text:
return "TEXT"
case sqltypes.Bit:
return "BIT"
Expand Down
36 changes: 36 additions & 0 deletions sql/type_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ func TestText(t *testing.T) {
lt(t, Text, "a", "b")
eq(t, Text, "a", "a")
gt(t, Text, "b", "a")

var3, err := VarChar(3).Convert("abc")
require.NoError(t, err)
convert(t, Text, var3, "abc")
}

func TestInt32(t *testing.T) {
Expand Down Expand Up @@ -237,6 +241,38 @@ func TestTuple(t *testing.T) {
gt(t, typ, []interface{}{1, 2, 4}, []interface{}{1, 2, 3})
}

func TestVarChar(t *testing.T) {
typ := VarChar(3)
require.True(t, IsVarChar(typ))
require.True(t, IsText(typ))
convert(t, typ, "foo", "foo")
fooByte := []byte{'f', 'o', 'o'}
convert(t, typ, fooByte, "foo")

typ = VarChar(1)
convertErr(t, typ, "foo")
convertErr(t, typ, fooByte)
convertErr(t, typ, 123)

typ = VarChar(10)
convert(t, typ, 123, "123")
convertErr(t, typ, 1234567890123)

convert(t, typ, "", "")
convert(t, typ, 1, "1")

lt(t, typ, "a", "b")
eq(t, typ, "a", "a")
gt(t, typ, "b", "a")

text, err := Text.Convert("abc")
require.NoError(t, err)

convert(t, typ, text, "abc")
typ1 := VarChar(1)
convertErr(t, typ1, text)
}

func TestArray(t *testing.T) {
require := require.New(t)

Expand Down
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy