Skip to content

Commit 752fbd3

Browse files
elianddbclaude
andcommitted
Fix SET and ENUM type casting to CHAR and BINARY
- Replace custom convertSetToStringForStringContext() with existing TypeAwareConversion() for CHAR conversions - Add explicit SET/ENUM handling for BINARY conversions using ConvertToCollatedString() - Remove custom helper function and use established conversion patterns - Add comprehensive casting tests for SET and ENUM types to all numeric types (unsigned, decimal, float, double) - Update function documentation to clarify SET/ENUM conversion behavior - Remove Skip flags from existing SET casting tests per issue requirements Fixes dolthub/dolt#9511 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 0204980 commit 752fbd3

File tree

2 files changed

+75
-16
lines changed

2 files changed

+75
-16
lines changed

enginetest/queries/script_queries.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9325,6 +9325,38 @@ where
93259325
{"abc"},
93269326
},
93279327
},
9328+
{
9329+
Query: "select e, cast(e as unsigned) from t order by e;",
9330+
Expected: []sql.Row{
9331+
{"abc", uint64(1)},
9332+
{"defg", uint64(2)},
9333+
{"hijkl", uint64(3)},
9334+
},
9335+
},
9336+
{
9337+
Query: "select e, cast(e as decimal) from t order by e;",
9338+
Expected: []sql.Row{
9339+
{"abc", "1"},
9340+
{"defg", "2"},
9341+
{"hijkl", "3"},
9342+
},
9343+
},
9344+
{
9345+
Query: "select e, cast(e as float) from t order by e;",
9346+
Expected: []sql.Row{
9347+
{"abc", float32(1)},
9348+
{"defg", float32(2)},
9349+
{"hijkl", float32(3)},
9350+
},
9351+
},
9352+
{
9353+
Query: "select e, cast(e as double) from t order by e;",
9354+
Expected: []sql.Row{
9355+
{"abc", float64(1)},
9356+
{"defg", float64(2)},
9357+
{"hijkl", float64(3)},
9358+
},
9359+
},
93289360
},
93299361
},
93309362
{
@@ -9928,6 +9960,42 @@ where
99289960
{"abc,defg,hijkl", []uint8("abc,defg,hijkl")},
99299961
},
99309962
},
9963+
{
9964+
Query: "select s, cast(s as unsigned) from t order by s;",
9965+
Expected: []sql.Row{
9966+
{"abc", uint64(1)},
9967+
{"defg", uint64(2)},
9968+
{"abc,defg", uint64(3)},
9969+
{"abc,defg,hijkl", uint64(7)},
9970+
},
9971+
},
9972+
{
9973+
Query: "select s, cast(s as decimal) from t order by s;",
9974+
Expected: []sql.Row{
9975+
{"abc", "1"},
9976+
{"defg", "2"},
9977+
{"abc,defg", "3"},
9978+
{"abc,defg,hijkl", "7"},
9979+
},
9980+
},
9981+
{
9982+
Query: "select s, cast(s as float) from t order by s;",
9983+
Expected: []sql.Row{
9984+
{"abc", float32(1)},
9985+
{"defg", float32(2)},
9986+
{"abc,defg", float32(3)},
9987+
{"abc,defg,hijkl", float32(7)},
9988+
},
9989+
},
9990+
{
9991+
Query: "select s, cast(s as double) from t order by s;",
9992+
Expected: []sql.Row{
9993+
{"abc", float64(1)},
9994+
{"defg", float64(2)},
9995+
{"abc,defg", float64(3)},
9996+
{"abc,defg,hijkl", float64(7)},
9997+
},
9998+
},
99319999
},
993210000
},
993310001
{

sql/expression/convert.go

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,8 @@ func (c *Convert) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
280280

281281
// convertValue converts a value from its current type to the specified target type for CAST/CONVERT operations.
282282
// It handles type-specific conversion logic and applies length/scale constraints where applicable.
283-
// For SET types converting to CHAR/BINARY, the uint64 bit field values are converted to their string representation.
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.
284285
// If |typeLength| and |typeScale| are 0, they are ignored, otherwise they are used as constraints on the
285286
// converted type where applicable (e.g. Char conversion supports only |typeLength|, Decimal conversion supports
286287
// |typeLength| and |typeScale|).
@@ -292,7 +293,10 @@ func convertValue(ctx *sql.Context, val interface{}, castTo string, originType s
292293
}
293294
switch strings.ToLower(castTo) {
294295
case ConvertToBinary:
295-
val = convertSetToStringForStringContext(val, originType)
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+
}
296300
b, _, err := types.LongBlob.Convert(ctx, val)
297301
if err != nil {
298302
return nil, nil
@@ -311,7 +315,7 @@ func convertValue(ctx *sql.Context, val interface{}, castTo string, originType s
311315
}
312316
return truncateConvertedValue(b, typeLength)
313317
case ConvertToChar, ConvertToNChar:
314-
val = convertSetToStringForStringContext(val, originType)
318+
val, _ = types.TypeAwareConversion(ctx, val, originType, types.LongText)
315319
s, _, err := types.LongText.Convert(ctx, val)
316320
if err != nil {
317321
return nil, nil
@@ -473,19 +477,6 @@ func createConvertedDecimalType(length, scale int, logErrors bool) sql.DecimalTy
473477
return types.InternalDecimalType
474478
}
475479

476-
// convertSetToStringForStringContext converts SET type bit field values to their string representation
477-
// when converting to string-based types (CHAR, BINARY, etc.). This ensures that SET types are properly
478-
// represented as their comma-separated string values rather than their internal uint64 bit field values.
479-
func convertSetToStringForStringContext(val interface{}, originType sql.Type) interface{} {
480-
if setType, ok := originType.(sql.SetType); ok {
481-
if bitField, ok := val.(uint64); ok {
482-
if stringVal, err := setType.BitsToString(bitField); err == nil {
483-
return stringVal
484-
}
485-
}
486-
}
487-
return val
488-
}
489480

490481
// convertHexBlobToDecimalForNumericContext converts byte array value to unsigned int value if originType is BLOB type.
491482
// This function is called when convertTo type is number type only. The hex literal values are parsed into blobs as

0 commit comments

Comments
 (0)