Skip to content

Commit c7eb252

Browse files
committed
Integrate with fangs UnionAll/Fork solution for branched views
1 parent 1fdf620 commit c7eb252

File tree

31 files changed

+627
-2698
lines changed

31 files changed

+627
-2698
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
9177000
1+
9183000

x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/Attribute.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ public abstract class Attribute extends NamedExpression {
3535
/**
3636
* Changing this will break bwc with 8.15, see {@link FieldAttribute#fieldName()}.
3737
*/
38-
protected static final String SYNTHETIC_ATTRIBUTE_NAME_PREFIX = "$$";
38+
public static final String SYNTHETIC_ATTRIBUTE_NAME_PREFIX = "$$";
39+
40+
public static final String SYNTHETIC_ATTRIBUTE_NAME_SEPARATOR = "$";
3941

4042
private static final TransportVersion ESQL_QUALIFIERS_IN_ATTRIBUTES = TransportVersion.fromName("esql_qualifiers_in_attributes");
4143

@@ -77,7 +79,7 @@ public Attribute(
7779
}
7880

7981
public static String rawTemporaryName(String... parts) {
80-
var name = String.join("$", parts);
82+
var name = String.join(SYNTHETIC_ATTRIBUTE_NAME_SEPARATOR, parts);
8183
return name.isEmpty() || name.startsWith(SYNTHETIC_ATTRIBUTE_NAME_PREFIX) ? name : SYNTHETIC_ATTRIBUTE_NAME_PREFIX + name;
8284
}
8385

x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/generative/GenerativeForkRestTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import java.util.List;
1515

1616
import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.FORK_V9;
17+
import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.SUBQUERY_IN_FROM_COMMAND;
1718
import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.UNMAPPED_FIELDS;
1819
import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.VIEWS_V1;
1920
import static org.elasticsearch.xpack.esql.qa.rest.RestEsqlTestCase.hasCapabilities;

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

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ ignoreOrder:true
88
count:long | country:keyword
99
1 | Japan
1010
1 | Netherlands
11-
1 | United States of America
11+
1 | United States
1212
;
1313

1414
airports
@@ -63,6 +63,26 @@ count:long | country:keyword
6363
11 | Nigeria
6464
;
6565

66+
airportsCountriesFiltered
67+
required_capability: views_v1
68+
69+
FROM airports_countries
70+
| WHERE count > 15
71+
;
72+
ignoreOrder:true
73+
74+
count:long | country:keyword
75+
129 | United States
76+
50 | India
77+
45 | Mexico
78+
41 | China
79+
37 | Canada
80+
31 | Brazil
81+
26 | Russia
82+
17 | Australia
83+
17 | United Kingdom
84+
;
85+
6686
countriesAirportsAddresses
6787
required_capability: views_v1
6888

@@ -87,25 +107,39 @@ count:long | country:keyword
87107
12 | Indonesia
88108
;
89109

110+
countriesAirportsAddressesUS
111+
required_capability: views_v1
112+
113+
FROM address_countries, airports_countries
114+
| WHERE country == "United States"
115+
;
116+
ignoreOrder:true
117+
118+
count:long | country:keyword
119+
130 | United States
120+
1 | United States
121+
;
122+
90123
languages
91124
required_capability: views_v1
92125

93126
FROM languages_lookup_non_unique_key
94127
| MV_EXPAND country
95128
| WHERE country IS NOT NULL AND country NOT LIKE ("*-Land*")
129+
| EVAL country = CASE(country == "United States of America", "United States", country)
96130
| STATS count=COUNT() BY country
97131
| SORT count DESC, country ASC
98132
;
99133
ignoreOrder:true
100134

101-
count:long | country:text
135+
count:long | country:keyword
102136
1 | Atlantis
103137
1 | Austria
104138
1 | Canada
105139
1 | Germany
106140
1 | Switzerland
107141
1 | United Kingdom
108-
1 | United States of America
142+
1 | United States
109143
;
110144

111145
languagesCountries
@@ -115,12 +149,12 @@ FROM languages_countries
115149
;
116150
ignoreOrder:true
117151

118-
count:long | country:text
152+
count:long | country:keyword
119153
1 | Atlantis
120154
1 | Austria
121155
1 | Canada
122156
1 | Germany
123157
1 | Switzerland
124158
1 | United Kingdom
125-
1 | United States of America
159+
1 | United States
126160
;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
FROM addresses
22
| RENAME city.country.name AS country
3+
| EVAL country = CASE(country == "United States of America", "United States", country)
34
| STATS count=COUNT() BY country
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
FROM languages_lookup_non_unique_key
22
| MV_EXPAND country
33
| WHERE country IS NOT NULL AND country NOT LIKE ("*-Land*")
4+
| EVAL country = CASE(country == "United States of America", "United States", country)
45
| STATS count=COUNT() BY country

x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.g4

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -108,21 +108,8 @@ timeSeriesCommand
108108
: TS indexPatternAndMetadataFields
109109
;
110110

111-
indexPatternAndMetadataFields
112-
: indexPatternOrSubquery (COMMA indexPatternOrSubquery)* metadata?
113-
;
114-
115-
indexPatternOrSubquery
116-
: indexPattern
117-
| {this.isDevVersion()}? subquery
118-
;
119-
120-
subquery
121-
: LP fromCommand (PIPE subqueryProcessingCommand)* RP
122-
;
123-
124-
subqueryProcessingCommand
125-
: processingCommand
111+
indexPatternAndMetadataFields:
112+
indexPattern (COMMA indexPattern)* metadata?
126113
;
127114

128115
indexPattern

x-pack/plugin/esql/src/main/antlr/lexer/From.g4

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,7 @@ FROM_ASSIGN : ASSIGN -> type(ASSIGN);
2323
METADATA : 'metadata';
2424

2525
// we need this for EXPLAIN
26-
// change to double popMode to accommodate subquerys in FROM, when see ')' pop out of subquery(default) mode and from mode
27-
FROM_RP : RP -> type(RP), popMode, popMode;
28-
29-
// accommodate subQuery inside FROM
30-
FROM_LP : LP -> type(LP), pushMode(DEFAULT_MODE);
26+
FROM_RP : RP -> type(RP), popMode;
3127

3228
// in 8.14 ` were not allowed
3329
// this has been relaxed in 8.15 since " is used for quoting

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

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -250,19 +250,9 @@ private static class ResolveTable extends ParameterizedAnalyzerRule<UnresolvedRe
250250

251251
@Override
252252
protected LogicalPlan rule(UnresolvedRelation plan, AnalyzerContext context) {
253-
String indexPattern = plan.indexPattern().indexPattern();
254-
IndexResolution indexResolution;
255-
if (plan.indexMode().equals(IndexMode.LOOKUP)) { // index on the RHS of lookup join
256-
indexResolution = context.lookupResolution().get(indexPattern);
257-
} else { // main index or index in subquery
258-
indexResolution = context.indexResolution();
259-
if (indexPattern != null
260-
&& indexResolution.matches(indexPattern) == false
261-
&& context.subqueryResolution().isEmpty() == false) {
262-
// index pattern does not match main index
263-
indexResolution = context.subqueryResolution().getOrDefault(indexPattern, indexResolution);
264-
}
265-
}
253+
IndexResolution indexResolution = plan.indexMode().equals(IndexMode.LOOKUP)
254+
? context.lookupResolution().get(plan.indexPattern().indexPattern())
255+
: context.indexResolution().get(plan.indexPattern());
266256
return resolveIndex(plan, indexResolution);
267257
}
268258

@@ -548,7 +538,7 @@ protected LogicalPlan rule(LogicalPlan plan, AnalyzerContext context) {
548538
}
549539

550540
if (plan instanceof Insist i) {
551-
return resolveInsist(i, childrenOutput, context.indexResolution());
541+
return resolveInsist(i, childrenOutput, context.indexResolution().values());
552542
}
553543

554544
if (plan instanceof Fuse fuse) {
@@ -979,23 +969,29 @@ private List<Attribute> resolveUsingColumns(List<Attribute> cols, List<Attribute
979969
return resolved;
980970
}
981971

982-
private LogicalPlan resolveInsist(Insist insist, List<Attribute> childrenOutput, IndexResolution indexResolution) {
972+
private LogicalPlan resolveInsist(Insist insist, List<Attribute> childrenOutput, Collection<IndexResolution> indexResolution) {
983973
List<Attribute> list = new ArrayList<>();
984974
for (Attribute a : insist.insistedAttributes()) {
985975
list.add(resolveInsistAttribute(a, childrenOutput, indexResolution));
986976
}
987977
return insist.withAttributes(list);
988978
}
989979

990-
private Attribute resolveInsistAttribute(Attribute attribute, List<Attribute> childrenOutput, IndexResolution indexResolution) {
980+
private Attribute resolveInsistAttribute(
981+
Attribute attribute,
982+
List<Attribute> childrenOutput,
983+
Collection<IndexResolution> indexResolution
984+
) {
991985
Attribute resolvedCol = maybeResolveAttribute((UnresolvedAttribute) attribute, childrenOutput);
992986
// Field isn't mapped anywhere.
993987
if (resolvedCol instanceof UnresolvedAttribute) {
994988
return insistKeyword(attribute);
995989
}
996990

997991
// Field is partially unmapped.
998-
if (resolvedCol instanceof FieldAttribute fa && indexResolution.get().isPartiallyUnmappedField(fa.name())) {
992+
// TODO: Should the check for partially unmapped fields be done specific to each sub-query in a fork?
993+
if (resolvedCol instanceof FieldAttribute fa
994+
&& indexResolution.stream().anyMatch(r -> r.get().isPartiallyUnmappedField(fa.name()))) {
999995
return fa.dataType() == KEYWORD ? insistKeyword(fa) : invalidInsistAttribute(fa);
1000996
}
1001997

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

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,39 +10,28 @@
1010
import org.elasticsearch.xpack.esql.expression.function.EsqlFunctionRegistry;
1111
import org.elasticsearch.xpack.esql.index.IndexResolution;
1212
import org.elasticsearch.xpack.esql.inference.InferenceResolution;
13+
import org.elasticsearch.xpack.esql.plan.IndexPattern;
1314
import org.elasticsearch.xpack.esql.session.Configuration;
1415

1516
import java.util.Map;
1617

1718
public record AnalyzerContext(
1819
Configuration configuration,
1920
EsqlFunctionRegistry functionRegistry,
20-
IndexResolution indexResolution,
21+
Map<IndexPattern, IndexResolution> indexResolution,
2122
Map<String, IndexResolution> lookupResolution,
2223
EnrichResolution enrichResolution,
23-
InferenceResolution inferenceResolution,
24-
Map<String, IndexResolution> subqueryResolution
24+
InferenceResolution inferenceResolution
2525
) {
2626
// Currently for tests only, since most do not test lookups
2727
// TODO: make this even simpler, remove the enrichResolution for tests that do not require it (most tests)
2828
public AnalyzerContext(
2929
Configuration configuration,
3030
EsqlFunctionRegistry functionRegistry,
31-
IndexResolution indexResolution,
31+
Map<IndexPattern, IndexResolution> indexResolution,
3232
EnrichResolution enrichResolution,
3333
InferenceResolution inferenceResolution
3434
) {
35-
this(configuration, functionRegistry, indexResolution, Map.of(), enrichResolution, inferenceResolution, Map.of());
36-
}
37-
38-
public AnalyzerContext(
39-
Configuration configuration,
40-
EsqlFunctionRegistry functionRegistry,
41-
IndexResolution indexResolution,
42-
Map<String, IndexResolution> lookupResolution,
43-
EnrichResolution enrichResolution,
44-
InferenceResolution inferenceResolution
45-
) {
46-
this(configuration, functionRegistry, indexResolution, lookupResolution, enrichResolution, inferenceResolution, Map.of());
35+
this(configuration, functionRegistry, indexResolution, Map.of(), enrichResolution, inferenceResolution);
4736
}
4837
}

0 commit comments

Comments
 (0)