Skip to content

Commit f6d221d

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 e4d9d0a commit f6d221d

File tree

2 files changed

+23
-6
lines changed

2 files changed

+23
-6
lines changed

enginetest/queries/script_queries.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9911,21 +9911,19 @@ where
99119911
},
99129912
},
99139913
{
9914-
// https://github.com/dolthub/dolt/issues/9511
9915-
Skip: true,
99169914
Query: "select s, cast(s as char) from t order by s;",
99179915
Expected: []sql.Row{
99189916
{"abc", "abc"},
9917+
{"defg", "defg"},
99199918
{"abc,defg", "abc,defg"},
99209919
{"abc,defg,hijkl", "abc,defg,hijkl"},
99219920
},
99229921
},
99239922
{
9924-
// https://github.com/dolthub/dolt/issues/9511
9925-
Skip: true,
99269923
Query: "select s, cast(s as binary) from t order by s;",
99279924
Expected: []sql.Row{
99289925
{"abc", []uint8("abc")},
9926+
{"defg", []uint8("defg")},
99299927
{"abc,defg", []uint8("abc,defg")},
99309928
{"abc,defg,hijkl", []uint8("abc,defg,hijkl")},
99319929
},

sql/expression/convert.go

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,17 +278,21 @@ 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 types converting to CHAR/BINARY, the uint64 bit field values are converted to their string representation.
283284
// If |typeLength| and |typeScale| are 0, they are ignored, otherwise they are used as constraints on the
284285
// converted type where applicable (e.g. Char conversion supports only |typeLength|, Decimal conversion supports
285286
// |typeLength| and |typeScale|).
287+
// Only returns an error if converting to JSON, Date, and Datetime; the zero value is returned for float types.
288+
// Nil is returned in all other cases.
286289
func convertValue(ctx *sql.Context, val interface{}, castTo string, originType sql.Type, typeLength, typeScale int) (interface{}, error) {
287290
if val == nil {
288291
return nil, nil
289292
}
290293
switch strings.ToLower(castTo) {
291294
case ConvertToBinary:
295+
val = convertSetToStringForStringContext(val, originType)
292296
b, _, err := types.LongBlob.Convert(ctx, val)
293297
if err != nil {
294298
return nil, nil
@@ -307,6 +311,7 @@ func convertValue(ctx *sql.Context, val interface{}, castTo string, originType s
307311
}
308312
return truncateConvertedValue(b, typeLength)
309313
case ConvertToChar, ConvertToNChar:
314+
val = convertSetToStringForStringContext(val, originType)
310315
s, _, err := types.LongText.Convert(ctx, val)
311316
if err != nil {
312317
return nil, nil
@@ -468,6 +473,20 @@ func createConvertedDecimalType(length, scale int, logErrors bool) sql.DecimalTy
468473
return types.InternalDecimalType
469474
}
470475

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+
}
489+
471490
// convertHexBlobToDecimalForNumericContext converts byte array value to unsigned int value if originType is BLOB type.
472491
// This function is called when convertTo type is number type only. The hex literal values are parsed into blobs as
473492
// binary string as default, but for numeric context, the value should be a number.

0 commit comments

Comments
 (0)