-
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: logically Apply() a diff to a CreateTable, CreateView or to a Schema #10183
schemadiff: logically Apply() a diff to a CreateTable, CreateView or to a Schema #10183
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>
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>
Working on final test failures. Moving to draft in the meantime. |
Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com>
Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com>
OK all good. I accidentally made a regression and pushed it before testing. Now fixed. |
@@ -134,6 +135,8 @@ func getViewDependentTableNames(createView *sqlparser.CreateView) (names []strin | |||
// normalize is called as part of Schema creation process. The user may only get a hold of normalized schema. | |||
// It validates some cross-entity constraints, and orders entity based on dependencies (e.g. tables, views that read from tables, 2nd level views, etc.) | |||
func (s *Schema) normalize() error { | |||
s.named = map[string]Entity{} | |||
s.sorted = []Entity{} |
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.
Are these added for a specific reason?
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.
They are. At the end of apply()
we call normalize, and we need to make sure that existing named
values are erased. sorted
happens to be unpopulated; but normalize
really expects both to be empty.
We could clear both in apply
, as right now this is the only path where the values get populated before normalize
. But I feel normalize
is the safer place to do that.
if !ok { | ||
return ErrEntityTypeMismatch | ||
} | ||
s.tables[i] = toCreateTableEntity |
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.
Does s.named
need to be updated here?
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.
It does not, because it is implied that the view name already exists in named
, and an update would just re-apply same name.
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.
@shlomi-noach I'm probably missing something, but doesn't then calling for example Entity(name)
return the old entity without the change applied? Or is this updated then somewhere else?
The reason I was asking is because this does get updated on create / drop so that's what caught my eye.
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.
@dbussink gotcha. named
is only used in this function to determine existence/nonexistence of an entity. At the end of this function, we call normalize()
which completely rebuilds named
. We could update the entity value here, but it then gets deleted and recreated in normalize
anyhow.
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.
@shlomi-noach Ah ok, if that's the case I think there's an inconsistency though in the add / drop logic.
When a create is done, we don't add it to named
so if the diffs
slice has multiple creates for the same table, it would not error but have a last one wins.
On the other hand, if diffs
contains multiple drops for the same table, it would error on the second one since it does delete from named
.
I have no super strong opinion on what the behavior should be, but I think it should be consistent between create and drop?
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're right, there is an inconsistency. Fixing.
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.
Please see updates to Schema.apply()
and consistent use of s.named
if !ok { | ||
return ErrEntityTypeMismatch | ||
} | ||
s.views[i] = toCreateViewEntity |
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.
Same here, does s.named
need to be updated?
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.
same as above, there is no need.
@@ -275,6 +277,46 @@ func (c *CreateTableEntity) diffTableCharset( | |||
return "" | |||
} | |||
|
|||
// isDefaultTableOptionValue sees if the value for a TableOption is also its default value | |||
func isDefaultTableOptionValue(option *sqlparser.TableOption) bool { |
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.
Not for this PR, but should there be something similar for what the defaults are for column level options?
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.
for our discussion later on.
go/vt/schemadiff/table.go
Outdated
} | ||
} | ||
if !afterColFound { | ||
return errors.Wrapf(ErrApplyColumnNotFound, "%v", after.Name.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.
Can this be simplified to errors.Wrap(ErrApplyColumnNotFound, after.Name.String())
? And for all the other further cases down in this file?
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.
done
go/vt/schemadiff/table.go
Outdated
return errors.Wrapf(ErrApplyColumnNotFound, "%v", after.Name.String()) | ||
} | ||
default: | ||
// no change in positiion |
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.
Double ii
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/table.go
Outdated
// Remove partitioning | ||
c.TableSpec.PartitionOption = nil | ||
default: | ||
return errors.Wrapf(ErrUnsupportedApplyOperation, "%v", sqlparser.String(spec)) |
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.
Can this be errors.Wrap(ErrUnsupportedApplyOperation, sqlparser.String(spec))
?
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.
done
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>
Tracking issue: #10203 |
Description
In this PR
schemadiff
canApply
a change onto a declarative table, view or schema, via these new public functions:as can be seen in the above, the things we can apply are:
ALTER TABLE
onto aCREATE TABLE
entityALTER VIEW
onto aCREATE VIEW
entitySchema
object. These diffs areCREATE/DROP/ALTER TABLE/SCHEMA
statementsIn each of the above functions:
error
if the operation is invalid (e.g. dropping a column when the column does not exist; adding a column when it already exists; etc)Diff()
So the idea is to be able to run purely-declarative schema changes, including ALTER TABLE statements.
The tests are trivially integrated into pre-existing tests: where we already validate a diff between
object1
andobject2
, now attempt to apply the diff toobject1
and expect the result to be identical toobject2
.Related Issue(s)
This PR extends #10164 as it relies on some of its functionality
Checklist
cc @dbussink