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

distsql: copy prefix key in index skip table reader #39636

Merged
merged 1 commit into from
Aug 14, 2019
Merged

distsql: copy prefix key in index skip table reader #39636

merged 1 commit into from
Aug 14, 2019

Conversation

asubiotto
Copy link
Contributor

@asubiotto asubiotto commented Aug 13, 2019

This is necessary because the table reader goes on to modify the key
returned from PartialKey in place, which would corrupt the current row
to return since the key is unsafe.

This commit also changes test descriptions to the more conventional
TestName/AndSubtestName in the index skip table reader tests and
shortens them to be able to run specific subtests more easily (less
typing).

Release note: None

@cockroach-teamcity
Copy link
Member

This change is Reviewable

@asubiotto
Copy link
Contributor Author

Also deleted some duplicate tests.

@asubiotto asubiotto requested a review from a team August 13, 2019 19:40
Copy link
Contributor

@rohany rohany left a comment

Choose a reason for hiding this comment

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

Thanks for cleaning up the tests alfonso!

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @asubiotto, @ridwanmsharif, and @rohany)


pkg/sql/distsqlrun/index_skip_table_reader.go, line 204 at r1 (raw file):

			// If this is a forward scan, skip to the end of the current prefix's
			// keyspace on the next seek.
			t.spans[t.currentSpan].Key = prefixKey.PrefixEnd()

If we want to not modify the current key we should just make a copy here, rather than using prefixEnd. I'm not sure PrefixEnd guards against null values being in every other position in the index.

Copy link
Contributor Author

@asubiotto asubiotto 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 @ridwanmsharif and @rohany)


pkg/sql/distsqlrun/index_skip_table_reader.go, line 204 at r1 (raw file):

Previously, rohany (Rohan Yadav) wrote…

If we want to not modify the current key we should just make a copy here, rather than using prefixEnd. I'm not sure PrefixEnd guards against null values being in every other position in the index.

Good point, done. We should probably have a test that checks this case. We should also maybe just increment currentSpan if the prefix key is maximal?

Copy link

@ridwanmsharif ridwanmsharif left a comment

Choose a reason for hiding this comment

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

The changes LGTM! Thanks for fixing this! I'll defer to @rohany for the ✅ cause I'm not too familiar with this area

Copy link
Contributor

@rohany rohany left a comment

Choose a reason for hiding this comment

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

LGTM with a nit + question

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


pkg/sql/distsqlrun/index_skip_table_reader.go, line 204 at r1 (raw file):

Previously, asubiotto (Alfonso Subiotto Marqués) wrote…

Good point, done. We should probably have a test that checks this case. We should also maybe just increment currentSpan if the prefix key is maximal?

I thought the interleaved tests should have tested this, or some of the null tests, but I guess not. I think a table with an index of 3 columns, where the last 2 columns only contain nulls should test this behavior. Can you open an issue about that?

Do you mean if the key is all 0xff? We could check that here, but it will get caught in the next case anyway, where we check that the span is valid.


pkg/sql/distsqlrun/index_skip_table_reader.go, line 203 at r2 (raw file):

		if !t.reverse {
			// Modifying key in place would corrupt our current row, so make a copy.
			key = append([]byte(nil), key...)

[nit] would it be clearer to just use copy

Copy link
Contributor

@rohany rohany 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 @asubiotto)


pkg/sql/distsqlrun/index_skip_table_reader.go, line 184 at r2 (raw file):

		}

		key, err := t.fetcher.PartialKey(t.keyPrefixLen)

Should you move the copy up here? In the case where we are doing a reverse scan we are using the key from the fetcher which could be a problem.

This is necessary because the table reader goes on to modify the key
returned from `PartialKey` in place, which would corrupt the current row
to return since the key is unsafe.

This commit also changes test descriptions to the more conventional
TestName/AndSubtestName in the index skip table reader tests and
shortens them to be able to run specific subtests more easily (less
typing).

Release note: None
Copy link
Contributor Author

@asubiotto asubiotto 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 @rohany)


pkg/sql/distsqlrun/index_skip_table_reader.go, line 204 at r1 (raw file):

Previously, rohany (Rohan Yadav) wrote…

I thought the interleaved tests should have tested this, or some of the null tests, but I guess not. I think a table with an index of 3 columns, where the last 2 columns only contain nulls should test this behavior. Can you open an issue about that?

Do you mean if the key is all 0xff? We could check that here, but it will get caught in the next case anyway, where we check that the span is valid.

Yes (maximal key/all 0xff). Aren't there cases where a max key is still valid (e.g. if the EndKey is a longer max key, I'm thinking in terms of a variable prefix length which is what ridwan is working on)? That's what I was worried about, but I guess you're saying there's something else? Why would the rest of the index (after the prefix length) matter? I'll merge it without modifying this logic but we should revisit this. I added a TODO.


pkg/sql/distsqlrun/index_skip_table_reader.go, line 184 at r2 (raw file):

Previously, rohany (Rohan Yadav) wrote…

Should you move the copy up here? In the case where we are doing a reverse scan we are using the key from the fetcher which could be a problem.

The issue is that we're doing in-place modification of an unsafe key in the forward case, so it's only that that would corrupt the row. But I moved the copy up here and added a separate scope to disallow reuse of the key variable.


pkg/sql/distsqlrun/index_skip_table_reader.go, line 203 at r2 (raw file):

Previously, rohany (Rohan Yadav) wrote…

[nit] would it be clearer to just use copy

True, in fact it's also more performant. I added a scratch variable though to avoid allocating on every lookup. I kept it as an append just to be sure we have enough capacity to copy the whole key (since it could have some extra bytes that we don't account for i.e. table/index ID).

Copy link
Contributor

@rohany rohany 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 @asubiotto)


pkg/sql/distsqlrun/index_skip_table_reader.go, line 204 at r1 (raw file):

Previously, asubiotto (Alfonso Subiotto Marqués) wrote…

Yes (maximal key/all 0xff). Aren't there cases where a max key is still valid (e.g. if the EndKey is a longer max key, I'm thinking in terms of a variable prefix length which is what ridwan is working on)? That's what I was worried about, but I guess you're saying there's something else? Why would the rest of the index (after the prefix length) matter? I'll merge it without modifying this logic but we should revisit this. I added a TODO.

I think we guarantee here that maximal keys are invalid here (by doing t.indexLen - t.keyPrefixLen + 1), but I'm not sure. We can talk about this in person when I come back and take a look at the issues -- it is tricky.


pkg/sql/distsqlrun/index_skip_table_reader.go, line 184 at r2 (raw file):

Previously, asubiotto (Alfonso Subiotto Marqués) wrote…

The issue is that we're doing in-place modification of an unsafe key in the forward case, so it's only that that would corrupt the row. But I moved the copy up here and added a separate scope to disallow reuse of the key variable.

that makes sense -- great.

@asubiotto
Copy link
Contributor Author

Looks like a storage flake: #39651

bors r=rohany

craig bot pushed a commit that referenced this pull request Aug 14, 2019
39636: distsql: use PrefixEnd in the index skip table reader r=rohany a=asubiotto

This commit defers the construction of the next key to read to
`PrefixEnd`, which does more or less the same thing as the current
key construction code but also returns a new key for that prefix end.
If we modify `key` in place and the needed output rows is greater than
the prefix length, we overwrite the current row's values (since the key
returned from `PartialKey` is unsafe.

This commit also changes test descriptions to the more conventional
TestName/AndSubtestName in the index skip table reader tests and
shortens them to be able to run specific subtests more easily (less
typing).

Release note: None

Co-authored-by: Alfonso Subiotto Marqués <alfonso@cockroachlabs.com>
@asubiotto asubiotto changed the title distsql: use PrefixEnd in the index skip table reader distsql: copy prefix key in index skip table reader Aug 14, 2019
@craig
Copy link
Contributor

craig bot commented Aug 14, 2019

Build succeeded

@craig craig bot merged commit 3dfb02e into cockroachdb:master Aug 14, 2019
@asubiotto asubiotto deleted the iss-changes branch September 10, 2019 15:01
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