-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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
sql/schemachanger: support for create sequence inside the declarative schema changer #104350
Conversation
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 took an early look at the last 3 commits and left some preliminary comments. Nicely done. Can you add support for ADD COLUMN SERIAL and friends, if that's straightforward? I can't remember too well, but it might be. Don't bother if it's out of scope, but it'd be a nice test case.
We have a tracking issue for the remaining ADD COLUMN work, but I'll definitely circle back as a follow on PR |
838ce29
to
fad8be8
Compare
fad8be8
to
aea6cc0
Compare
aea6cc0
to
64eb7f3
Compare
64eb7f3
to
66d8186
Compare
@postamar This is ready for another look, its rebased and now uses TableData elements for decision making so more future proof. |
seenDescriptors := screl.AllTargetDescIDs(ts) | ||
// Elements without metadata can only be retained, if some other descriptor | ||
// is referencing them. We may have multiple index data and table data's, | ||
// but not all of them are relevant if the primary descriptor ID never shows. | ||
for _, ex := range extraTargets { | ||
if seenDescriptors.Contains(screl.GetDescID(ex.t.Element())) { | ||
ts.Targets = append(ts.Targets, ex.t) | ||
initial = append(initial, ex.e.initial) | ||
current = append(current, ex.e.current) |
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 didn't understand this part: So in the loop-above, we iterate all elements and populate extraTargets
, which are all the elements that have empty metadata but should be retained. Here, we are looping over those extra targets and append them into the TargetState if they are contained in seenDescriptors
. Why would any of them be contained in seenDescriptors
?
I guess in general those comments are a bit too high level to me still.
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.
// We are going to retain certain elements for metadata purposes, like
// TableData/IndexData elements, which will allow the declarative schema
// changer to know if a given table is empty. Once these elements exist
// the two-version invariant is applied when making mutations to elements.
// Only emit data elements for descriptors if they are references with
// some transition.
for _, e := range bs.output { | ||
if e.metadata.Size() == 0 { | ||
if e.metadata.Size() == 0 && !shouldElementBeRetainedWithoutMetadata(e.element) { |
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 help me understand the overall purpose of including those TableData
element and IndexData
element in the TargetState even if they are not added/dropped in the builder. In other words, how exactly do they help "hinting" if a backfill is needed
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 allow us to know if a table is empty, which allows us to skip backfill steps completely. The other alternative is to use the DESCRIPTOR_ADDED state, but that breaks if we enter a more transactional world. Since you should be able to insert on those
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.
Updated the comments here:
// Exceptions are TableData/IndexData elements which allow our planning
// execution to skip certain transitions and fences like the two version
// invariant. We will only keep these for descriptors going through
// a transition.
247eba1
to
32a2927
Compare
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.
Nicely done! I only have minor complaints.
data.TableID = rewrite.ID | ||
data.DatabaseID = rewrite.ParentID | ||
continue | ||
} |
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.
This rewrite makes sense but should this be in the switch case below? Not a rethorical question. Or is this case somehow different? If so I can't see it and this deserves commentary perhaps.
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.
@postaar It's because the parentID is not contained within the map that we are using, so it ends up special cased. Let me add the comment:
// Since the parent database ID is never written in the descriptorRewrites
// map we need to special case certain elements that need their ParentID
// re-written.
│ │ ├── ABSENT → PUBLIC SequenceOption:{DescID: 104 (sq1+), Name: "MAXVALUE"} | ||
│ │ ├── ABSENT → PUBLIC SequenceOption:{DescID: 104 (sq1+), Name: "START"} | ||
│ │ ├── ABSENT → PUBLIC SequenceOption:{DescID: 104 (sq1+), Name: "VIRTUAL"} | ||
│ │ ├── ABSENT → PUBLIC SequenceOption:{DescID: 104 (sq1+), Name: "CACHE"} |
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.
This is out of scope for this PR but come to think of it, we'll also have to bind the value to a new Value
attr in screl at some point, to handle ALTER SEQUENCE
DDLs.
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.
Agree that will need to be revisited
be18379
to
d194d3f
Compare
3c06e15
to
248f090
Compare
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.
Reviewable status: complete! 0 of 0 LGTMs obtained (waiting on @msirek, @postamar, and @Xiang-Gu)
pkg/sql/catalog/dbdesc/database_desc_builder.go
line 165 at r9 (raw file):
Previously, postamar (Marius Posta) wrote…
Shouldn't the second arg be 0?
Good catch
pkg/sql/schemachanger/scbuild/build.go
line 112 at r8 (raw file):
Previously, postamar (Marius Posta) wrote…
Call
TargetIsLinkedToSchemaChange
instead?
Done.
pkg/sql/schemachanger/scbuild/build.go
line 486 at r14 (raw file):
Previously, postamar (Marius Posta) wrote…
I wonder if perhaps we'd be better served by adding a boolean override flag in the metadata protobuf instead, that would be set by
scdecomp
for TableData/IndexData elements. I'm not sure if it's actually better, perhaps not. Your approach is fine in the meantime, perhaps I'll explore this after this merges.
I think that is pretty reasonable and would generalize this a lot better.
pkg/sql/schemachanger/scdecomp/decomp.go
line 245 at r13 (raw file):
Previously, postamar (Marius Posta) wrote…
s/keyStr/valueStr/
Done.
pkg/sql/schemachanger/scdecomp/decomp.go
line 248 at r13 (raw file):
Previously, postamar (Marius Posta) wrote…
You need to also return when the value is 0 (or whatever the default is) for integer values. Perhaps pass an extra
defaultValue
argument toaddSequenceOption
and compare the value to that?
Done.
pkg/sql/schemachanger/scexec/dependencies.go
line 105 at r13 (raw file):
Previously, postamar (Marius Posta) wrote…
This is fine, though FYI I wouldn't have minded simply adding the
InitializeSequence
method toscexec.Catalog
, because I'm not sure how much this interface will grow in the future.
Done.
pkg/sql/schemachanger/scpb/state.go
line 99 at r8 (raw file):
Previously, postamar (Marius Posta) wrote…
Call
TargetIsLinkedToSchemaChange
instead?
Done.
pkg/sql/schemachanger/scpb/state.go
line 150 at r8 (raw file):
Previously, postamar (Marius Posta) wrote…
I like this.
Done.
pkg/sql/schemachanger/scplan/internal/opgen/opgen_column_not_null.go
line 34 at r10 (raw file):
Previously, postamar (Marius Posta) wrote…
What about other constraints? Shouldn't they also have this check?
Yes, they, need the same check let me update them as well.
Done.
pkg/sql/schemachanger/scplan/internal/opgen/opgen_sequence.go
line 42 at r13 (raw file):
Previously, postamar (Marius Posta) wrote…
Instead of having a pointer to an int, can we have an extra
UseRestartWith
boolean field instead? I'm not sure how well an *int64 serializes in YAML (which is how we render EXPLAIN diagrams) and this isn't tested. For consistency, you might want to do the same in the element model.
Good point, that's much cleaner. The element model can have a similar change too.
pkg/sql/schemachanger/scplan/internal/opgen/opgen_sequence_option.go
line 1 at r13 (raw file):
Previously, postamar (Marius Posta) wrote…
We're in 2023.
Done.
pkg/sql/schemachanger/scplan/internal/scstage/build.go
line 345 at r10 (raw file):
Previously, postamar (Marius Posta) wrote…
This change makes sense but I'm a bit concerned about the added computational complexity that this loop adds. Can we pre-compute the
anyRemainingOpsCanFail
property for each node instead? DefineanyRemainingOpsCanFail := make(map[*screl.Node]bool)
, then for each target, start with the sink node and do a depth-first traversal going backwards along each op edge, if you've verifiedoe.CanFail()
at least once in the path to the sink node then setanyRemainingOpsCanFail[oe.From()] = true
and vice-versa.
Done.
pkg/sql/schemachanger/scrun/scrun.go
line 277 at r8 (raw file):
Previously, postamar (Marius Posta) wrote…
Call
TargetIsLinkedToSchemaChange
instead?
Done.
pkg/sql/logictest/testdata/logic_test/crdb_internal
line 866 at r13 (raw file):
Previously, postamar (Marius Posta) wrote…
Remind me, what triggered this change?
This is triggered by MaybeSplit.* from the primary index. I guess the question is if we want this temporary admin split or not since for a sequence it's only a single row.
pkg/sql/schemachanger/scbuild/testdata/unimplemented_create
line 0 at r13 (raw file):
Previously, postamar (Marius Posta) wrote…
(Reviewable was unable to map this GitHub inline comment thread to the right spot — sorry!)
Hooray :)
Done.
8fe8cf4
to
abe3515
Compare
To support the ability of skipping operations when data exists, we will add support for including data targets within plans even if they have no transitions. These elements then can be used by rules to decide if backfill or the two version invariant are required. This patch, will add logic to do this detection. Epic: none Release note: None
Previously, if an existing job was missing the TableData element, the new job would not properly handle the current set of rules in the mixed version state. This patch adds, a migration to inject those elements. Epic: none Release note: None
39bfbae
to
44153a6
Compare
@postamar ready for another look |
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 missing at least one end-to-end test case involving CREATE SEQUENCE
.
addSequenceOption(tree.SeqOptStart, tempSequenceOpts.Start) | ||
addSequenceOption(tree.SeqOptVirtual, tempSequenceOpts.Virtual) | ||
addSequenceOption(tree.SeqOptCache, tempSequenceOpts.CacheSize) | ||
addSequenceOption(tree.SeqOptAs, tempSequenceOpts.AsIntegerType) |
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.
Shouldn't you be reusing the same logic as in scdecomp here for the sequence options?
if value == nil { | ||
return | ||
} | ||
keyStr := fmt.Sprintf("%v", value) |
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.
This hasn't been fixed.
} | ||
|
||
} | ||
} |
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 move this logic into a top-level function which you'll call in the struct initialization above: bc := buildContext{ ... }
.
│ SequenceID: 104 | ||
│ | ||
└── • MarkDescriptorAsPublic | ||
DescriptorID: 104 |
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.
This file shouldn't exist.
├── SetIndexName {"IndexID":1,"Name":"primary","TableID":104} | ||
├── MakeValidatedPrimaryIndexPublic {"IndexID":1,"TableID":104} | ||
├── InitSequence {"SequenceID":104} | ||
└── MarkDescriptorAsPublic {"DescriptorID":104} |
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.
This file shouldn't exist.
EXPLAIN (ddl, shape) CREATE SEQUENCE sq1 MINVALUE 1 MAXVALUE 9223372036854775807 INCREMENT 1 START 32; | ||
---- | ||
Schema change plan for CREATE SEQUENCE ‹defaultdb›.‹public›.‹sq1› MINVALUE 1 MAXVALUE 9223372036854775807 INCREMENT 1 START 32; | ||
└── execute 1 system table mutations transaction |
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.
This file shouldn't exist.
Ah, the directory structure changed for this stuff, let me move it over and regenerate it. |
75611df
to
fb0f4c9
Compare
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.
At this point if the CI's happy I'm happy. I've looked at enough iterations of this PR that I'm starting to lose track of things. I don't want to block this, though, and I'm feeling pretty good about this change.. Feel free to have this looked at by a fresh pair of eyes, depending on how confident you are about this change. It's up to you.
persist all catalog changes to storage | ||
adding table for stats refresh: 104 | ||
# end PreCommitPhase | ||
commit transaction #1 |
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 don't actually need an expected output in the .definition file. Please remove.
Thanks for the patience in reviewing this, and I appreciate the feedback it made the entire thing much better. I'm gonna make sure CI is clear then merge it with the remaining fixes. |
fb0f4c9
to
827a139
Compare
Previously, we would always generate operations to backfill and validate on newly created tables (with data elements). This will prevent us from being able to generate single stage plans for creating relations. This patch removes those checks for added tables, and allows data elements to be emitted as targets. Epic: none Release note: None
Previously, the two version invariant was enforced for all non-dropped descriptors. When creating new descriptors if they are going to be decomposed into individual elements, then similar logic needs to skip added descriptors. To address this, this patch disables these rules for added descriptors. Epic: none Release note: None
Previously, when trying to resolve prefixes for newly created objects, we didn't handle two parts names properly in the declarative schema changer. This, patch fixes this logic to match the resolver. Epic: none Release note: None
Previously, the CREATE SEQUENCE command only worked in the legacy schema changer. This patch, adds support for creating sequences in declarative schema changer. Epic: None Release note: None
Previously, our CREATE SEQUENCE support for the declarative schema changer fell back if an OWNED BY clause is specified. To address this patch adds support for owned by clause. Epic: none Release note: None
827a139
to
74edfa9
Compare
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.
Reviewable status: complete! 0 of 0 LGTMs obtained (waiting on @msirek, @postamar, and @Xiang-Gu)
a discussion (no related file):
Previously, postamar (Marius Posta) wrote…
(Reviewable was unable to map this GitHub inline comment thread to the right spot — sorry!)
You don't actually need an expected output in the .definition file. Please remove.
Done.
pkg/sql/schemachanger/scbuild/internal/scbuildstmt/create_sequence.go
line 110 at r14 (raw file):
Previously, postamar (Marius Posta) wrote…
This seems like it should be in the previous commit.
Done.
pkg/sql/schemachanger/scbuild/internal/scbuildstmt/create_sequence.go
line 135 at r35 (raw file):
Previously, postamar (Marius Posta) wrote…
Shouldn't you be reusing the same logic as in scdecomp here for the sequence options?
Done.
pkg/sql/schemachanger/scdecomp/decomp.go
line 245 at r13 (raw file):
Previously, postamar (Marius Posta) wrote…
This hasn't been fixed.
Ugh, I fixed the comment but forgot to fix the variable name.
pkg/sql/schemachanger/scplan/internal/scstage/build.go
line 100 at r35 (raw file):
Previously, postamar (Marius Posta) wrote…
Please move this logic into a top-level function which you'll call in the struct initialization above:
bc := buildContext{ ... }
.
Done.
pkg/sql/schemachanger/testdata/end_to_end/create_schema_drop_schema_separate_statements/create_sequence
line 7 at r35 (raw file):
Previously, postamar (Marius Posta) wrote…
This file shouldn't exist.
Done.
pkg/sql/schemachanger/testdata/end_to_end/drop_column_create_index_separate_statements/create_sequence
line 130 at r35 (raw file):
Previously, postamar (Marius Posta) wrote…
This file shouldn't exist.
Done.
pkg/sql/schemachanger/testdata/explain_verbose/create_sequence
line 778 at r35 (raw file):
Previously, postamar (Marius Posta) wrote…
This file shouldn't exist.
Done.
bors r+ |
Build succeeded: |
This patch implements CREATE SEQUENCE in the declarative schema changer. The first three commits can be ignored and are included in (#104348, which should be reviewed and merged first). This patch will:
Fixes: #104351