Skip to content

Commit a148619

Browse files
craigtavernerdavidkyle
authored andcommitted
Support widening of numeric types in union-types (#112610)
* Support widening of numeric types in union-types Only two lines of this PR are the actual fix. All the rest is updating the CSV-spec testing infrastructure to make it easier to test this, and adding the tests. The refactoring involve some cleanup and simplifications also. This update allows us to add alternative mappings of existing data files without copying the files and changing the header line. Some of the existing union-types test files were deleted as a result, which is a step in the right direction. * Update docs/changelog/112610.yaml * Link capability to PR
1 parent 051f504 commit a148619

File tree

12 files changed

+201
-187
lines changed

12 files changed

+201
-187
lines changed

docs/changelog/112610.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pr: 112610
2+
summary: Support widening of numeric types in union-types
3+
area: ES|QL
4+
type: bug
5+
issues:
6+
- 111277

x-pack/plugin/esql/qa/testFixtures/build.gradle

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,18 @@ apply plugin: 'elasticsearch.java'
22
apply plugin: org.elasticsearch.gradle.dependencies.CompileOnlyResolvePlugin
33

44
dependencies {
5-
implementation project(':x-pack:plugin:esql:compute')
6-
implementation project(':x-pack:plugin:esql')
7-
compileOnly project(path: xpackModule('core'))
8-
implementation project(":libs:elasticsearch-x-content")
9-
implementation project(':client:rest')
10-
implementation project(':libs:elasticsearch-logging')
11-
implementation project(':test:framework')
12-
api(testArtifact(project(xpackModule('esql-core'))))
13-
implementation project(':server')
14-
implementation "net.sf.supercsv:super-csv:${versions.supercsv}"
5+
implementation project(':x-pack:plugin:esql:compute')
6+
implementation project(':x-pack:plugin:esql')
7+
compileOnly project(path: xpackModule('core'))
8+
implementation project(":libs:elasticsearch-x-content")
9+
implementation project(':client:rest')
10+
implementation project(':libs:elasticsearch-logging')
11+
implementation project(':test:framework')
12+
api(testArtifact(project(xpackModule('esql-core'))))
13+
implementation project(':server')
14+
implementation "net.sf.supercsv:super-csv:${versions.supercsv}"
15+
implementation "com.fasterxml.jackson.core:jackson-core:${versions.jackson}"
16+
implementation "com.fasterxml.jackson.core:jackson-databind:${versions.jackson}"
1517
}
1618

1719
/**

x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvTestUtils.java

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ public static Tuple<Version, Version> skipVersionRange(String testName, String i
118118
return null;
119119
}
120120

121-
public static Tuple<Page, List<String>> loadPageFromCsv(URL source) throws Exception {
121+
public static Tuple<Page, List<String>> loadPageFromCsv(URL source, Map<String, String> typeMapping) throws Exception {
122122

123123
record CsvColumn(String name, Type type, BuilderWrapper builderWrapper) implements Releasable {
124124
void append(String stringValue) {
@@ -164,21 +164,16 @@ public void close() {
164164
if (columns == null) {
165165
columns = new CsvColumn[entries.length];
166166
for (int i = 0; i < entries.length; i++) {
167-
int split = entries[i].indexOf(':');
168-
String name, typeName;
167+
String[] header = entries[i].split(":");
168+
String name = header[0].trim();
169+
String typeName = (typeMapping != null && typeMapping.containsKey(name)) ? typeMapping.get(name)
170+
: header.length > 1 ? header[1].trim()
171+
: null;
169172

170-
if (split < 0) {
173+
if (typeName == null || typeName.isEmpty()) {
171174
throw new IllegalArgumentException(
172175
"A type is always expected in the schema definition; found " + entries[i]
173176
);
174-
} else {
175-
name = entries[i].substring(0, split).trim();
176-
typeName = entries[i].substring(split + 1).trim();
177-
if (typeName.length() == 0) {
178-
throw new IllegalArgumentException(
179-
"A type is always expected in the schema definition; found " + entries[i]
180-
);
181-
}
182177
}
183178
Type type = Type.asType(typeName);
184179
if (type == null) {

x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvTestsDataLoader.java

Lines changed: 102 additions & 117 deletions
Large diffs are not rendered by default.

x-pack/plugin/esql/qa/testFixtures/src/main/resources/mapping-sample_data_str.json

Lines changed: 0 additions & 16 deletions
This file was deleted.

x-pack/plugin/esql/qa/testFixtures/src/main/resources/mapping-sample_data_ts_long.json

Lines changed: 0 additions & 16 deletions
This file was deleted.

x-pack/plugin/esql/qa/testFixtures/src/main/resources/sample_data_str.csv

Lines changed: 0 additions & 8 deletions
This file was deleted.

x-pack/plugin/esql/qa/testFixtures/src/main/resources/union_types.csv-spec

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,3 +1351,54 @@ FROM sample_data, sample_data_ts_long
13511351
null | 172.21.0.5 | 1232382 | Disconnected | Disconnected
13521352
null | 172.21.0.5 | 1232382 | Disconnected | Disconnected
13531353
;
1354+
1355+
shortIntegerWidening
1356+
required_capability: union_types
1357+
required_capability: metadata_fields
1358+
required_capability: casting_operator
1359+
required_capability: union_types_numeric_widening
1360+
1361+
FROM apps, apps_short METADATA _index
1362+
| EVAL id = id::integer
1363+
| KEEP _index, id, version, name
1364+
| WHERE name == "aaaaa" OR name == "hhhhh"
1365+
| SORT _index ASC, id ASC
1366+
;
1367+
1368+
_index:keyword | id:integer | version:version | name:keyword
1369+
apps | 1 | 1 | aaaaa
1370+
apps | 8 | 1.2.3.4 | hhhhh
1371+
apps | 12 | 1.2.3.4 | aaaaa
1372+
apps_short | 1 | 1 | aaaaa
1373+
apps_short | 8 | 1.2.3.4 | hhhhh
1374+
apps_short | 12 | 1.2.3.4 | aaaaa
1375+
;
1376+
1377+
shortIntegerWideningStats
1378+
required_capability: union_types
1379+
required_capability: casting_operator
1380+
required_capability: union_types_numeric_widening
1381+
1382+
FROM apps, apps_short
1383+
| EVAL id = id::integer
1384+
| STATS count=count() BY name, id
1385+
| KEEP id, name, count
1386+
| SORT id ASC, name ASC
1387+
;
1388+
1389+
id:integer | name:keyword | count:long
1390+
1 | aaaaa | 2
1391+
2 | bbbbb | 2
1392+
3 | ccccc | 2
1393+
4 | ddddd | 2
1394+
5 | eeeee | 2
1395+
6 | fffff | 2
1396+
7 | ggggg | 2
1397+
8 | hhhhh | 2
1398+
9 | iiiii | 2
1399+
10 | jjjjj | 2
1400+
11 | kkkkk | 2
1401+
12 | aaaaa | 2
1402+
13 | lllll | 2
1403+
14 | mmmmm | 2
1404+
;

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,11 @@ public enum Cap {
198198
*/
199199
UNION_TYPES_MISSING_FIELD,
200200

201+
/**
202+
* Fix for widening of short numeric types in union-types. Done in #112610
203+
*/
204+
UNION_TYPES_NUMERIC_WIDENING,
205+
201206
/**
202207
* Fix a parsing issue where numbers below Long.MIN_VALUE threw an exception instead of parsing as doubles.
203208
* see <a href="https://github.com/elastic/elasticsearch/issues/104323"> Parsing large numbers is inconsistent #104323 </a>

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@
115115
import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD;
116116
import static org.elasticsearch.xpack.esql.core.type.DataType.LONG;
117117
import static org.elasticsearch.xpack.esql.core.type.DataType.TEXT;
118-
import static org.elasticsearch.xpack.esql.core.type.DataType.UNSIGNED_LONG;
119118
import static org.elasticsearch.xpack.esql.core.type.DataType.VERSION;
120119
import static org.elasticsearch.xpack.esql.core.type.DataType.isTemporalAmount;
121120
import static org.elasticsearch.xpack.esql.stats.FeatureMetric.LIMIT;
@@ -1223,8 +1222,7 @@ private Expression resolveConvertFunction(AbstractConvertFunction convert, List<
12231222
HashMap<TypeResolutionKey, Expression> typeResolutions = new HashMap<>();
12241223
Set<DataType> supportedTypes = convert.supportedTypes();
12251224
imf.types().forEach(type -> {
1226-
// TODO: Shouldn't we perform widening of small numerical types here?
1227-
if (supportedTypes.contains(type)) {
1225+
if (supportedTypes.contains(type.widenSmallNumeric())) {
12281226
TypeResolutionKey key = new TypeResolutionKey(fa.name(), type);
12291227
var concreteConvert = typeSpecificConvert(convert, fa.source(), type, imf);
12301228
typeResolutions.put(key, concreteConvert);

0 commit comments

Comments
 (0)