Skip to content

Commit

Permalink
schemadiff: ViewDependencyUnresolvedError lists missing referenced en…
Browse files Browse the repository at this point in the history
…tities

Signed-off-by: Shlomi Noach <[email protected]>
  • Loading branch information
shlomi-noach committed Feb 6, 2025
1 parent e08d85c commit 3a238d1
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 7 deletions.
9 changes: 7 additions & 2 deletions go/vt/schemadiff/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -389,11 +389,16 @@ func (e *IndexNeededByForeignKeyError) Error() string {
}

type ViewDependencyUnresolvedError struct {
View string
View string
MissingReferencedEntities []string
}

func (e *ViewDependencyUnresolvedError) Error() string {
return fmt.Sprintf("view %s has unresolved/loop dependencies", sqlescape.EscapeID(e.View))
s := make([]string, len(e.MissingReferencedEntities))
for i, entity := range e.MissingReferencedEntities {
s[i] = sqlescape.EscapeID(entity)
}
return fmt.Sprintf("view %s has unresolved/loop dependencies: %s", sqlescape.EscapeID(e.View), strings.Join(s, ", "))
}

type InvalidColumnReferencedInViewError struct {
Expand Down
9 changes: 8 additions & 1 deletion go/vt/schemadiff/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,14 @@ func (s *Schema) normalize(hints *DiffHints) error {
if _, ok := dependencyLevels[v.Name()]; !ok {
// We _know_ that in this iteration, at least one view is found unassigned a dependency level.
// We gather all the errors.
errs = errors.Join(errs, &ViewDependencyUnresolvedError{View: v.ViewName.Name.String()})
dependentNames := getViewDependentTableNames(v.CreateView)
missingReferencedEntities := []string{}
for _, name := range dependentNames {
if _, ok := dependencyLevels[name]; !ok {
missingReferencedEntities = append(missingReferencedEntities, name)
}
}
errs = errors.Join(errs, &ViewDependencyUnresolvedError{View: v.ViewName.Name.String(), MissingReferencedEntities: missingReferencedEntities})
// We still add it so it shows up in the output if that is used for anything.
s.sorted = append(s.sorted, v)
}
Expand Down
21 changes: 17 additions & 4 deletions go/vt/schemadiff/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,25 @@ func TestNewSchemaFromQueriesUnresolved(t *testing.T) {
)
schema, err := NewSchemaFromQueries(NewTestEnv(), queries)
assert.Error(t, err)
assert.EqualError(t, err, (&ViewDependencyUnresolvedError{View: "v7"}).Error())
assert.EqualError(t, err, (&ViewDependencyUnresolvedError{View: "v7", MissingReferencedEntities: []string{"v8"}}).Error())
v := schema.sorted[len(schema.sorted)-1]
assert.IsType(t, &CreateViewEntity{}, v)
assert.Equal(t, "CREATE VIEW `v7` AS SELECT * FROM `v8`, `t2`", v.Create().CanonicalStatementString())
}

func TestNewSchemaFromQueriesUnresolvedMulti(t *testing.T) {
// v8 does not exist
queries := append(schemaTestCreateQueries,
"create view v7 as select * from v8, t2, t20, v21",
)
schema, err := NewSchemaFromQueries(NewTestEnv(), queries)
assert.Error(t, err)
assert.EqualError(t, err, (&ViewDependencyUnresolvedError{View: "v7", MissingReferencedEntities: []string{"v8", "t20", "v21"}}).Error())
v := schema.sorted[len(schema.sorted)-1]
assert.IsType(t, &CreateViewEntity{}, v)
assert.Equal(t, "CREATE VIEW `v7` AS SELECT * FROM `v8`, `t2`, `t20`, `v21`", v.Create().CanonicalStatementString())
}

func TestNewSchemaFromQueriesWithSQLKeyword(t *testing.T) {
queries := []string{
"create table `order` (id int primary key, info int not null)",
Expand All @@ -141,7 +154,7 @@ func TestNewSchemaFromQueriesUnresolvedAlias(t *testing.T) {
)
_, err := NewSchemaFromQueries(NewTestEnv(), queries)
assert.Error(t, err)
assert.EqualError(t, err, (&ViewDependencyUnresolvedError{View: "v7"}).Error())
assert.EqualError(t, err, (&ViewDependencyUnresolvedError{View: "v7", MissingReferencedEntities: []string{"something_else"}}).Error())
}

func TestNewSchemaFromQueriesViewFromDual(t *testing.T) {
Expand Down Expand Up @@ -171,7 +184,7 @@ func TestNewSchemaFromQueriesLoop(t *testing.T) {
_, err := NewSchemaFromQueries(NewTestEnv(), queries)
require.Error(t, err)
err = vterrors.UnwrapFirst(err)
assert.EqualError(t, err, (&ViewDependencyUnresolvedError{View: "v7"}).Error())
assert.EqualError(t, err, (&ViewDependencyUnresolvedError{View: "v7", MissingReferencedEntities: []string{"v8"}}).Error())
}

func TestToSQL(t *testing.T) {
Expand Down Expand Up @@ -582,7 +595,7 @@ SELECT
) AS ranking
FROM users AS u JOIN earnings AS e ON e.user_id = u.id;
`,
expectErr: &ViewDependencyUnresolvedError{View: "user_earnings_ranking"},
expectErr: &ViewDependencyUnresolvedError{View: "user_earnings_ranking", MissingReferencedEntities: []string{"earnings"}},
},
}
for _, ts := range tt {
Expand Down

0 comments on commit 3a238d1

Please sign in to comment.