From c214f7ad51c512e07107b182eb1e8b59b80a100f Mon Sep 17 00:00:00 2001 From: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com> Date: Tue, 5 Dec 2023 15:23:04 +0200 Subject: [PATCH] schemadiff: granular foreign key reference errors Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com> --- go/vt/schemadiff/errors.go | 20 ++++++++++++++++++++ go/vt/schemadiff/schema.go | 8 ++++++++ go/vt/schemadiff/schema_test.go | 10 +++++++++- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/go/vt/schemadiff/errors.go b/go/vt/schemadiff/errors.go index 8317fbe9cea..723240f0d02 100644 --- a/go/vt/schemadiff/errors.go +++ b/go/vt/schemadiff/errors.go @@ -286,6 +286,26 @@ func (e *ForeignKeyDependencyUnresolvedError) Error() string { sqlescape.EscapeID(e.Table)) } +type ForeignKeyNonexistentReferencedTableError struct { + Table string + ReferencedTable string +} + +func (e *ForeignKeyNonexistentReferencedTableError) Error() string { + return fmt.Sprintf("table %s foreign key references nonexistent table %s", + sqlescape.EscapeID(e.Table), sqlescape.EscapeID(e.ReferencedTable)) +} + +type ForeignKeyReferencesViewError struct { + Table string + ReferencedView string +} + +func (e *ForeignKeyReferencesViewError) Error() string { + return fmt.Sprintf("table %s foreign key references view %s", + sqlescape.EscapeID(e.Table), sqlescape.EscapeID(e.ReferencedView)) +} + type InvalidColumnInForeignKeyConstraintError struct { Table string Constraint string diff --git a/go/vt/schemadiff/schema.go b/go/vt/schemadiff/schema.go index c34f05b7a9f..405ad6c7f45 100644 --- a/go/vt/schemadiff/schema.go +++ b/go/vt/schemadiff/schema.go @@ -239,6 +239,14 @@ func (s *Schema) normalize() error { if referencedTableName != name { nonSelfReferenceNames = append(nonSelfReferenceNames, referencedTableName) } + referencedEntity, ok := s.named[referencedTableName] + if !ok { + return &ForeignKeyNonexistentReferencedTableError{Table: name, ReferencedTable: referencedTableName} + } + if _, ok := referencedEntity.(*CreateViewEntity); ok { + return &ForeignKeyReferencesViewError{Table: name, ReferencedView: referencedTableName} + } + fkParents[referencedTableName] = true } if allNamesFoundInLowerLevel(nonSelfReferenceNames, iterationLevel) { diff --git a/go/vt/schemadiff/schema_test.go b/go/vt/schemadiff/schema_test.go index 3a609bdf769..c2c17df3080 100644 --- a/go/vt/schemadiff/schema_test.go +++ b/go/vt/schemadiff/schema_test.go @@ -331,7 +331,15 @@ func TestInvalidSchema(t *testing.T) { expectErr: &ForeignKeyColumnCountMismatchError{Table: "t11", Constraint: "f11", ColumnCount: 2, ReferencedTable: "t11", ReferencedColumnCount: 1}, }, { - schema: "create table t11 (id int primary key, i int, constraint f12 foreign key (i) references t12(id) on delete restrict)", + schema: "create table t11 (id int primary key, i int, constraint f12 foreign key (i) references t12 (id) on delete restrict)", + expectErr: &ForeignKeyNonexistentReferencedTableError{Table: "t11", ReferencedTable: "t12"}, + }, + { + schema: "create view v as select 1 as id from dual; create table t11 (id int primary key, i int, constraint fv foreign key (i) references v (id) on delete restrict)", + expectErr: &ForeignKeyReferencesViewError{Table: "t11", ReferencedView: "v"}, + }, + { + schema: "create table t11 (id int primary key, i int, constraint f11 foreign key (i) references t12 (id) on delete restrict); create table t12 (id int primary key, i int, constraint f12 foreign key (i) references t11 (id) on delete restrict)", expectErr: &ForeignKeyDependencyUnresolvedError{Table: "t11"}, }, {