Skip to content
2 changes: 1 addition & 1 deletion enginetest/queries/insert_queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -2836,7 +2836,7 @@ var InsertIgnoreScripts = []ScriptTest{
Assertions: []ScriptTestAssertion{
{
Query: "insert into test_table values (1, 'invalid'), (2, 'comparative politics'), (3, null)",
ExpectedErr: types.ErrConvertingToEnum, // TODO: should be ErrDataTruncatedForColumn
ExpectedErr: types.ErrDataTruncatedForColumnAtRow,
},
{
Query: "insert ignore into test_table values (1, 'invalid'), (2, 'bye'), (3, null)",
Expand Down
30 changes: 15 additions & 15 deletions enginetest/queries/script_queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -1202,7 +1202,7 @@ CREATE TABLE tab3 (
{
// enum values must match EXACTLY for case-sensitive collations
Query: "INSERT INTO enumtest1 VALUES (10, 'ABC'), (11, 'aBc'), (12, 'xyz');",
ExpectedErrStr: "value ABC is not valid for this Enum",
ExpectedErrStr: "Data truncated for column 'e' at row 1",
},
{
Query: "SHOW CREATE TABLE enumtest1;",
Expand Down Expand Up @@ -8053,11 +8053,11 @@ where
Assertions: []ScriptTestAssertion{
{
Query: "insert into t values (1, 500)",
ExpectedErrStr: "value 500 is not valid for this Enum",
ExpectedErrStr: "Data truncated for column 'e' at row 1",
},
{
Query: "insert into t values (1, -1)",
ExpectedErrStr: "value -1 is not valid for this Enum",
ExpectedErrStr: "Data truncated for column 'e' at row 1",
},
},
},
Expand Down Expand Up @@ -9164,7 +9164,7 @@ where
},
},
{
Skip: true,
Skip: false,
Name: "enums with foreign keys",
Dialect: "mysql",
SetUpScript: []string{
Expand Down Expand Up @@ -9207,7 +9207,7 @@ where
},
{
Query: "insert into child1 values (3);",
ExpectedErr: sql.ErrForeignKeyParentViolation,
ExpectedErr: sql.ErrForeignKeyChildViolation,
},
{
Query: "insert into child1 values ('x'), ('y');",
Expand All @@ -9217,11 +9217,11 @@ where
},
{
Query: "insert into child1 values ('z');",
ExpectedErr: sql.ErrForeignKeyParentViolation,
ExpectedErr: sql.ErrForeignKeyChildViolation,
},
{
Query: "insert into child1 values ('a');",
ExpectedErrStr: "Data truncated for column 'e'",
ExpectedErrStr: "Data truncated for column 'e' at row 1",
},
{
Query: "select * from child1 order by e;",
Expand All @@ -9247,7 +9247,7 @@ where
},
{
Query: "insert into child2 values (3);",
ExpectedErr: sql.ErrForeignKeyParentViolation,
ExpectedErr: sql.ErrForeignKeyChildViolation,
},
{
Query: "insert into child2 values ('c');",
Expand All @@ -9257,14 +9257,14 @@ where
},
{
Query: "insert into child2 values ('a');",
ExpectedErr: sql.ErrForeignKeyParentViolation,
ExpectedErr: sql.ErrForeignKeyChildViolation,
},
{
Query: "select * from child2 order by e;",
Expected: []sql.Row{
{"b"},
{"c"},
{"c"},
{"b"},
},
},

Expand All @@ -9282,7 +9282,7 @@ where
},
{
Query: "insert into child3 values (3);",
ExpectedErr: sql.ErrForeignKeyParentViolation,
ExpectedErr: sql.ErrForeignKeyChildViolation,
},
{
Query: "insert into child3 values ('x'), ('y');",
Expand All @@ -9292,11 +9292,11 @@ where
},
{
Query: "insert into child3 values ('z');",
ExpectedErr: sql.ErrForeignKeyParentViolation,
ExpectedErr: sql.ErrForeignKeyChildViolation,
},
{
Query: "insert into child3 values ('a');",
ExpectedErr: sql.ErrForeignKeyParentViolation,
ExpectedErr: sql.ErrForeignKeyChildViolation,
},
{
Query: "select * from child3 order by e;",
Expand All @@ -9322,7 +9322,7 @@ where
},
{
Query: "insert into child4 values (3);",
ExpectedErrStr: "Data truncated for column 'e'",
ExpectedErrStr: "Data truncated for column 'e' at row 1",
},
{
Query: "insert into child4 values ('q');",
Expand All @@ -9332,7 +9332,7 @@ where
},
{
Query: "insert into child4 values ('a');",
ExpectedErrStr: "Data truncated for column 'e'",
ExpectedErrStr: "Data truncated for column 'e' at row 1",
},
{
Query: "select * from child4 order by e;",
Expand Down
4 changes: 4 additions & 0 deletions sql/plan/alter_foreign_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,10 @@ func foreignKeyComparableTypes(ctx *sql.Context, type1 sql.Type, type2 sql.Type)
if type1String.Collation().CharacterSet() != type2String.Collation().CharacterSet() {
return false
}
case sqltypes.Enum:
// Enum types can reference each other in foreign keys regardless of their string values.
// MySQL allows enum foreign keys to match based on underlying numeric values.
return true
default:
return false
}
Expand Down
6 changes: 6 additions & 0 deletions sql/rowexec/insert.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ type insertIter struct {
firstGeneratedAutoIncRowIdx int

deferredDefaults sql.FastIntSet
rowNumber int64
}

func getInsertExpressions(values sql.Node) []sql.Expression {
Expand All @@ -74,6 +75,9 @@ func (i *insertIter) Next(ctx *sql.Context) (returnRow sql.Row, returnErr error)
return nil, i.ignoreOrClose(ctx, row, err)
}

// Increment row number for error reporting (MySQL starts at 1)
i.rowNumber++

// Prune the row down to the size of the schema. It can be larger in the case of running with an outer scope, in which
// case the additional scope variables are prepended to the row.
if len(row) > len(i.schema) {
Expand Down Expand Up @@ -140,6 +144,8 @@ func (i *insertIter) Next(ctx *sql.Context) (returnRow sql.Row, returnErr error)
cErr = types.ErrLengthBeyondLimit.New(row[idx], col.Name)
} else if sql.ErrNotMatchingSRID.Is(cErr) {
cErr = sql.ErrNotMatchingSRIDWithColName.New(col.Name, cErr)
} else if types.ErrConvertingToEnum.Is(cErr) {
cErr = types.ErrDataTruncatedForColumnAtRow.New(col.Name, i.rowNumber)
}
return nil, sql.NewWrappedInsertError(origRow, cErr)
}
Expand Down
3 changes: 2 additions & 1 deletion sql/types/enum.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ const (
var (
ErrConvertingToEnum = errors.NewKind("value %v is not valid for this Enum")

ErrDataTruncatedForColumn = errors.NewKind("Data truncated for column '%s'")
ErrDataTruncatedForColumn = errors.NewKind("Data truncated for column '%s'")
ErrDataTruncatedForColumnAtRow = errors.NewKind("Data truncated for column '%s' at row %d")

enumValueType = reflect.TypeOf(uint16(0))
)
Expand Down