Skip to content

Commit 2800ae5

Browse files
committed
Add explain check
Signed-off-by: Tomoyuki Morita <[email protected]>
1 parent 5ff679e commit 2800ae5

File tree

3 files changed

+103
-31
lines changed

3 files changed

+103
-31
lines changed

integ-test/src/test/java/org/opensearch/sql/calcite/standalone/CalciteDynamicFieldsCommandIT.java

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,33 +30,67 @@ public void init() throws IOException {
3030

3131
@Test
3232
public void testBasicProjection() throws IOException {
33-
JSONObject result =
34-
executeQuery(
35-
source(TEST_INDEX_DYNAMIC, "fields firstname, lastname, department, salary | head 1"));
36-
33+
String query =
34+
source(TEST_INDEX_DYNAMIC, "fields firstname, lastname, department, salary | head 1");
35+
JSONObject result = executeQuery(query);
3736
verifySchema(
3837
result,
3938
schema("firstname", "string"),
4039
schema("lastname", "string"),
4140
schema("department", "string"),
4241
schema("salary", "int"));
4342
verifyDataRows(result, rows("John", "Doe", "Engineering", 75000));
43+
44+
assertExplainYaml(
45+
query,
46+
"calcite:\n"
47+
+ " logical: |\n"
48+
+ " LogicalSystemLimit(fetch=[200], type=[QUERY_SIZE_LIMIT])\n"
49+
+ " LogicalSort(fetch=[1])\n"
50+
+ " LogicalProject(firstname=[$0], lastname=[$2], department=[ITEM($9,"
51+
+ " 'department')], salary=[ITEM($9, 'salary')])\n"
52+
+ " CalciteLogicalIndexScan(table=[[OpenSearch, test_dynamic_fields]])\n"
53+
+ " physical: |\n"
54+
+ " EnumerableLimit(fetch=[200])\n"
55+
+ " EnumerableCalc(expr#0..9=[{inputs}], expr#10=['department'],"
56+
+ " expr#11=[ITEM($t9, $t10)], expr#12=['salary'], expr#13=[ITEM($t9, $t12)],"
57+
+ " firstname=[$t0], lastname=[$t2], department=[$t11], salary=[$t13])\n"
58+
+ " EnumerableLimit(fetch=[1])\n"
59+
+ " CalciteEnumerableIndexScan(table=[[OpenSearch, test_dynamic_fields]])\n");
4460
}
4561

4662
@Test
4763
public void testEval() throws IOException {
48-
JSONObject result =
49-
executeQuery(
50-
source(
51-
TEST_INDEX_DYNAMIC,
52-
"eval salary = cast(salary as int) * 2 | fields firstname,"
53-
+ " lastname, salary | head 1"));
64+
String query =
65+
source(
66+
TEST_INDEX_DYNAMIC,
67+
"eval salary = cast(salary as int) * 2 | fields firstname,"
68+
+ " lastname, salary | head 1");
69+
JSONObject result = executeQuery(query);
5470

5571
verifySchema(
5672
result,
5773
schema("firstname", "string"),
5874
schema("lastname", "string"),
5975
schema("salary", "int"));
76+
77+
assertExplainYaml(
78+
query,
79+
"calcite:\n"
80+
+ " logical: |\n"
81+
+ " LogicalSystemLimit(fetch=[200], type=[QUERY_SIZE_LIMIT])\n"
82+
+ " LogicalSort(fetch=[1])\n"
83+
+ " LogicalProject(firstname=[$0], lastname=[$2], salary=[*(SAFE_CAST(ITEM($9,"
84+
+ " 'salary')), 2)])\n"
85+
+ " CalciteLogicalIndexScan(table=[[OpenSearch, test_dynamic_fields]])\n"
86+
+ " physical: |\n"
87+
+ " EnumerableLimit(fetch=[200])\n"
88+
+ " EnumerableCalc(expr#0..9=[{inputs}], expr#10=['salary'], expr#11=[ITEM($t9,"
89+
+ " $t10)], expr#12=[SAFE_CAST($t11)], expr#13=[2], expr#14=[*($t12, $t13)],"
90+
+ " firstname=[$t0], lastname=[$t2], salary=[$t14])\n"
91+
+ " EnumerableLimit(fetch=[1])\n"
92+
+ " CalciteEnumerableIndexScan(table=[[OpenSearch, test_dynamic_fields]])\n"
93+
+ "");
6094
}
6195

6296
private void createTestIndexWithUnmappedFields() throws IOException {
@@ -67,8 +101,8 @@ private void createTestIndexWithUnmappedFields() throws IOException {
67101
String mapping =
68102
"{"
69103
+ "\"mappings\": {"
70-
+ " \"dynamic\": false," // Disable dynamic mapping - extra fields won't be indexed but
71-
// will be stored
104+
// Disable dynamic mapping - extra fields won't be indexed but will be stored
105+
+ " \"dynamic\": false,"
72106
+ " \"properties\": {"
73107
+ " \"firstname\": {\"type\": \"text\"},"
74108
+ " \"lastname\": {\"type\": \"text\"},"

integ-test/src/test/java/org/opensearch/sql/calcite/standalone/CalcitePPLIntegTestCase.java

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@
6565
import org.opensearch.sql.ppl.domain.PPLQueryRequest;
6666
import org.opensearch.sql.protocol.response.QueryResult;
6767
import org.opensearch.sql.protocol.response.format.JsonResponseFormatter;
68+
import org.opensearch.sql.protocol.response.format.ResponseFormatter;
6869
import org.opensearch.sql.protocol.response.format.SimpleJsonResponseFormatter;
70+
import org.opensearch.sql.protocol.response.format.YamlResponseFormatter;
6971
import org.opensearch.sql.sql.SQLService;
7072
import org.opensearch.sql.sql.antlr.SQLSyntaxParser;
7173
import org.opensearch.sql.storage.DataSourceFactory;
@@ -232,29 +234,50 @@ public void onFailure(Exception e) {
232234
protected String explainQuery(String query) {
233235
AtomicReference<String> actual = new AtomicReference<>();
234236
pplService.explain(
235-
new PPLQueryRequest(query, null, null),
236-
new ResponseListener<ExecutionEngine.ExplainResponse>() {
237-
238-
@Override
239-
public void onResponse(ExecutionEngine.ExplainResponse response) {
240-
String responseContent =
241-
new JsonResponseFormatter<ExecutionEngine.ExplainResponse>(PRETTY) {
242-
@Override
243-
protected Object buildJsonObject(ExecutionEngine.ExplainResponse response) {
244-
return response;
245-
}
246-
}.format(response);
247-
actual.set(responseContent.replace("\\r\\n", "\\n"));
248-
}
237+
new PPLQueryRequest("explain " + query, null, null), formatListener(jsonFormatter, actual));
238+
return actual.get();
239+
}
249240

250-
@Override
251-
public void onFailure(Exception e) {
252-
throw new IllegalStateException("Exception happened during execution", e);
253-
}
254-
});
241+
@Override
242+
protected String explainQueryYaml(String query) {
243+
AtomicReference<String> actual = new AtomicReference<>();
244+
pplService.explain(
245+
new PPLQueryRequest("explain " + query, null, null), formatListener(yamlFormatter, actual));
255246
return actual.get();
256247
}
257248

249+
private <T> ResponseListener<T> formatListener(
250+
ResponseFormatter<T> formatter, AtomicReference<String> actual) {
251+
return new ResponseListener<T>() {
252+
@Override
253+
public void onResponse(T response) {
254+
String responseContent = formatter.format(response);
255+
actual.set(responseContent.replace("\\r\\n", "\\n"));
256+
}
257+
258+
@Override
259+
public void onFailure(Exception e) {
260+
throw new IllegalStateException("Exception happened during execution", e);
261+
}
262+
};
263+
}
264+
265+
private JsonResponseFormatter<ExecutionEngine.ExplainResponse> jsonFormatter =
266+
new JsonResponseFormatter<>(PRETTY) {
267+
@Override
268+
protected Object buildJsonObject(ExecutionEngine.ExplainResponse response) {
269+
return response;
270+
}
271+
};
272+
273+
private YamlResponseFormatter<ExecutionEngine.ExplainResponse> yamlFormatter =
274+
new YamlResponseFormatter<>() {
275+
@Override
276+
protected Object buildYamlObject(ExecutionEngine.ExplainResponse response) {
277+
return response;
278+
}
279+
};
280+
258281
public static DataSourceMetadataStorage getDataSourceMetadataStorage() {
259282
return new DataSourceMetadataStorage() {
260283
@Override

integ-test/src/test/java/org/opensearch/sql/calcite/standalone/CalcitePPLPermissiveIntegTestCase.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,19 @@ public DataSource createDataSource(DataSourceMetadata metadata) {
3434
protected Settings getSettings() {
3535
return defaultSettings(getDefaultSettingsBuilder().put(Key.PPL_QUERY_PERMISSIVE, true).build());
3636
}
37+
38+
protected void assertExplainYaml(String query, String expectedYaml) {
39+
String actualYaml = explainQueryYaml(query);
40+
assertTrue(getMessage(expectedYaml, actualYaml), expectedYaml.equals(actualYaml));
41+
}
42+
43+
private String getMessage(String expectedYaml, String actualYaml) {
44+
return "Explain did not match:\n"
45+
+ String.format(
46+
"# Expected: %s# Actual: %s", blockQuote(expectedYaml), blockQuote(actualYaml));
47+
}
48+
49+
private String blockQuote(String str) {
50+
return "```\n" + str + "```\n";
51+
}
3752
}

0 commit comments

Comments
 (0)