Skip to content

Commit 2f80db5

Browse files
committed
Fixed error handling on type conversion errros
1 parent 6a5e2ee commit 2f80db5

File tree

1 file changed

+26
-23
lines changed

1 file changed

+26
-23
lines changed

sql/plan/foreign_key_editor.go

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ func (fkEditor *ForeignKeyEditor) OnUpdateSetNull(ctx *sql.Context, refActionDat
228228

229229
// Delete handles both the standard DELETE statement and propagated referential actions from a parent table's ON DELETE.
230230
func (fkEditor *ForeignKeyEditor) Delete(ctx *sql.Context, row sql.Row, depth int) error {
231-
//TODO: may need to process some cascades after the update to avoid recursive violations, write some tests on this
231+
// TODO: may need to process some cascades after the update to avoid recursive violations, write some tests on this
232232
for _, refActionData := range fkEditor.RefActions {
233233
switch refActionData.ForeignKey.OnDelete {
234234
default: // RESTRICT and friends
@@ -426,7 +426,7 @@ func (reference *ForeignKeyReferenceHandler) CheckReference(ctx *sql.Context, ro
426426
return nil
427427
}
428428
}
429-
429+
430430
return sql.ErrForeignKeyChildViolation.New(reference.ForeignKey.Name, reference.ForeignKey.Table,
431431
reference.ForeignKey.ParentTable, reference.RowMapper.GetKeyString(row))
432432
}
@@ -458,7 +458,7 @@ type ForeignKeyRowMapper struct {
458458
Updater sql.ForeignKeyEditor
459459
SourceSch sql.Schema
460460
// TargetTypeConversions are a set of functions to transform the value in the table to the corresponding value in the
461-
// other table. This is required when the types of the two tables are compatible but different (e.g. INT and BIGINT).
461+
// other table. This is required when the types of the two tables are compatible but different (e.g. INT and BIGINT).
462462
TargetTypeConversions []ForeignKeyTypeConversionFn
463463
// IndexPositions hold the mapping between an index's column position and the source row's column position. Given
464464
// an index (x1, x2) and a source row (y1, y2, y3) and the relation (x1->y3, x2->y1), this slice would contain
@@ -486,18 +486,20 @@ func (mapper *ForeignKeyRowMapper) GetIter(ctx *sql.Context, row sql.Row, refChe
486486
if rowVal == nil {
487487
return sql.RowsToRowIter(), nil
488488
}
489-
489+
490490
targetType := mapper.SourceSch[rowPos].Type
491491
// Transform the type of the value in this row to the one in the other table for the index lookup, if necessary
492492
if mapper.TargetTypeConversions != nil && mapper.TargetTypeConversions[rowPos] != nil {
493493
var err error
494494
targetType, rowVal, err = mapper.TargetTypeConversions[rowPos](ctx, rowVal)
495-
// TODO: possible for this to fail without error, which means the value cannot be found in the other table
495+
// An error means the type conversion failed, which typically means there's no way to convert the value given to
496+
// the target value because of e.g. range constraints (trying to assign an INT to a TINYINT column). We treat
497+
// this as an empty result for this iterator, since this value cannot possibly be present in the other table.
496498
if err != nil {
497-
return nil, err
499+
return sql.RowsToRowIter(), nil
498500
}
499501
}
500-
502+
501503
rang[rangPosition] = sql.ClosedRangeColumnExpr(rowVal, rowVal, targetType)
502504
}
503505
for i, appendType := range mapper.AppendTypes {
@@ -507,7 +509,7 @@ func (mapper *ForeignKeyRowMapper) GetIter(ctx *sql.Context, row sql.Row, refChe
507509
if !mapper.Index.CanSupport(rang) {
508510
return nil, ErrInvalidLookupForIndexedTable.New(rang.DebugString())
509511
}
510-
//TODO: profile this, may need to redesign this or add a fast path
512+
// TODO: profile this, may need to redesign this or add a fast path
511513
lookup := sql.IndexLookup{Ranges: sql.MySQLRangeCollection{rang}, Index: mapper.Index}
512514

513515
editorData := mapper.Updater.IndexedAccess(lookup)
@@ -557,9 +559,10 @@ func GetChildParentMapping(parentSch sql.Schema, childSch sql.Schema, fkDef sql.
557559
return mapping, nil
558560
}
559561

560-
// ForeignKeyTypeConversionDirection specifies whether a child column type is being converted to its parent type for
562+
// ForeignKeyTypeConversionDirection specifies whether a child column type is being converted to its parent type for
561563
// constraint enforcement, or vice versa.
562564
type ForeignKeyTypeConversionDirection byte
565+
563566
const (
564567
ChildToParent ForeignKeyTypeConversionDirection = iota
565568
ParentToChild
@@ -569,17 +572,17 @@ const (
569572
// enforcement. The target type is returned along with the transformed value, or an error if the transformation fails.
570573
type ForeignKeyTypeConversionFn func(ctx *sql.Context, val any) (sql.Type, any, error)
571574

572-
// GetForeignKeyTypeConversions returns a set of functions to convert a type in a one foreign key column table to the
575+
// GetForeignKeyTypeConversions returns a set of functions to convert a type in a one foreign key column table to the
573576
// type in the corresponding table. Specify the schema of both child and parent tables, as well as whether the
574577
// transformation is from child to parent or vice versa.
575578
func GetForeignKeyTypeConversions(
576-
parentSch sql.Schema,
577-
childSch sql.Schema,
578-
fkDef sql.ForeignKeyConstraint,
579-
direction ForeignKeyTypeConversionDirection,
579+
parentSch sql.Schema,
580+
childSch sql.Schema,
581+
fkDef sql.ForeignKeyConstraint,
582+
direction ForeignKeyTypeConversionDirection,
580583
) ([]ForeignKeyTypeConversionFn, error) {
581-
var mapping []ForeignKeyTypeConversionFn
582-
584+
var convFns []ForeignKeyTypeConversionFn
585+
583586
for i := range fkDef.Columns {
584587
childIndex := childSch.IndexOfColName(fkDef.Columns[i])
585588
if childIndex < 0 {
@@ -594,13 +597,13 @@ func GetForeignKeyTypeConversions(
594597

595598
childType := childSch[childIndex].Type
596599
parentType := parentSch[parentIndex].Type
597-
600+
598601
childExtendedType, _ := childType.(types.ExtendedType)
599602
// if even one of the types is not an extended type, then we can't transform any values
600603
if childExtendedType == nil {
601604
return nil, nil
602605
}
603-
606+
604607
if !childType.Equals(parentType) {
605608
parentExtendedType, _ := parentType.(types.ExtendedType)
606609
if parentExtendedType == nil {
@@ -615,15 +618,15 @@ func GetForeignKeyTypeConversions(
615618
toType = childExtendedType
616619
}
617620

618-
if mapping == nil {
619-
mapping = make([]ForeignKeyTypeConversionFn, len(childSch))
621+
if convFns == nil {
622+
convFns = make([]ForeignKeyTypeConversionFn, len(childSch))
620623
}
621-
mapping[childIndex] = func(ctx *sql.Context, val any) (sql.Type, any, error) {
624+
convFns[childIndex] = func(ctx *sql.Context, val any) (sql.Type, any, error) {
622625
convertedVal, err := toType.ConvertToType(ctx, fromType, val)
623626
return toType, convertedVal, err
624627
}
625628
}
626629
}
627-
628-
return mapping, nil
630+
631+
return convFns, nil
629632
}

0 commit comments

Comments
 (0)