-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
schemadiff: foreign key validation (tables and columns) #11944
Conversation
Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com>
Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com>
Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com>
Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com>
Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com>
…nKeyColumnCountError, MismatchingForeignKeyColumnTypeError Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com>
Review ChecklistHello reviewers! 👋 Please follow this checklist when reviewing this Pull Request. General
If a new flag is being introduced:
If a workflow is added or modified:
Bug fixes
Non-trivial changes
New/Existing features
Backward compatibility
|
Foreign keys tracking issue: #11975 |
go/vt/schemadiff/errors.go
Outdated
sqlescape.EscapeID(e.ReferencedTable), sqlescape.EscapeID(e.ReferencedColumn), sqlescape.EscapeID(e.Constraint), sqlescape.EscapeID(e.Table)) | ||
} | ||
|
||
type MismatchingForeignKeyColumnCountError struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Name suggestion: ForeignKeyColumnCountMismatchError
. I don't know if users ever see this though so it may not matter too much.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed
Table string | ||
} | ||
|
||
func (e *ForeignKeyDependencyUnresolvedError) Error() string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see a unit test for this new error type. 4 new errors, but only 1 new unit test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You must have missed them, the tests are as follows:
ForeignKeyDependencyUnresolvedError
has these unit tests:
- https://github.com/vitessio/vitess/pull/11944/files#diff-22a7f102b05d7044eda2deaa4242957aaffa51bfe99fb9a3e70dda855c6dc544R358-R378
- https://github.com/vitessio/vitess/pull/11944/files#diff-22a7f102b05d7044eda2deaa4242957aaffa51bfe99fb9a3e70dda855c6dc544R307-R310
InvalidColumnInForeignKeyConstraintError
has https://github.com/vitessio/vitess/pull/11944/files#diff-22a7f102b05d7044eda2deaa4242957aaffa51bfe99fb9a3e70dda855c6dc544R295-R298
ForeignKeyColumnCountMismatchError
has:
- https://github.com/vitessio/vitess/pull/11944/files#diff-22a7f102b05d7044eda2deaa4242957aaffa51bfe99fb9a3e70dda855c6dc544R299-R306
- https://github.com/vitessio/vitess/pull/11944/files#diff-2de8e8fe0a6b562dc9d4566b3de63c1718f3d3df4a938f9ce428ca22a7ebfc66R1481-R1486
MismatchingForeignKeyColumnTypeError
has https://github.com/vitessio/vitess/pull/11944/files#diff-22a7f102b05d7044eda2deaa4242957aaffa51bfe99fb9a3e70dda855c6dc544R319-R342
Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com>
@deepthi for another look please 🙏 |
go/vt/schemadiff/errors.go
Outdated
e.ReferencedColumnCount, sqlescape.EscapeID(e.Constraint), sqlescape.EscapeID(e.Table), e.ColumnCount) | ||
} | ||
|
||
type MismatchingForeignKeyColumnTypeError struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry I didn't catch this in the previous review. It will be good to rename this as well - to ForeignKeyColumnTypeMismatchError
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed!
…smatchError Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com>
Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com>
/cc @dbussink for review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly some questions but nothing blocking.
go/vt/schemadiff/schema.go
Outdated
// we stop when we have been unable to find a table in an iteration. | ||
fkParents := map[string]bool{} | ||
iterationLevel := 0 | ||
for ; ; iterationLevel++ { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd probably write this slight different like this:
for {
iterationLevel++
...
}
Reads simpler to me, but no strong opinion really on this.
The other question though is, would it be possible to craft a schema manually that triggers an infinite loop here? Should we have a safeguard for a max level we support?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it be possible to craft a schema manually that triggers an infinite loop
The algorithm addresses infinite loops. It leaves out any infinitely dependent views. There's a unit test for that:
vitess/go/vt/schemadiff/schema_test.go
Lines 126 to 135 in ec7e1a8
func TestNewSchemaFromQueriesLoop(t *testing.T) { | |
// v7 and v8 depend on each other | |
queries := append(createQueries, | |
"create view v7 as select * from v8, t2", | |
"create view v8 as select * from t1, v7", | |
) | |
_, err := NewSchemaFromQueries(queries) | |
assert.Error(t, err) | |
assert.EqualError(t, err, (&ViewDependencyUnresolvedError{View: "v7"}).Error()) | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just clarifying, that the rewrite would be:
for {
...
iterationLevel++
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
go/vt/schemadiff/schema.go
Outdated
// Now validate foreign key columns: | ||
// - referenced table columns must exist | ||
// - foreign key columns must match in count and type to referenced table columns | ||
// - referenced table as an appropriate index over referenced columns |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as an
=> has an
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
} | ||
} | ||
|
||
// TODO(shlomi): find a valid index |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is having an index a logical strict requirement or more an implementation detail of how MySQL uses it to enforce constraints?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MySQL requires you to have an index over foreign key columns; a future PR enforces that. If you create a foreign key without creating an index, MySQL implicitly creates one on your behalf. The key must cover all the FK columns as a prefix. See future PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The future PR being #12026
Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com>
Description
We improve
schemadiff
's support/validation for foreign keys as follows:schemadiff
analyzes foreign key dependency across the schemaint
to anint
, for example, and does not allowint
-to-bigint
. It does allow differentVARCHAR
length.Most of this takes place at the schema level, not at the table level.
Many tests added.
Still todo (in a different PR):
drop key
if it leaves a foreign key without an appropriate indexRelated Issue(s)
Foreign keys tracking issue: #11975
schemadiff
tracking issue: #10203Followup to #10359
Checklist
Deployment Notes