Skip to content

Commit 0429d89

Browse files
authored
Merge pull request #3095 from dolthub/angela/setconversion
Convert SetType to strings
2 parents 186222f + ec4cff6 commit 0429d89

File tree

4 files changed

+56
-26
lines changed

4 files changed

+56
-26
lines changed

enginetest/queries/script_queries.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9280,7 +9280,6 @@ where
92809280
},
92819281
{
92829282
// https://github.com/dolthub/dolt/issues/8598
9283-
Skip: true,
92849283
Query: "select (case e when 'abc' then e when 'defg' then e when 'hijkl' then 'something' end) as e from t order by e;",
92859284
Expected: []sql.Row{
92869285
{"abc"},
@@ -9290,12 +9289,11 @@ where
92909289
},
92919290
{
92929291
// https://github.com/dolthub/dolt/issues/8598
9293-
Skip: true,
92949292
Query: "select (case e when 'abc' then e when 'defg' then e when 'hijkl' then 123 end) as e from t order by e;",
92959293
Expected: []sql.Row{
92969294
{"123"},
92979295
{"abc"},
9298-
{"def"},
9296+
{"defg"},
92999297
},
93009298
},
93019299
{
@@ -9778,15 +9776,14 @@ where
97789776
Skip: true,
97799777
Query: "select i, s + 0, s from tt;",
97809778
Expected: []sql.Row{
9781-
{0, float64(0), "something,"},
9782-
{1, float64(1), "something,"},
9779+
{0, float64(3), "something,"},
9780+
{1, float64(3), "something,"},
97839781
{2, float64(2), ""},
97849782
},
97859783
},
97869784
},
97879785
},
97889786
{
9789-
Skip: true,
97909787
Name: "set conversion to strings",
97919788
Dialect: "mysql",
97929789
SetUpScript: []string{
@@ -9822,6 +9819,8 @@ where
98229819
},
98239820
},
98249821
{
9822+
// https://github.com/dolthub/dolt/issues/9510
9823+
Skip: true,
98259824
Query: "select s from t where s like 'a%' order by s;",
98269825
Expected: []sql.Row{
98279826
{"abc"},
@@ -9911,6 +9910,8 @@ where
99119910
},
99129911
},
99139912
{
9913+
// https://github.com/dolthub/dolt/issues/9511
9914+
Skip: true,
99149915
Query: "select s, cast(s as char) from t order by s;",
99159916
Expected: []sql.Row{
99169917
{"abc", "abc"},
@@ -9919,6 +9920,8 @@ where
99199920
},
99209921
},
99219922
{
9923+
// https://github.com/dolthub/dolt/issues/9511
9924+
Skip: true,
99229925
Query: "select s, cast(s as binary) from t order by s;",
99239926
Expected: []sql.Row{
99249927
{"abc", []uint8("abc")},

sql/expression/case.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ func (c *Case) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
136136
}
137137
// When unable to convert to the type of the case, return the original value
138138
// A common error here is "Out of bounds value for decimal type"
139-
if ret, _, err := t.Convert(ctx, bval); err == nil {
139+
if ret, err := types.TypeAwareConversion(ctx, bval, b.Value.Type(), t); err == nil {
140140
return ret, nil
141141
}
142142
return bval, nil
@@ -150,7 +150,7 @@ func (c *Case) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
150150
}
151151
// When unable to convert to the type of the case, return the original value
152152
// A common error here is "Out of bounds value for decimal type"
153-
if ret, _, err := t.Convert(ctx, val); err == nil {
153+
if ret, err := types.TypeAwareConversion(ctx, val, c.Else.Type(), t); err == nil {
154154
return ret, nil
155155
}
156156
return val, nil

sql/types/conversion.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,3 +734,23 @@ func GeneralizeTypes(a, b sql.Type) sql.Type {
734734
// TODO: decide if we want to make this VarChar to match MySQL, match VarChar length to max of two types
735735
return LongText
736736
}
737+
738+
// TypeAwareConversion converts a value to a specified type, with awareness of the value's original type. This is
739+
// necessary because some types, such as EnumType and SetType, are stored as ints and require information from the
740+
// original type to properly convert to strings.
741+
func TypeAwareConversion(ctx *sql.Context, val interface{}, originalType sql.Type, convertedType sql.Type) (interface{}, error) {
742+
if val == nil {
743+
return nil, nil
744+
}
745+
var converted interface{}
746+
var err error
747+
if IsTextOnly(convertedType) {
748+
converted, _, err = ConvertToCollatedString(ctx, val, originalType)
749+
} else {
750+
converted, _, err = convertedType.Convert(ctx, val)
751+
}
752+
if err != nil {
753+
return nil, err
754+
}
755+
return converted, nil
756+
}

sql/types/strings.go

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,7 @@ func convertToLongTextString(ctx context.Context, val interface{}) (string, erro
610610
}
611611

612612
// convertEnumToString converts an enum value to its string representation
613-
func convertEnumToString(ctx context.Context, val interface{}, enumType sql.EnumType) (string, error) {
613+
func convertEnumToString(ctx context.Context, val interface{}, enumType EnumType) (string, error) {
614614
if enumVal, ok := val.(uint16); ok {
615615
if enumStr, exists := enumType.At(int(enumVal)); exists {
616616
return enumStr, nil
@@ -620,6 +620,14 @@ func convertEnumToString(ctx context.Context, val interface{}, enumType sql.Enum
620620
return convertToLongTextString(ctx, val)
621621
}
622622

623+
// convertSetToString converts a set value to its string representation
624+
func convertSetToString(ctx context.Context, val interface{}, setType SetType) (string, error) {
625+
if setVal, ok := val.(uint64); ok {
626+
return setType.BitsToString(setVal)
627+
}
628+
return convertToLongTextString(ctx, val)
629+
}
630+
623631
// ConvertToCollatedString returns the given interface as a string, along with its collation. If the Type possess a
624632
// collation, then that collation is returned. If the Type does not possess a collation (such as an integer), then the
625633
// value is converted to a string and the default collation is used. If the value is already a string then no additional
@@ -640,28 +648,27 @@ func ConvertToCollatedString(ctx context.Context, val interface{}, typ sql.Type)
640648
content = strVal
641649
} else if byteVal, ok := val.([]byte); ok {
642650
content = encodings.BytesToString(byteVal)
643-
} else if enumType, ok := typ.(sql.EnumType); ok {
644-
// Handle enum types in string context - return the string value, not the index
645-
content, err = convertEnumToString(ctx, val, enumType)
646-
if err != nil {
647-
return "", sql.Collation_Unspecified, err
648-
}
649651
} else {
650-
content, err = convertToLongTextString(ctx, val)
651-
if err != nil {
652-
return "", sql.Collation_Unspecified, err
652+
switch typ := typ.(type) {
653+
case EnumType:
654+
content, err = convertEnumToString(ctx, val, typ)
655+
if err != nil {
656+
return "", sql.Collation_Unspecified, err
657+
}
658+
case SetType:
659+
content, err = convertSetToString(ctx, val, typ)
660+
if err != nil {
661+
return "", sql.Collation_Unspecified, err
662+
}
663+
default:
664+
content, err = convertToLongTextString(ctx, val)
665+
if err != nil {
666+
return "", sql.Collation_Unspecified, err
667+
}
653668
}
654669
}
655670
} else {
656671
collation = sql.Collation_Default
657-
// Handle enum types in string context even without collation
658-
if enumType, ok := typ.(sql.EnumType); ok {
659-
content, err = convertEnumToString(ctx, val, enumType)
660-
if err != nil {
661-
return "", sql.Collation_Unspecified, err
662-
}
663-
return content, collation, nil
664-
}
665672
content, err = convertToLongTextString(ctx, val)
666673
if err != nil {
667674
return "", sql.Collation_Unspecified, err

0 commit comments

Comments
 (0)