Skip to content

Commit 16ef988

Browse files
elianddbclaude
andcommitted
Fix enum default validation to use actual column names
- Move validateEnumLiteralDefault to resolve_column_defaults.go - Pass actual column name instead of '(unknown)' to match MySQL - MySQL returns 'Invalid default value for 'column_name'' format - Remove enum validation from CheckType to avoid duplicate logic - Verified behavior matches MySQL exactly for both invalid cases 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 121b5f3 commit 16ef988

File tree

2 files changed

+41
-35
lines changed

2 files changed

+41
-35
lines changed

sql/analyzer/resolve_column_defaults.go

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,14 +273,52 @@ func validateColumnDefault(ctx *sql.Context, col *sql.Column, colDefault *sql.Co
273273
return err
274274
}
275275

276-
// validate type of default expression
277-
if err = colDefault.CheckType(ctx); err != nil {
278-
return err
276+
// For enum literal defaults, use stricter validation than runtime conversion
277+
if enumType, isEnum := col.Type.(sql.EnumType); isEnum && colDefault.IsLiteral() {
278+
if err = validateEnumLiteralDefault(enumType, colDefault, col.Name, ctx); err != nil {
279+
return err
280+
}
281+
} else {
282+
// validate type of default expression
283+
if err = colDefault.CheckType(ctx); err != nil {
284+
return err
285+
}
279286
}
280287

281288
return nil
282289
}
283290

291+
// validateEnumLiteralDefault validates enum literal defaults more strictly than runtime conversions
292+
// MySQL doesn't allow numeric index references for literal enum defaults
293+
func validateEnumLiteralDefault(enumType sql.EnumType, colDefault *sql.ColumnDefaultValue, columnName string, ctx *sql.Context) error {
294+
val, err := colDefault.Expr.Eval(ctx, nil)
295+
if err != nil {
296+
return err
297+
}
298+
299+
switch v := val.(type) {
300+
case string:
301+
// For string values, check if it's a direct enum value match
302+
enumValues := enumType.Values()
303+
for _, enumVal := range enumValues {
304+
if enumVal == v {
305+
return nil // Valid enum value
306+
}
307+
}
308+
// String doesn't match any enum value, return appropriate error
309+
if v == "" {
310+
return sql.ErrIncompatibleDefaultType.New()
311+
}
312+
return sql.ErrInvalidColumnDefaultValue.New(columnName)
313+
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
314+
// MySQL doesn't allow numeric enum indices as literal defaults
315+
return sql.ErrInvalidColumnDefaultValue.New(columnName)
316+
default:
317+
// Other types not supported for enum defaults
318+
return sql.ErrIncompatibleDefaultType.New()
319+
}
320+
}
321+
284322
func stripTableNamesFromDefault(e *expression.Wrapper) (sql.Expression, transform.TreeIdentity, error) {
285323
newDefault, ok := e.Unwrap().(*sql.ColumnDefaultValue)
286324
if !ok {

sql/columndefault.go

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -227,12 +227,6 @@ func (e *ColumnDefaultValue) CheckType(ctx *Context) error {
227227
if val == nil && !e.ReturnNil {
228228
return ErrIncompatibleDefaultType.New()
229229
}
230-
231-
// For enum literal defaults, use stricter validation than runtime conversion
232-
if enumType, isEnum := e.OutType.(EnumType); isEnum {
233-
return e.validateEnumLiteralDefault(enumType, val)
234-
}
235-
236230
_, inRange, err := e.OutType.Convert(ctx, val)
237231
if err != nil {
238232
return ErrIncompatibleDefaultType.Wrap(err)
@@ -244,32 +238,6 @@ func (e *ColumnDefaultValue) CheckType(ctx *Context) error {
244238
return nil
245239
}
246240

247-
// validateEnumLiteralDefault validates enum literal defaults more strictly than runtime conversions
248-
// MySQL doesn't allow numeric index references for literal enum defaults
249-
func (e *ColumnDefaultValue) validateEnumLiteralDefault(enumType EnumType, val interface{}) error {
250-
switch v := val.(type) {
251-
case string:
252-
// For string values, check if it's a direct enum value match
253-
enumValues := enumType.Values()
254-
for _, enumVal := range enumValues {
255-
if enumVal == v {
256-
return nil // Valid enum value
257-
}
258-
}
259-
// String doesn't match any enum value, return appropriate error
260-
if v == "" {
261-
return ErrIncompatibleDefaultType.New()
262-
}
263-
return ErrInvalidColumnDefaultValue.New("(unknown)")
264-
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
265-
// MySQL doesn't allow numeric enum indices as literal defaults
266-
return ErrInvalidColumnDefaultValue.New("(unknown)")
267-
default:
268-
// Other types not supported for enum defaults
269-
return ErrIncompatibleDefaultType.New()
270-
}
271-
}
272-
273241
type UnresolvedColumnDefault struct {
274242
ExprString string
275243
}

0 commit comments

Comments
 (0)