Skip to content
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: support ALTER COLUMN SET NOT NULL #37554

Merged
merged 1 commit into from Jun 19, 2019
Merged

Conversation

thoszhang
Copy link
Contributor

@thoszhang thoszhang commented May 16, 2019

This PR adds support for ALTER TABLE ... ALTER COLUMN ... SET NOT NULL, to
add a non-null constraint to an existing column. This is done by creating a
dummy CHECK constraint in the Validating state which moves through the states
of the schema changer, and setting Nullable to true on the column descriptor
only at the very end. Adding a constraint to an existing column requires the
constraint to be in a "write-only" state while validation occurs, and the
advantage of the approach in this PR is that we can reuse the existing CHECK
constraint states, where "write-only" corresponds to the state where the
constraint is on the table descriptor in the Validating state.

(As with FK and check constraints, we still need to process dropped constraints
in the schema changer. That's been left for a separate PR.)

Closes #28751.

Release note (sql change): Add support for ALTER TABLE ... ALTER COLUMN ... SET NOT NULL, which adds a non-null constraint to an existing column.

@thoszhang thoszhang added the do-not-merge bors won't merge a PR with this label. label May 16, 2019
@thoszhang thoszhang requested review from dt and a team May 16, 2019 17:42
@cockroach-teamcity
Copy link
Member

This change is Reviewable

Copy link
Member

@dt dt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 13 of 15 files at r1.
Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @dt and @lucy-zhang)


pkg/sql/sqlbase/structured.go, line 2459 at r1 (raw file):

func (desc *MutableTableDescriptor) AddNotNullValidationMutation(name string, c ColumnID) {
	// TODO (lucy): generate this constraint properly, as in MakeCheckConstraint
	ck := TableDescriptor_CheckConstraint{

I think we should add a real, structured field to CheckConstraint that indicates that this is really a NOT NULL instead of just the name match, even if we don't use it for now.

We could then later decide to e.g. hide them from check constraints, or find them by column id (assuming that the field was, say, the col id for which it was added), etc.


pkg/sql/sqlbase/structured.go, line 2530 at r1 (raw file):

// with a schema mutation that is still not yet public: Data validation,
// error reporting.
func (desc *ImmutableTableDescriptor) MakeFirstMutationPublic(includeConstraints bool) (*MutableTableDescriptor, error) {

Style nits w.r.t. bool args:

The style guide, for better or for worse, says all the callsites should include a comment with the arg name, e.g. doFoo(true /* includeConstraints */) OR pass a named constants instead of literal. I usually do the later, exporting the named const along side the function that takes it, e.g.const IgnoreConstraints, IncludeConstraints = false, true and then use those expressive names at the callsites instead of the literal + inline comment clutter.

In either case, I'd include in this function comment what this arg actually means / does, e.g. A reader might wonder what the behavior is if the first mutation is a constraint but the flag is false? or if it is true, but the first is an index?

Alternatively, the style guide also suggests avoiding bool args if it makes sense to instead just offer separate named functions that do behavior A vs B (that maybe then just hide an internal, bool-arg'ed helper).

Copy link
Contributor Author

@thoszhang thoszhang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @dt and @lucy-zhang)


pkg/sql/sqlbase/structured.go, line 2459 at r1 (raw file):

Previously, dt (David Taylor) wrote…

I think we should add a real, structured field to CheckConstraint that indicates that this is really a NOT NULL instead of just the name match, even if we don't use it for now.

We could then later decide to e.g. hide them from check constraints, or find them by column id (assuming that the field was, say, the col id for which it was added), etc.

Relatedly: Currently, this PR removes the dummy check constraint from the table descriptor when the schema change is complete, so that only the non-nullable flag remains. One problem with keeping a special marked check constraint on the descriptor even after the schema change is that there won't be a corresponding check constraint for non-null constraints that existed prior to this change being rolled out. We either have to do a migration for existing not null constraints somehow (which seems undesirable), or deal with the special marked check constraints being possibly not present, which adds confusion. (There's also the fact that the presence of the check constraint means an extra check during writes, which isn't ideal.)

I do think it's a good idea to add a field to CheckConstraint anyway to indicate this, but I think we are going to have to delete the dummy check constraint after adding the non-null constraint, and re-synthesize a new one for the schema changer if/when the not null constraint is dropped.

@thoszhang thoszhang changed the title sql: [wip] support ALTER COLUMN SET NOT NULL sql: support ALTER COLUMN SET NOT NULL Jun 18, 2019
@thoszhang thoszhang removed the do-not-merge bors won't merge a PR with this label. label Jun 18, 2019
Copy link
Contributor Author

@thoszhang thoszhang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is ready for another look.

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @dt)


pkg/sql/sqlbase/structured.go, line 2530 at r1 (raw file):

Previously, dt (David Taylor) wrote…

Style nits w.r.t. bool args:

The style guide, for better or for worse, says all the callsites should include a comment with the arg name, e.g. doFoo(true /* includeConstraints */) OR pass a named constants instead of literal. I usually do the later, exporting the named const along side the function that takes it, e.g.const IgnoreConstraints, IncludeConstraints = false, true and then use those expressive names at the callsites instead of the literal + inline comment clutter.

In either case, I'd include in this function comment what this arg actually means / does, e.g. A reader might wonder what the behavior is if the first mutation is a constraint but the flag is false? or if it is true, but the first is an index?

Alternatively, the style guide also suggests avoiding bool args if it makes sense to instead just offer separate named functions that do behavior A vs B (that maybe then just hide an internal, bool-arg'ed helper).

Done. I ended up defining new constants.

@thoszhang thoszhang force-pushed the not-null branch 2 times, most recently from 2c28012 to 94a1002 Compare June 18, 2019 20:45
@thoszhang thoszhang requested a review from a team June 18, 2019 20:45
@thoszhang thoszhang force-pushed the not-null branch 2 times, most recently from 47092c2 to 3a4596f Compare June 19, 2019 17:47
This PR adds support for `ALTER TABLE ... ALTER COLUMN ... SET NOT NULL`, to
add a non-null constraint to an existing column. This is done by creating a
dummy CHECK constraint in the `Validating` state which moves through the states
of the schema changer, and setting `Nullable` to true on the column descriptor
only at the very end. Adding a constraint to an existing column requires the
constraint to be in a "write-only" state while validation occurs, and the
advantage of the approach in this PR is that we can reuse the existing CHECK
constraint states, where "write-only" corresponds to the state where the
constraint is on the table descriptor in the `Validating` state.

(As with FK and check constraints, we still need to process dropped constraints
in the schema changer. That's been left for a separate PR.)

Release note (sql change): Add support for `ALTER TABLE ... ALTER COLUMN ...
SET NOT NULL`, which adds a non-null constraint to an existing column.
@thoszhang
Copy link
Contributor Author

TFTR

bors r+

craig bot pushed a commit that referenced this pull request Jun 19, 2019
37554: sql: support ALTER COLUMN SET NOT NULL r=lucy-zhang a=lucy-zhang

This PR adds support for `ALTER TABLE ... ALTER COLUMN ... SET NOT NULL`, to
add a non-null constraint to an existing column. This is done by creating a
dummy CHECK constraint in the `Validating` state which moves through the states
of the schema changer, and setting `Nullable` to true on the column descriptor
only at the very end. Adding a constraint to an existing column requires the
constraint to be in a "write-only" state while validation occurs, and the
advantage of the approach in this PR is that we can reuse the existing CHECK
constraint states, where "write-only" corresponds to the state where the
constraint is on the table descriptor in the `Validating` state.

(As with FK and check constraints, we still need to process dropped constraints
in the schema changer. That's been left for a separate PR.)

Closes #28751.

Release note (sql change): Add support for `ALTER TABLE ... ALTER COLUMN ...
SET NOT NULL`, which adds a non-null constraint to an existing column.

Co-authored-by: Lucy Zhang <lucy-zhang@users.noreply.github.com>
@craig
Copy link
Contributor

craig bot commented Jun 19, 2019

Build succeeded

@craig craig bot merged commit 8fe4986 into cockroachdb:master Jun 19, 2019
@thoszhang thoszhang deleted the not-null branch June 19, 2019 22:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

sql: support ALTER TABLE ALTER COLUMN SET NOT NULL
4 participants