Skip to content

Commit 65b3391

Browse files
alex-spieselasticsearchmachinecraigtaverner
committed
ESQL: Add createdVersion for types (elastic#137432)
* Add createdVersion for types * [CI] Update transport version definitions * [CI] Update transport version definitions * Do not create new transport version for exp histo --------- Co-authored-by: elasticsearchmachine <[email protected]> Co-authored-by: Craig Taverner <[email protected]>
1 parent a999178 commit 65b3391

File tree

2 files changed

+98
-43
lines changed

2 files changed

+98
-43
lines changed

x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/type/DataType.java

Lines changed: 64 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -47,20 +47,25 @@
4747
* {@link DataType#OBJECT})
4848
*
4949
* <h2>Process for adding a new data type</h2>
50+
* We assume that the data type is already supported in ES indices, but not in
51+
* ES|QL. Types that aren't yet enabled in ES will require some adjustments to
52+
* the process.
53+
* <p>
5054
* Note: it is not expected that all the following steps be done in a single PR.
5155
* Use capabilities to gate tests as you go, and use as many PRs as you think
5256
* appropriate. New data types are complex, and smaller PRs will make reviews
5357
* easier.
5458
* <ul>
5559
* <li>
5660
* Create a new data type and mark it as under construction using
57-
* {@link Builder#underConstruction()}. This makes the type available on
61+
* {@link Builder#underConstruction(TransportVersion)}. This makes the type available on
5862
* SNAPSHOT builds, only, prevents some tests from running and prevents documentation
5963
* for the new type to be built.</li>
6064
* <li>
6165
* New tests using the type will require a new {@code EsqlCapabilities} entry,
6266
* otherwise bwc tests will fail (even in SNAPSHOT builds) because old nodes don't
63-
* know about the new type.</li>
67+
* know about the new type. This capability needs to be SNAPSHOT-only as long as
68+
* the type is under construction</li>
6469
* <li>
6570
* Create a new CSV test file for the new type. You'll either need to
6671
* create a new data file as well, or add values of the new type to
@@ -115,20 +120,30 @@
115120
* EsqlDataTypeConverter#commonType, individual function type checking, the
116121
* verifier rules, or other places. We suggest starting with CSV tests and
117122
* seeing where they fail.</li>
123+
* <li>
124+
* Ensure the new type doesn't break {@code FROM idx | KEEP *} queries by
125+
* updating AllSupportedFieldsTestCase. Make sure to run this test in bwc
126+
* configurations in release mode.
127+
* </li>
118128
* </ul>
119-
* There are some additional steps that should be taken when removing the
120-
* feature flag and getting ready for a release:
129+
* There are some additional steps that should be taken when getting ready for a release:
121130
* <ul>
122131
* <li>
123132
* Ensure the capabilities for this type are always enabled.</li>
124133
* <li>
125134
* Mark the type with a new transport version via
126-
* {@link Builder#supportedSince(TransportVersion)}. This will enable the type on
127-
* non-SNAPSHOT builds as long as all nodes in the cluster (and remote clusters)
128-
* support it.</li>
135+
* {@link Builder#supportedSince(TransportVersion, TransportVersion)}.
136+
* This will enable the type on non-SNAPSHOT builds as long as all nodes in the cluster
137+
* (and remote clusters) support it.
138+
* Use the under-construction transport version for the {@code createdVersion} here so that
139+
* existing tests continue to run.
140+
* </li>
129141
* <li>
130142
* Fix new test failures related to declared function types.</li>
131143
* <li>
144+
* Update the expectations in AllSupportedFieldsTestCase and make sure it
145+
* passes in release builds.</li>
146+
* <li>
132147
* Make sure to run the full test suite locally via gradle to generate
133148
* the function type tables and helper files with the new type. Ensure all
134149
* the functions that support the type have appropriate docs for it.</li>
@@ -299,12 +314,23 @@ public enum DataType implements Writeable {
299314
// mixed/multi clusters with remotes that don't support these types. This is low-ish risk because these types require specific
300315
// geo functions to turn up in the query, and those types aren't available before 9.2.0 either.
301316
GEOHASH(
302-
builder().esType("geohash").typeName("GEOHASH").estimatedSize(Long.BYTES).supportedSince(DataTypesTransportVersions.INDEX_SOURCE)
317+
builder().esType("geohash")
318+
.typeName("GEOHASH")
319+
.estimatedSize(Long.BYTES)
320+
.supportedSince(DataTypesTransportVersions.INDEX_SOURCE, DataTypesTransportVersions.INDEX_SOURCE)
303321
),
304322
GEOTILE(
305-
builder().esType("geotile").typeName("GEOTILE").estimatedSize(Long.BYTES).supportedSince(DataTypesTransportVersions.INDEX_SOURCE)
323+
builder().esType("geotile")
324+
.typeName("GEOTILE")
325+
.estimatedSize(Long.BYTES)
326+
.supportedSince(DataTypesTransportVersions.INDEX_SOURCE, DataTypesTransportVersions.INDEX_SOURCE)
327+
),
328+
GEOHEX(
329+
builder().esType("geohex")
330+
.typeName("GEOHEX")
331+
.estimatedSize(Long.BYTES)
332+
.supportedSince(DataTypesTransportVersions.INDEX_SOURCE, DataTypesTransportVersions.INDEX_SOURCE)
306333
),
307-
GEOHEX(builder().esType("geohex").typeName("GEOHEX").estimatedSize(Long.BYTES).supportedSince(DataTypesTransportVersions.INDEX_SOURCE)),
308334

309335
/**
310336
* Fields with this type represent a Lucene doc id. This field is a bit magic in that:
@@ -328,7 +354,10 @@ public enum DataType implements Writeable {
328354
// mixed/multi clusters with remotes that don't support these types. This is low-ish risk because _tsid requires specifically being
329355
// used in `FROM idx METADATA _tsid` or in the `TS` command, which both weren't available before 9.2.0.
330356
TSID_DATA_TYPE(
331-
builder().esType("_tsid").estimatedSize(Long.BYTES * 2).docValues().supportedSince(DataTypesTransportVersions.INDEX_SOURCE)
357+
builder().esType("_tsid")
358+
.estimatedSize(Long.BYTES * 2)
359+
.docValues()
360+
.supportedSince(DataTypesTransportVersions.INDEX_SOURCE, DataTypesTransportVersions.INDEX_SOURCE)
332361
),
333362
/**
334363
* Fields with this type are the partial result of running a non-time-series aggregation
@@ -339,17 +368,25 @@ public enum DataType implements Writeable {
339368
AGGREGATE_METRIC_DOUBLE(
340369
builder().esType("aggregate_metric_double")
341370
.estimatedSize(Double.BYTES * 3 + Integer.BYTES)
342-
.supportedSince(DataTypesTransportVersions.ESQL_AGGREGATE_METRIC_DOUBLE_CREATED_VERSION)
371+
.supportedSince(
372+
DataTypesTransportVersions.ESQL_AGGREGATE_METRIC_DOUBLE_CREATED_VERSION,
373+
DataTypesTransportVersions.ESQL_AGGREGATE_METRIC_DOUBLE_CREATED_VERSION
374+
)
343375
),
344376
/**
345377
* Fields with this type are dense vectors, represented as an array of float values.
346378
*/
347379
DENSE_VECTOR(
348-
builder().esType("dense_vector").estimatedSize(4096).supportedSince(DataTypesTransportVersions.ESQL_DENSE_VECTOR_CREATED_VERSION)
380+
builder().esType("dense_vector")
381+
.estimatedSize(4096)
382+
.supportedSince(
383+
DataTypesTransportVersions.ESQL_DENSE_VECTOR_CREATED_VERSION,
384+
DataTypesTransportVersions.ESQL_DENSE_VECTOR_CREATED_VERSION
385+
)
349386
);
350387

351388
public static final Set<DataType> UNDER_CONSTRUCTION = Arrays.stream(DataType.values())
352-
.filter(t -> t.supportedVersion() == SupportedVersion.UNDER_CONSTRUCTION)
389+
.filter(t -> t.supportedVersion().underConstruction())
353390
.collect(Collectors.toSet());
354391

355392
private final String typeName;
@@ -952,13 +989,15 @@ Builder counter(DataType counter) {
952989
}
953990

954991
/**
955-
* The version from when on a {@link DataType} is supported. When a query tries to use a data type
956-
* not supported on any of the nodes it runs on, it is invalid.
992+
* Marks a type that is supported in production since {@code supportedVersion}.
993+
* When a query tries to use a data type not supported on the nodes it runs on, this is a bug.
957994
* <p>
958-
* Generally, we should add a dedicated transport version when a type is enabled on release builds.
995+
* On snapshot builds, the {@code createdVersion} is used instead, so that existing tests continue
996+
* to work after release if the type was previously {@link #underConstruction(TransportVersion)};
997+
* the under-construction version should be used as the {@code createdVersion}.
959998
*/
960-
Builder supportedSince(TransportVersion supportedVersion) {
961-
this.supportedVersion = SupportedVersion.supportedSince(supportedVersion);
999+
Builder supportedSince(TransportVersion createdVersion, TransportVersion supportedVersion) {
1000+
this.supportedVersion = SupportedVersion.supportedSince(createdVersion, supportedVersion);
9621001
return this;
9631002
}
9641003

@@ -967,8 +1006,12 @@ Builder supportedOnAllNodes() {
9671006
return this;
9681007
}
9691008

970-
Builder underConstruction() {
971-
this.supportedVersion = SupportedVersion.UNDER_CONSTRUCTION;
1009+
/**
1010+
* Marks a type that is not supported in production yet, but is supported in snapshot builds
1011+
* starting with the given version.
1012+
*/
1013+
Builder underConstruction(TransportVersion createdVersion) {
1014+
this.supportedVersion = SupportedVersion.underConstruction(createdVersion);
9721015
return this;
9731016
}
9741017
}

x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/type/SupportedVersion.java

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ default boolean supportedLocally() {
1717
return supportedOn(TransportVersion.current(), Build.current().isSnapshot());
1818
}
1919

20+
default boolean underConstruction() {
21+
return false;
22+
}
23+
2024
SupportedVersion SUPPORTED_ON_ALL_NODES = new SupportedVersion() {
2125
@Override
2226
public boolean supportedOn(TransportVersion version, boolean currentBuildIsSnapshot) {
@@ -37,47 +41,55 @@ public String toString() {
3741
* <li>
3842
* Not tested by {@code ErrorsForCasesWithoutExamplesTestCase} subclasses.
3943
* When a function supports a type it includes a test case in its subclass
40-
* of {@code AbstractFunctionTestCase}. If a function does not support.
44+
* of {@code AbstractFunctionTestCase}. If a function does not support
4145
* them like {@code TO_STRING} then the tests won't notice. See class javadoc
4246
* for instructions on adding new types, but that usually involves adding support
4347
* for that type to a handful of functions. Once you've done that you should be
44-
* able to remove your new type from UNDER_CONSTRUCTION and update a few error
45-
* messages.
48+
* able to turn your new type from under construction into released and update
49+
* a few error messages.
4650
* </li>
4751
* </ul>
4852
* <p>
49-
* Snapshot builds treat these as always supported so that we can write tests before actually
50-
* turning on the support for the type. Mixed/multi cluster tests with older nodes have to be
51-
* skipped based on capabilites, as always.
53+
* Snapshot builds treat these as supported starting from the version they were created on,
54+
* so that we can write tests before actually turning on the support for the type.
55+
* Mixed/multi cluster tests with older nodes should be skipped based on SNAPSHOT-only
56+
* capabilites, as always.
5257
*/
5358
// We used to have a feature-flag based override, so that in-development types could be
5459
// turned on for testing in release builds. If needed, it's fine to bring this back, but we
5560
// need to make sure that other checks for types being under construction are also overridden.
56-
// Check usage of this constant to be sure.
57-
SupportedVersion UNDER_CONSTRUCTION = new SupportedVersion() {
58-
@Override
59-
public boolean supportedOn(TransportVersion version, boolean currentBuildIsSnapshot) {
60-
return currentBuildIsSnapshot;
61-
}
61+
// Check usage of this method to be sure.
62+
static SupportedVersion underConstruction(TransportVersion createdVersion) {
63+
return new SupportedVersion() {
64+
@Override
65+
public boolean supportedOn(TransportVersion version, boolean currentBuildIsSnapshot) {
66+
return currentBuildIsSnapshot && version.supports(createdVersion);
67+
}
6268

63-
@Override
64-
public String toString() {
65-
return "UnderConstruction";
66-
}
67-
};
69+
@Override
70+
public String toString() {
71+
return "UnderConstruction";
72+
}
73+
74+
@Override
75+
public boolean underConstruction() {
76+
return true;
77+
}
78+
};
79+
}
6880

6981
/**
7082
* Types that are supported starting with the given version.
7183
* <p>
72-
* Snapshot builds treat these as always supported, so that any existing tests using them
73-
* continue to work. Otherwise, we'd have to update bwc tests to skip older versions based
74-
* on a capability check, which can be error-prone and risks turning off an unrelated bwc test.
84+
* Snapshot builds treat these as supported from their created version onward, so that any existing tests
85+
* using them should continue to work.
7586
*/
76-
static SupportedVersion supportedSince(TransportVersion supportedVersion) {
87+
static SupportedVersion supportedSince(TransportVersion createdVersion, TransportVersion supportedVersion) {
88+
assert supportedVersion.onOrAfter(createdVersion) : "support for a type cannot be enabled before its initial creation";
7789
return new SupportedVersion() {
7890
@Override
7991
public boolean supportedOn(TransportVersion version, boolean currentBuildIsSnapshot) {
80-
return version.supports(supportedVersion) || currentBuildIsSnapshot;
92+
return currentBuildIsSnapshot ? version.supports(createdVersion) : version.supports(supportedVersion);
8193
}
8294

8395
@Override

0 commit comments

Comments
 (0)