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

ESQL: Introduce language versioning to REST API #106824

Merged
merged 30 commits into from
Apr 3, 2024

Conversation

alex-spies
Copy link
Contributor

@alex-spies alex-spies commented Mar 27, 2024

First part of #104890

For the _query endpoint, add a parameter for the language version to the JSON payload. This will become a required parameter in a follow-up PR; in this PR, this parameter is only validated with no further action.

Copy link
Member

@not-napoleon not-napoleon 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 tackling this! I think this is a great first draft. I've left a bunch of comments, but I think this is the right direction.

NIGHTLY(Integer.MAX_VALUE, Integer.MAX_VALUE, "\uD83D\uDE34"),
PARTY_POPPER(2024, 4, "\uD83C\uDF89");

EsqlVersion(int year, int month, String emoji) {
Copy link
Member

Choose a reason for hiding this comment

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

If we think we might need to serialize this, we should explicitly pass in an ordinal value for serialization (that way it's proof against re-ordering the constants or deleting one). I don't know that we'll have to serialize these, but in case you aren't familiar with that pattern, I wanted to call it out.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Discussed with Mark: will add a disambiguation counter for good measure, so versions will be 2024.04.01.🎉 and if we end up really having to release two language versions in a month, there may be a 2024.04.02.💥.

"[" + RequestXContent.ESQL_VERSION_FIELD + "] has invalid value [" + esqlVersion + "]",
validationException
);
} else if (version == EsqlVersion.NIGHTLY && Build.current().isSnapshot() == false) {
Copy link
Member

Choose a reason for hiding this comment

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

Thinking out loud - does the snapshot check belong here, or in the EsqlVersion.parse method? I can see arguments for both.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hm, personally I do think it belongs here - EsqlVersion shouldn't need to worry about where we permit certain versions to be used IMHO, and why; also, this allows to keep EsqlVersion.parse simple: either the string is a valid version or it's not - otherwise we'd have to throw an exception containing the reason why parsing failed and catch it in EsqlQueryRequest.validate(). We might also parse versions coming from elsewhere in the future, and wouldn't want to prevent parsing of "nightly" just because we're not on a snapshot version.

@@ -46,10 +46,12 @@ final class RequestXContent {
PARAM_PARSER.declareString(constructorArg(), TYPE);
}

private static final ParseField QUERY_FIELD = new ParseField("query");
// TODO: Maybe esql_version would be better? This looks like there's a JSON attribute `esql` with subattribute `version`.
Copy link
Member

Choose a reason for hiding this comment

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

yeah, we should probably think about that a bit. Worth discussing with Kibana as well. For future proofing, I wonder if we want to set up a whole esql object, something like

"esql": {
    "version": "2024.04.🎉 ",
    "whatever_future_setting": "goes_here"
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Discussed with the team: probably just {"query": "...", "version": "2024.04.01.🎉"} is fine.

@elasticsearchmachine
Copy link
Collaborator

Hi @alex-spies, I've created a changelog YAML for you.

@alex-spies alex-spies marked this pull request as ready for review March 28, 2024 16:20
@elasticsearchmachine elasticsearchmachine added the Team:Analytics Meta label for analytical engine team (ESQL/Aggs/Geo) label Mar 28, 2024
@elasticsearchmachine
Copy link
Collaborator

Pinging @elastic/es-analytical-engine (Team:Analytics)

import java.util.LinkedHashMap;
import java.util.Map;

public enum EsqlVersion implements VersionId<EsqlVersion> {
Copy link
Member

Choose a reason for hiding this comment

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

Better make this a class similar to Version - enum are quite restrictive and impossible to extend.
Having a class gives us future extension points - in the worse case we won't use them and the class will be like an enum.

Copy link
Member

Choose a reason for hiding this comment

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

I think we can flip it to a class with constants when we need that. If we can get away with an enum for a while I'd prefer that.

}

private int year;
private int month;
Copy link
Contributor

Choose a reason for hiding this comment

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

month can be made byte.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Makes sense; I'd like to still use an int in the constructor. though, for easier readability if that's good with you?

Comment on lines 28 to 34
for (EsqlVersion version : EsqlVersion.values()) {
EsqlVersion existingVersionForKey = null;
existingVersionForKey = stringToVersion.put(version.versionStringWithoutEmoji(), version);
assert existingVersionForKey == null;
existingVersionForKey = stringToVersion.put(version.toString(), version);
assert existingVersionForKey == null;
}
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
for (EsqlVersion version : EsqlVersion.values()) {
EsqlVersion existingVersionForKey = null;
existingVersionForKey = stringToVersion.put(version.versionStringWithoutEmoji(), version);
assert existingVersionForKey == null;
existingVersionForKey = stringToVersion.put(version.toString(), version);
assert existingVersionForKey == null;
}
for (EsqlVersion version : EsqlVersion.values()) {
assert null == stringToVersion.put(version.versionStringWithoutEmoji(), version);
assert null == stringToVersion.put(version.toString(), version);
}

Copy link
Member

Choose a reason for hiding this comment

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

I think I actually prefer an explicit throw here rather than just an assert. This should run once per instance of Elasticsearch, I don't think we need the performance gain of being able to disable asserts in production.

Copy link
Member

Choose a reason for hiding this comment

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

I'm not entirely sure how assert works, but I'd be worried that putting these onto one line will make it not perform the put if assertions are disabled. FWIW, it doesn't really matter if it runs it or not - it'll slow down a reader either way. But the assert on it's own line is fin.

You could make it a hard test. The extra test on startup is probably not going to hurt us.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This suggestion looks cleaner, but is not equivalent; disabling assertions breaks the version parsing altogether as no version strings are added to the stringToVersion map anymore.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll add an explicit throw new AssertionError(...).

@astefan astefan self-requested a review April 2, 2024 11:34
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.

Also, I think you should have tests for the functionality inherited from VersionId interface, ie comparison of versions based on their id.


@Override
public int id() {
return this == NIGHTLY ? Integer.MAX_VALUE : (10000 * year + 100 * month + revision);
Copy link
Member

Choose a reason for hiding this comment

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

Maybe we should have a test that generates the IDs for all the versions and makes sure there are no duplicates. There shouldn't be, but if someone typos a month I want something to fail.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No dups are already enforced in the construction of the map String -> Version. I'll add a test, though, that ensures a strict ordering of the versions based on their id.

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.

LGTM

@alex-spies alex-spies merged commit 147f5a0 into elastic:main Apr 3, 2024
14 checks passed
@alex-spies alex-spies deleted the esql-version branch April 3, 2024 19:23
@alex-spies
Copy link
Contributor Author

💚 All backports created successfully

Status Branch Result
8.13

Questions ?

Please refer to the Backport tool documentation

alex-spies added a commit to alex-spies/elasticsearch that referenced this pull request Apr 10, 2024
For the _query endpoint, add a parameter for the ESQL language version to the JSON payload.
For now, it is optional and is only validated with no further action.

(cherry picked from commit 147f5a0)

# Conflicts:
#	x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/esql/action/EsqlQueryRequest.java
#	x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/esql/action/EsqlQueryRequestBuilder.java
#	x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequest.java
#	x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequestBuilder.java
#	x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/RequestXContent.java
alex-spies added a commit that referenced this pull request Apr 10, 2024
For the _query endpoint, add a parameter for the ESQL language version to the JSON payload.
For now, it is optional and is only validated with no further action.
alex-spies added a commit to alex-spies/elasticsearch that referenced this pull request Apr 12, 2024
For the _query endpoint, add a parameter for the ESQL language version to the JSON payload.
For now, it is optional and is only validated with no further action.

(cherry picked from commit 147f5a0)

# Conflicts:
#	x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/esql/action/EsqlQueryRequest.java
#	x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/esql/action/EsqlQueryRequestBuilder.java
#	x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequest.java
#	x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequestBuilder.java
#	x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/RequestXContent.java
#	x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequestTests.java
@alex-spies
Copy link
Contributor Author

💚 All backports created successfully

Status Branch Result
8.12
8.11

Questions ?

Please refer to the Backport tool documentation

alex-spies added a commit to alex-spies/elasticsearch that referenced this pull request Apr 12, 2024
For the _query endpoint, add a parameter for the ESQL language version to the JSON payload.
For now, it is optional and is only validated with no further action.

(cherry picked from commit 147f5a0)

# Conflicts:
#	x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/esql/action/EsqlQueryRequest.java
#	x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/esql/action/EsqlQueryRequestBuilder.java
#	x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequest.java
#	x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequestBuilder.java
#	x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/RequestXContent.java
#	x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequestTests.java
elasticsearchmachine pushed a commit that referenced this pull request Apr 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
:Analytics/ES|QL AKA ESQL >enhancement Team:Analytics Meta label for analytical engine team (ESQL/Aggs/Geo) v8.14.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants