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

opt: support UPDATE with partial UNIQUE WITHOUT INDEX constraints #60836

Merged
merged 1 commit into from
Feb 23, 2021

Conversation

mgartner
Copy link
Collaborator

This commit add uniqueness checks for partial UNIQUE WITHOUT INDEX
constraints during UPDATE statements.

As partial of this change, I discovered that #60535 introduced a
regression where columns not required by uniqueness checks are not
pruned. I've left TODOs in the column pruning tests and plan on fixing
this in a follow-up PR.

There is no release note because these constraints are gated behind the
experimental_enable_unique_without_index_constraints session variable.

Release note: None

@mgartner mgartner requested a review from a team as a code owner February 20, 2021 18:44
@cockroach-teamcity
Copy link
Member

This change is Reviewable

Copy link
Collaborator

@rytaft rytaft left a comment

Choose a reason for hiding this comment

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

:lgtm:

Reviewed 6 of 6 files at r1.
Reviewable status: :shipit: complete! 1 of 0 LGTMs obtained (waiting on @mgartner and @RaduBerinde)


pkg/sql/logictest/testdata/logic_test/unique, line 455 at r1 (raw file):

# Set a to a non-existing value.
statement ok
UPDATE uniq_partial SET a = 10 WHERE a = 9 AND b = 9

would be good to add one additional test that would fail if we had a full constraint, but succeeds with a partial constraint. For example, SET a = 1 WHERE b = -7


pkg/sql/opt/optbuilder/mutation_builder_unique.go, line 124 at r1 (raw file):

	if _, isPartial := uc.Predicate(); isPartial {
		pred := mb.parseUniqueConstraintPredicateExpr(uniqueOrdinal)
		typedPred := mb.fetchScope.resolveAndRequireType(pred, types.Bool)

Are we now building this predicate multiple times? Is it worth caching it in the metadata like we do for indexes?

(Doesn't need to hold up this PR, but maybe open an issue if you think it's worth addressing at some point)

This commit add uniqueness checks for partial `UNIQUE WITHOUT INDEX`
constraints during `UPDATE` statements.

As partial of this change, I discovered that cockroachdb#60535 introduced a
regression where columns not required by uniqueness checks are not
pruned. I've left TODOs in the column pruning tests and plan on fixing
this in a follow-up PR.

There is no release note because these constraints are gated behind the
experimental_enable_unique_without_index_constraints session variable.

Release note: None
@mgartner mgartner force-pushed the partial-unique-update branch from b5cc909 to e5d499a Compare February 22, 2021 19:53
Copy link
Collaborator Author

@mgartner mgartner 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 (and 1 stale) (waiting on @RaduBerinde and @rytaft)


pkg/sql/logictest/testdata/logic_test/unique, line 455 at r1 (raw file):

Previously, rytaft (Rebecca Taft) wrote…

would be good to add one additional test that would fail if we had a full constraint, but succeeds with a partial constraint. For example, SET a = 1 WHERE b = -7

Done.


pkg/sql/opt/optbuilder/mutation_builder_unique.go, line 124 at r1 (raw file):

Previously, rytaft (Rebecca Taft) wrote…

Are we now building this predicate multiple times? Is it worth caching it in the metadata like we do for indexes?

(Doesn't need to hold up this PR, but maybe open an issue if you think it's worth addressing at some point)

Yes, there's a number of places where we build these expressions, like determining arbiters and uniqueness checks, and it's tricky to determine exactly how many times we are building the expression and what the minimum number could be. When add the expression to a relation expression in the memo, the scoping is critical. When we use the expression like we do here, to determine which column ordinals are referenced, the exact scoping isn't important, we just need some valid table scope to build the expression with.

In this case I actually tried to to use the predicate expression that is built with the WithScan scope or Scan scope of the uniqueness check, but it seemed to require a lot of refactoring given that this check happens before the uniqueness check is built.

I've created #60943 to track.

Copy link
Member

@RaduBerinde RaduBerinde left a comment

Choose a reason for hiding this comment

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

:lgtm:

Reviewable status: :shipit: complete! 1 of 0 LGTMs obtained (and 1 stale) (waiting on @rytaft)


pkg/sql/opt/optbuilder/mutation_builder_unique.go, line 124 at r1 (raw file):

Previously, mgartner (Marcus Gartner) wrote…

Yes, there's a number of places where we build these expressions, like determining arbiters and uniqueness checks, and it's tricky to determine exactly how many times we are building the expression and what the minimum number could be. When add the expression to a relation expression in the memo, the scoping is critical. When we use the expression like we do here, to determine which column ordinals are referenced, the exact scoping isn't important, we just need some valid table scope to build the expression with.

In this case I actually tried to to use the predicate expression that is built with the WithScan scope or Scan scope of the uniqueness check, but it seemed to require a lot of refactoring given that this check happens before the uniqueness check is built.

I've created #60943 to track.

Why can't we use TableMeta.PartialIndexPredicate()?

@mgartner
Copy link
Collaborator Author


pkg/sql/opt/optbuilder/mutation_builder_unique.go, line 124 at r1 (raw file):

Previously, RaduBerinde wrote…

Why can't we use TableMeta.PartialIndexPredicate()?

In which case? In these particular lines, we can't use it because partial unique constraint predicates do not exist in TableMeta.PartialIndexPredicate().

@mgartner
Copy link
Collaborator Author

TFTRs!

bors r+

Copy link
Member

@RaduBerinde RaduBerinde 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! 1 of 0 LGTMs obtained (and 1 stale) (waiting on @rytaft)


pkg/sql/opt/optbuilder/mutation_builder_unique.go, line 124 at r1 (raw file):

Previously, mgartner (Marcus Gartner) wrote…

In which case? In these particular lines, we can't use it because partial unique constraint predicates do not exist in TableMeta.PartialIndexPredicate().

I see.. maybe we should add those to the meta as well? At a high level, I don't see why they would be treated differently

@mgartner
Copy link
Collaborator Author


pkg/sql/opt/optbuilder/mutation_builder_unique.go, line 124 at r1 (raw file):

Previously, RaduBerinde wrote…

I see.. maybe we should add those to the meta as well? At a high level, I don't see why they would be treated differently

That's definitely an option. The primary reason for adding partial index predicates to table metadata was so that the predicates could be accessed during exploration rules. No explorations rules need access to partial unique constraint predicates, so I never added them to the table metadata. These predicates are only needed in optbuilder.

Also, by adding them to the table metadata, we may be able to use them in 1 or 2 places in optbuilder, but not in all places. When they are added as filters for uniqueness checks or for arbiter-related expressions, we must build them with a scope specific to the relational expression they are added to.

So, adding them to table meta might simplify a few things, but it won't eliminate all the places where these expressions are built. I'll look more into it.

@craig
Copy link
Contributor

craig bot commented Feb 23, 2021

This PR was included in a batch that was canceled, it will be automatically retried

@craig
Copy link
Contributor

craig bot commented Feb 23, 2021

Build succeeded:

@craig craig bot merged commit a660767 into cockroachdb:master Feb 23, 2021
@mgartner mgartner deleted the partial-unique-update branch February 23, 2021 21:41
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.

4 participants