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

backwards compatible deserialization of SqlQueryResponse and fix SQL bwc tests #78467

Merged
merged 5 commits into from
Oct 6, 2021

Conversation

Luegg
Copy link
Contributor

@Luegg Luegg commented Sep 29, 2021

Resolves #78424

With the merge of #78363, it's the first time in a while that the bwc tests run cases where upgraded nodes redirect SQL queries to older nodes. Unfortunately, the upgraded nodes were not able to redirect the response from the old nodes to the client due to a bug in deserialization of SqlQueryResponse.

This PR fixes the deserialization issue. I also had to work around some follow up issues with SqlSearchIT because the new query redirect triggers some new code paths that were not yet correct in all wire compatible versions.

@Luegg Luegg added the test-full-bwc Trigger full BWC version matrix tests label Sep 29, 2021
@Luegg Luegg requested review from astefan, bpintea and costin September 29, 2021 15:38
@Luegg Luegg marked this pull request as ready for review September 29, 2021 15:39
@Luegg
Copy link
Contributor Author

Luegg commented Sep 29, 2021

I've also already created the backport PR #78465 to ensure the 7.x bwc tests turn green as well.

Copy link
Contributor

@bpintea bpintea left a comment

Choose a reason for hiding this comment

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

Lgtm, thanks.

import org.elasticsearch.xpack.ql.async.QlStatusResponse;
import org.elasticsearch.xpack.sql.proto.ColumnInfo;
import org.elasticsearch.xpack.sql.proto.Mode;
import org.elasticsearch.xpack.sql.proto.Protocol;
import org.elasticsearch.xpack.sql.proto.SqlVersion;
import org.elasticsearch.xpack.sql.proto.StringUtils;

import java.io.IOException;
Copy link
Contributor

Choose a reason for hiding this comment

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

have these been reordered automatically by the editor?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes. I think that follows the default imports layout.

}
}

private Map<String, Object> dropDisplaySizes(Map<String, Object> response) {
// if JDBC mode is used, display_size will also be part of the response, remove it because it's not part of the expected response
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// if JDBC mode is used, display_size will also be part of the response, remove it because it's not part of the expected response
// in JDBC mode, display_size will be part of the response, so remove it because it's not part of the expected response

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 thx

Comment on lines 264 to 265
Map<String, Object> actualResponse = dropDisplaySizes(runSql(client, request));
assertResponse(expectedResponse, actualResponse);
Copy link
Contributor

Choose a reason for hiding this comment

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

optional nit: actualResponse could be inlined.

Copy link
Contributor

@astefan astefan left a comment

Choose a reason for hiding this comment

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

Left some comments.

Comment on lines 259 to 260
String intervalYearMonth = "INTERVAL '150' YEAR AS interval_year, ";
String intervalDayTime = "INTERVAL '163' MINUTE AS interval_minute, ";
Copy link
Contributor

Choose a reason for hiding this comment

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

I find this style to be more "visible" and easier to read. Can you, please, keep the original version?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure, I inlined it because I thought it was a leftover from using a conditional here in earlier revisions.

Comment on lines +85 to +94
if (in.getVersion().onOrAfter(Version.V_7_14_0)) {
columnar = in.readBoolean();
asyncExecutionId = in.readOptionalString();
isPartial = in.readBoolean();
isRunning = in.readBoolean();
} else {
asyncExecutionId = null;
isPartial = false;
isRunning = false;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Why this change and why is columnar included there (it seems you grouped together the async specific settings)?

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

The fact that we discovered this in a BWC test and not when the async search was introduced is troubling. At some point in future we will need a set of tests that should cover the serialization differences between bwc versions for both the request and response objects. I did something similar for EQL here: #68339. @Luegg please open an issue for improving the tests coverage in this area.

Copy link
Contributor

Choose a reason for hiding this comment

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

My initial question still stands.
To clarify a bit: columnar has been added in 7.2.0 (#39287). If we should handle it differently depending on the version it shouldn't be 7.14, since that's not the version that added it. Or I am missing something.

Copy link
Contributor

Choose a reason for hiding this comment

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

it shouldn't be 7.14, since that's not the version that added it.

True, but that's the version that added it to the serialisation.
If not mistaking, between (and before) 7.2 and 7.14, a serialised SqlQueryResponse didn't contain the columnar field. So trying to deserialise a SqlQueryResponse and read the columnar field would eventually fail.
A 7.14+ serialised SqlQueryResponse will otoh contain it and needs to be read.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks @bpintea, I was getting confused myself.

@Luegg Luegg requested a review from astefan October 4, 2021 08:30
Copy link
Contributor

@astefan astefan left a comment

Choose a reason for hiding this comment

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

Looks good in general but the original question I had about columnar still stands.

Comment on lines +85 to +94
if (in.getVersion().onOrAfter(Version.V_7_14_0)) {
columnar = in.readBoolean();
asyncExecutionId = in.readOptionalString();
isPartial = in.readBoolean();
isRunning = in.readBoolean();
} else {
asyncExecutionId = null;
isPartial = false;
isRunning = false;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

My initial question still stands.
To clarify a bit: columnar has been added in 7.2.0 (#39287). If we should handle it differently depending on the version it shouldn't be 7.14, since that's not the version that added it. Or I am missing something.

Copy link
Member

@costin costin left a comment

Choose a reason for hiding this comment

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

LGTM

@@ -22,7 +22,7 @@ testClusters.configureEach {
tasks.named("integTest").configure{ enabled = false}

// A bug (https://github.com/elastic/elasticsearch/issues/68439) limits us to perform tests with versions from 7.10.3 onwards
for (Version bwcVersion : BuildParams.bwcVersions.wireCompatible.findAll { it.onOrAfter('7.10.0') }) {
for (Version bwcVersion : BuildParams.bwcVersions.wireCompatible.findAll { it.onOrAfter('7.10.3') }) {
Copy link
Member

Choose a reason for hiding this comment

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

small nit but a comment would help on what changed in 7.10.3 vs 7.10.0 to make this version being considered.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Using 7.10.0 was a bug. As the comment on line 24 says the version should always have been 7.10.3. But accidentally, the tests also worked with 7.10.0 until I introduced missing_order.

@Luegg Luegg added the auto-merge-without-approval Automatically merge pull request when CI checks pass (NB doesn't wait for reviews!) label Oct 6, 2021
@elasticsearchmachine elasticsearchmachine merged commit 8af3bc1 into elastic:master Oct 6, 2021
@Luegg Luegg deleted the fix/sqlBwcMaster branch October 6, 2021 14:25
@danhermann danhermann added the >test Issues or PRs that are addressing/adding tests label Dec 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
:Analytics/SQL SQL querying auto-merge-without-approval Automatically merge pull request when CI checks pass (NB doesn't wait for reviews!) >test Issues or PRs that are addressing/adding tests test-full-bwc Trigger full BWC version matrix tests v7.16.0 v8.0.0-beta1
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[CI] SqlSearchIT testAllTypesWithRequestToUpgradedNodes failing
7 participants