Skip to content

Commit 586248c

Browse files
elianddbclaude
andcommitted
Fix SET type casting to CHAR and BINARY
This commit fixes an issue where SET types were not properly converted to their string representation when casting to CHAR or BINARY types. The problem was that SET types use internal uint64 values to represent bit fields, but when casting to CHAR or BINARY, the string representation of the SET should be used instead. Changes: - Added special handling in convertValue() for SET types in both CHAR and BINARY conversion cases - Convert SET uint64 bit field to string representation before passing to LongText/LongBlob converters - Removed Skip flags from previously failing tests in script_queries.go - Updated test expectations to include all SET values (including "defg") Fixes dolthub/dolt#9511 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent ea7a469 commit 586248c

File tree

2 files changed

+82
-6
lines changed

2 files changed

+82
-6
lines changed

enginetest/queries/script_queries.go

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9491,6 +9491,38 @@ where
94919491
{"abc"},
94929492
},
94939493
},
9494+
{
9495+
Query: "select e, cast(e as unsigned) from t order by e;",
9496+
Expected: []sql.Row{
9497+
{"abc", uint64(1)},
9498+
{"defg", uint64(2)},
9499+
{"hijkl", uint64(3)},
9500+
},
9501+
},
9502+
{
9503+
Query: "select e, cast(e as decimal) from t order by e;",
9504+
Expected: []sql.Row{
9505+
{"abc", "1"},
9506+
{"defg", "2"},
9507+
{"hijkl", "3"},
9508+
},
9509+
},
9510+
{
9511+
Query: "select e, cast(e as float) from t order by e;",
9512+
Expected: []sql.Row{
9513+
{"abc", float32(1)},
9514+
{"defg", float32(2)},
9515+
{"hijkl", float32(3)},
9516+
},
9517+
},
9518+
{
9519+
Query: "select e, cast(e as double) from t order by e;",
9520+
Expected: []sql.Row{
9521+
{"abc", float64(1)},
9522+
{"defg", float64(2)},
9523+
{"hijkl", float64(3)},
9524+
},
9525+
},
94949526
},
94959527
},
94969528
{
@@ -10077,25 +10109,59 @@ where
1007710109
},
1007810110
},
1007910111
{
10080-
// https://github.com/dolthub/dolt/issues/9511
10081-
Skip: true,
1008210112
Query: "select s, cast(s as char) from t order by s;",
1008310113
Expected: []sql.Row{
1008410114
{"abc", "abc"},
10115+
{"defg", "defg"},
1008510116
{"abc,defg", "abc,defg"},
1008610117
{"abc,defg,hijkl", "abc,defg,hijkl"},
1008710118
},
1008810119
},
1008910120
{
10090-
// https://github.com/dolthub/dolt/issues/9511
10091-
Skip: true,
1009210121
Query: "select s, cast(s as binary) from t order by s;",
1009310122
Expected: []sql.Row{
1009410123
{"abc", []uint8("abc")},
10124+
{"defg", []uint8("defg")},
1009510125
{"abc,defg", []uint8("abc,defg")},
1009610126
{"abc,defg,hijkl", []uint8("abc,defg,hijkl")},
1009710127
},
1009810128
},
10129+
{
10130+
Query: "select s, cast(s as unsigned) from t order by s;",
10131+
Expected: []sql.Row{
10132+
{"abc", uint64(1)},
10133+
{"defg", uint64(2)},
10134+
{"abc,defg", uint64(3)},
10135+
{"abc,defg,hijkl", uint64(7)},
10136+
},
10137+
},
10138+
{
10139+
Query: "select s, cast(s as decimal) from t order by s;",
10140+
Expected: []sql.Row{
10141+
{"abc", "1"},
10142+
{"defg", "2"},
10143+
{"abc,defg", "3"},
10144+
{"abc,defg,hijkl", "7"},
10145+
},
10146+
},
10147+
{
10148+
Query: "select s, cast(s as float) from t order by s;",
10149+
Expected: []sql.Row{
10150+
{"abc", float32(1)},
10151+
{"defg", float32(2)},
10152+
{"abc,defg", float32(3)},
10153+
{"abc,defg,hijkl", float32(7)},
10154+
},
10155+
},
10156+
{
10157+
Query: "select s, cast(s as double) from t order by s;",
10158+
Expected: []sql.Row{
10159+
{"abc", float64(1)},
10160+
{"defg", float64(2)},
10161+
{"abc,defg", float64(3)},
10162+
{"abc,defg,hijkl", float64(7)},
10163+
},
10164+
},
1009910165
},
1010010166
},
1010110167
{

sql/expression/convert.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,17 +278,25 @@ func (c *Convert) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
278278
return casted, nil
279279
}
280280

281-
// convertValue only returns an error if converting to JSON, Date, and Datetime;
282-
// the zero value is returned for float types. Nil is returned in all other cases.
281+
// convertValue converts a value from its current type to the specified target type for CAST/CONVERT operations.
282+
// It handles type-specific conversion logic and applies length/scale constraints where applicable.
283+
// For SET/ENUM types converting to text types, uses TypeAwareConversion for proper string representation.
284+
// For SET/ENUM types converting to binary types, converts to string first before applying binary conversion.
283285
// If |typeLength| and |typeScale| are 0, they are ignored, otherwise they are used as constraints on the
284286
// converted type where applicable (e.g. Char conversion supports only |typeLength|, Decimal conversion supports
285287
// |typeLength| and |typeScale|).
288+
// Only returns an error if converting to JSON, Date, and Datetime; the zero value is returned for float types.
289+
// Nil is returned in all other cases.
286290
func convertValue(ctx *sql.Context, val interface{}, castTo string, originType sql.Type, typeLength, typeScale int) (interface{}, error) {
287291
if val == nil {
288292
return nil, nil
289293
}
290294
switch strings.ToLower(castTo) {
291295
case ConvertToBinary:
296+
// For SET/ENUM types, convert to string first since TypeAwareConversion only handles text types
297+
if types.IsSet(originType) || types.IsEnum(originType) {
298+
val, _, _ = types.ConvertToCollatedString(ctx, val, originType)
299+
}
292300
b, _, err := types.LongBlob.Convert(ctx, val)
293301
if err != nil {
294302
return nil, nil
@@ -307,6 +315,7 @@ func convertValue(ctx *sql.Context, val interface{}, castTo string, originType s
307315
}
308316
return truncateConvertedValue(b, typeLength)
309317
case ConvertToChar, ConvertToNChar:
318+
val, _ = types.TypeAwareConversion(ctx, val, originType, types.LongText)
310319
s, _, err := types.LongText.Convert(ctx, val)
311320
if err != nil {
312321
return nil, nil
@@ -468,6 +477,7 @@ func createConvertedDecimalType(length, scale int, logErrors bool) sql.DecimalTy
468477
return types.InternalDecimalType
469478
}
470479

480+
471481
// convertHexBlobToDecimalForNumericContext converts byte array value to unsigned int value if originType is BLOB type.
472482
// This function is called when convertTo type is number type only. The hex literal values are parsed into blobs as
473483
// binary string as default, but for numeric context, the value should be a number.

0 commit comments

Comments
 (0)