Skip to content

Commit 10a6916

Browse files
schemadiff: ViewDependencyUnresolvedError lists missing referenced entities (vitessio#17711)
Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com> Signed-off-by: Dirkjan Bussink <d.bussink@gmail.com> Co-authored-by: Dirkjan Bussink <d.bussink@gmail.com>
1 parent 1c56ca1 commit 10a6916

File tree

3 files changed

+37
-7
lines changed

3 files changed

+37
-7
lines changed

go/vt/schemadiff/errors.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -389,11 +389,20 @@ func (e *IndexNeededByForeignKeyError) Error() string {
389389
}
390390

391391
type ViewDependencyUnresolvedError struct {
392-
View string
392+
View string
393+
MissingReferencedEntities []string
393394
}
394395

395396
func (e *ViewDependencyUnresolvedError) Error() string {
396-
return fmt.Sprintf("view %s has unresolved/loop dependencies", sqlescape.EscapeID(e.View))
397+
var b strings.Builder
398+
fmt.Fprintf(&b, "view %s has unresolved/loop dependencies: ", sqlescape.EscapeID(e.View))
399+
for i, entity := range e.MissingReferencedEntities {
400+
if i > 0 {
401+
b.WriteString(", ")
402+
}
403+
sqlescape.WriteEscapeID(&b, entity)
404+
}
405+
return b.String()
397406
}
398407

399408
type InvalidColumnReferencedInViewError struct {

go/vt/schemadiff/schema.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,14 @@ func (s *Schema) normalize(hints *DiffHints) error {
341341
if _, ok := dependencyLevels[v.Name()]; !ok {
342342
// We _know_ that in this iteration, at least one view is found unassigned a dependency level.
343343
// We gather all the errors.
344-
errs = errors.Join(errs, &ViewDependencyUnresolvedError{View: v.ViewName.Name.String()})
344+
dependentNames := getViewDependentTableNames(v.CreateView)
345+
missingReferencedEntities := []string{}
346+
for _, name := range dependentNames {
347+
if _, ok := dependencyLevels[name]; !ok {
348+
missingReferencedEntities = append(missingReferencedEntities, name)
349+
}
350+
}
351+
errs = errors.Join(errs, &ViewDependencyUnresolvedError{View: v.ViewName.Name.String(), MissingReferencedEntities: missingReferencedEntities})
345352
// We still add it so it shows up in the output if that is used for anything.
346353
s.sorted = append(s.sorted, v)
347354
}

go/vt/schemadiff/schema_test.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,26 @@ func TestNewSchemaFromQueriesUnresolved(t *testing.T) {
119119
)
120120
schema, err := NewSchemaFromQueries(NewTestEnv(), queries)
121121
assert.Error(t, err)
122-
assert.EqualError(t, err, (&ViewDependencyUnresolvedError{View: "v7"}).Error())
122+
assert.EqualError(t, err, (&ViewDependencyUnresolvedError{View: "v7", MissingReferencedEntities: []string{"v8"}}).Error())
123123
v := schema.sorted[len(schema.sorted)-1]
124124
assert.IsType(t, &CreateViewEntity{}, v)
125125
assert.Equal(t, "CREATE VIEW `v7` AS SELECT * FROM `v8`, `t2`", v.Create().CanonicalStatementString())
126126
}
127127

128+
func TestNewSchemaFromQueriesUnresolvedMulti(t *testing.T) {
129+
// v8 does not exist
130+
queries := append(schemaTestCreateQueries,
131+
"create view v7 as select * from v8, t2, t20, v21",
132+
)
133+
schema, err := NewSchemaFromQueries(NewTestEnv(), queries)
134+
assert.Error(t, err)
135+
assert.EqualError(t, err, (&ViewDependencyUnresolvedError{View: "v7", MissingReferencedEntities: []string{"v8", "t20", "v21"}}).Error())
136+
assert.Equal(t, "view `v7` has unresolved/loop dependencies: `v8`, `t20`, `v21`", err.Error())
137+
v := schema.sorted[len(schema.sorted)-1]
138+
assert.IsType(t, &CreateViewEntity{}, v)
139+
assert.Equal(t, "CREATE VIEW `v7` AS SELECT * FROM `v8`, `t2`, `t20`, `v21`", v.Create().CanonicalStatementString())
140+
}
141+
128142
func TestNewSchemaFromQueriesWithSQLKeyword(t *testing.T) {
129143
queries := []string{
130144
"create table `order` (id int primary key, info int not null)",
@@ -141,7 +155,7 @@ func TestNewSchemaFromQueriesUnresolvedAlias(t *testing.T) {
141155
)
142156
_, err := NewSchemaFromQueries(NewTestEnv(), queries)
143157
assert.Error(t, err)
144-
assert.EqualError(t, err, (&ViewDependencyUnresolvedError{View: "v7"}).Error())
158+
assert.EqualError(t, err, (&ViewDependencyUnresolvedError{View: "v7", MissingReferencedEntities: []string{"something_else"}}).Error())
145159
}
146160

147161
func TestNewSchemaFromQueriesViewFromDual(t *testing.T) {
@@ -171,7 +185,7 @@ func TestNewSchemaFromQueriesLoop(t *testing.T) {
171185
_, err := NewSchemaFromQueries(NewTestEnv(), queries)
172186
require.Error(t, err)
173187
err = vterrors.UnwrapFirst(err)
174-
assert.EqualError(t, err, (&ViewDependencyUnresolvedError{View: "v7"}).Error())
188+
assert.EqualError(t, err, (&ViewDependencyUnresolvedError{View: "v7", MissingReferencedEntities: []string{"v8"}}).Error())
175189
}
176190

177191
func TestToSQL(t *testing.T) {
@@ -582,7 +596,7 @@ SELECT
582596
) AS ranking
583597
FROM users AS u JOIN earnings AS e ON e.user_id = u.id;
584598
`,
585-
expectErr: &ViewDependencyUnresolvedError{View: "user_earnings_ranking"},
599+
expectErr: &ViewDependencyUnresolvedError{View: "user_earnings_ranking", MissingReferencedEntities: []string{"earnings"}},
586600
},
587601
}
588602
for _, ts := range tt {

0 commit comments

Comments
 (0)