Skip to content

Commit fb124c9

Browse files
committed
Refactor to access views within FROM command
Also add csv-spec tests that actually pass!
1 parent 2b97966 commit fb124c9

File tree

9 files changed

+180
-126
lines changed

9 files changed

+180
-126
lines changed

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

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import java.util.Locale;
5252
import java.util.Map;
5353
import java.util.TreeMap;
54+
import java.util.concurrent.Callable;
5455
import java.util.stream.Collectors;
5556
import java.util.stream.IntStream;
5657
import java.util.stream.LongStream;
@@ -121,20 +122,49 @@ protected EsqlSpecTestCase(
121122
this.mode = randomFrom(Mode.values());
122123
}
123124

124-
private static boolean dataLoaded = false;
125+
private static final Object lock = new Object();
126+
private static volatile boolean dataLoaded = false;
127+
private static volatile boolean setupStarted = false;
128+
private static volatile Throwable setupFailure = null;
125129

126130
@Before
127-
public void setup() throws IOException {
128-
boolean supportsLookup = supportsIndexModeLookup();
129-
boolean supportsSourceMapping = supportsSourceFieldMapping();
130-
boolean supportsInferenceTestService = supportsInferenceTestService();
131-
if (dataLoaded == false) {
131+
public void setup() {
132+
protectedBlock(() -> {
133+
boolean supportsLookup = supportsIndexModeLookup();
134+
boolean supportsSourceMapping = supportsSourceFieldMapping();
135+
boolean supportsInferenceTestService = supportsInferenceTestService();
132136
if (supportsInferenceTestService) {
133137
createInferenceEndpoints(adminClient());
134138
}
135-
136139
loadDataSetIntoEs(client(), supportsLookup, supportsSourceMapping, supportsInferenceTestService);
137-
dataLoaded = true;
140+
return null;
141+
});
142+
}
143+
144+
private static void protectedBlock(Callable<Void> callable) {
145+
if (dataLoaded) {
146+
return;
147+
}
148+
// In case tests get run in parallel, we ensure only one setup is run, and other tests wait for this
149+
synchronized (lock) {
150+
if (dataLoaded) {
151+
return;
152+
}
153+
if (setupStarted) {
154+
// Should only happen if a previous test setup failed, possibly with partial setup, let's fail fast the current test
155+
if (setupFailure != null) {
156+
fail(setupFailure, "Previous test setup failed: " + setupFailure.getMessage());
157+
}
158+
fail("Previous test setup failed with unknown error");
159+
}
160+
setupStarted = true;
161+
try {
162+
callable.call();
163+
dataLoaded = true;
164+
} catch (Throwable t) {
165+
setupFailure = t;
166+
fail(setupFailure, "Current test setup failed: " + setupFailure.getMessage());
167+
}
138168
}
139169
}
140170

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,11 @@ public class CsvTestsDataLoader {
268268
);
269269
public static final String NUMERIC_REGEX = "-?\\d+(\\.\\d+)?";
270270

271+
private static final ViewConfig ADDRESS_COUNTRIES = new ViewConfig("address_countries");
272+
private static final ViewConfig AIRPORTS_COUNTRIES = new ViewConfig("airports_countries");
273+
private static final ViewConfig LANGUAGES_COUNTRIES = new ViewConfig("languages_countries");
274+
public static final List<ViewConfig> VIEW_CONFIGS = List.of(ADDRESS_COUNTRIES, AIRPORTS_COUNTRIES, LANGUAGES_COUNTRIES);
275+
271276
/**
272277
* <p>
273278
* Loads spec data on a local ES server.
@@ -402,14 +407,20 @@ private static void loadDataSetIntoEs(
402407
Logger logger = LogManager.getLogger(CsvTestsDataLoader.class);
403408

404409
Set<String> loadedDatasets = new HashSet<>();
410+
logger.info("Loading test datasets");
405411
for (var dataset : availableDatasetsForEs(supportsIndexModeLookup, supportsSourceFieldMapping, inferenceEnabled)) {
406412
load(client, dataset, logger, indexCreator);
407413
loadedDatasets.add(dataset.indexName);
408414
}
409415
forceMerge(client, loadedDatasets, logger);
416+
logger.info("Loading enrich policies");
410417
for (var policy : ENRICH_POLICIES) {
411418
loadEnrichPolicy(client, policy.policyName, policy.policyFileName, logger);
412419
}
420+
logger.info("Loading views");
421+
for (var view : VIEW_CONFIGS) {
422+
loadView(client, view.viewName, view.viewFileName, logger);
423+
}
413424
}
414425

415426
public static void createInferenceEndpoints(RestClient client) throws IOException {
@@ -548,6 +559,7 @@ private static void deleteInferenceEndpoint(RestClient client, String inferenceI
548559
}
549560

550561
private static void loadEnrichPolicy(RestClient client, String policyName, String policyFileName, Logger logger) throws IOException {
562+
logger.info("Loading enrich policy [{}] from file [{}]", policyName, policyFileName);
551563
URL policyMapping = getResource("/" + policyFileName);
552564
String entity = readTextFile(policyMapping);
553565
Request request = new Request("PUT", "/_enrich/policy/" + policyName);
@@ -558,6 +570,16 @@ private static void loadEnrichPolicy(RestClient client, String policyName, Strin
558570
client.performRequest(request);
559571
}
560572

573+
private static void loadView(RestClient client, String viewName, String viewFilename, Logger logger) throws IOException {
574+
logger.info("Loading view [{}] from file [{}]", viewName, viewFilename);
575+
URL viewFile = getResource("/" + viewFilename);
576+
String viewQuery = readTextFile(viewFile);
577+
Request request = new Request("PUT", "/_query/view/" + viewName);
578+
request.setJsonEntity("{\"query\":\"" + viewQuery.replace("\"", "\\\"").replace("\n", " ") + "\"}");
579+
Response response = client.performRequest(request);
580+
logger.info("View creation response: {}", response.getStatusLine());
581+
}
582+
561583
private static URL getResource(String name) {
562584
URL result = CsvTestsDataLoader.class.getResource(name);
563585
if (result == null) {
@@ -567,6 +589,7 @@ private static URL getResource(String name) {
567589
}
568590

569591
private static void load(RestClient client, TestDataset dataset, Logger logger, IndexCreator indexCreator) throws IOException {
592+
logger.info("Loading dataset [{}] into ES index [{}]", dataset.dataFileName, dataset.indexName);
570593
URL mapping = getResource("/" + dataset.mappingFileName);
571594
Settings indexSettings = dataset.readSettingsFile();
572595
indexCreator.createIndex(client, dataset.indexName, readMappingFile(mapping, dataset.typeMapping), indexSettings);
@@ -933,6 +956,12 @@ private Settings readSettingsFile() throws IOException {
933956
}
934957
}
935958

959+
public record ViewConfig(String viewName, String viewFileName) {
960+
public ViewConfig(String viewName) {
961+
this(viewName, "views/" + viewName + ".esql");
962+
}
963+
}
964+
936965
public record EnrichConfig(String policyName, String policyFileName) {}
937966

938967
private interface IndexCreator {
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
addressCountries
2+
FROM address_countries
3+
;
4+
5+
count:long | country:keyword
6+
1 | Netherlands
7+
1 | United States of America
8+
1 | Japan
9+
;
10+
11+
airports
12+
FROM airports
13+
| WHERE country IS NOT NULL
14+
| STATS count=COUNT() BY country
15+
| SORT count DESC
16+
| WHERE count > 10
17+
;
18+
19+
count:long | country:keyword
20+
129 | United States
21+
50 | India
22+
45 | Mexico
23+
41 | China
24+
37 | Canada
25+
31 | Brazil
26+
26 | Russia
27+
17 | United Kingdom
28+
17 | Australia
29+
13 | Argentina
30+
12 | France
31+
12 | Indonesia
32+
11 | Nigeria
33+
11 | Italy
34+
11 | Germany
35+
;
36+
37+
airportsCountries
38+
FROM airports_countries
39+
;
40+
41+
count:long | country:keyword
42+
129 | United States
43+
50 | India
44+
45 | Mexico
45+
41 | China
46+
37 | Canada
47+
31 | Brazil
48+
26 | Russia
49+
17 | United Kingdom
50+
17 | Australia
51+
13 | Argentina
52+
12 | France
53+
12 | Indonesia
54+
11 | Nigeria
55+
11 | Italy
56+
11 | Germany
57+
;
58+
59+
languages
60+
FROM languages_lookup_non_unique_key
61+
| MV_EXPAND country
62+
| WHERE country IS NOT NULL AND country NOT LIKE ("*-Land*")
63+
| STATS count=COUNT() BY country
64+
;
65+
66+
count:long | country:text
67+
1 | Canada
68+
1 | United Kingdom
69+
1 | United States of America
70+
1 | Germany
71+
1 | Austria
72+
1 | Switzerland
73+
1 | Atlantis
74+
;
75+
76+
languagesCountries
77+
FROM languages_countries
78+
;
79+
80+
count:long | country:text
81+
1 | Canada
82+
1 | United Kingdom
83+
1 | United States of America
84+
1 | Germany
85+
1 | Austria
86+
1 | Switzerland
87+
1 | Atlantis
88+
;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
FROM addresses
2+
| RENAME city.country.name AS country
3+
| STATS count=COUNT() BY country
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
FROM airports
2+
| WHERE country IS NOT NULL
3+
| STATS count=COUNT() BY country
4+
| SORT count DESC
5+
| WHERE count > 10
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
FROM languages_lookup_non_unique_key
2+
| MV_EXPAND country
3+
| WHERE country IS NOT NULL AND country NOT LIKE ("*-Land*")
4+
| STATS count=COUNT() BY country

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/logical/UnresolvedView.java

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

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/view/RestPutViewAction.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@
1919
import java.io.IOException;
2020
import java.util.List;
2121

22-
import static org.elasticsearch.rest.RestRequest.Method.POST;
22+
import static org.elasticsearch.rest.RestRequest.Method.PUT;
2323

2424
@ServerlessScope(Scope.PUBLIC)
2525
public class RestPutViewAction extends BaseRestHandler {
2626
@Override
2727
public List<Route> routes() {
28-
return List.of(new Route(POST, "/_query/view/{name}"));
28+
return List.of(new Route(PUT, "/_query/view/{name}"));
2929
}
3030

3131
@Override

0 commit comments

Comments
 (0)