fields(String... fieldNames) {
}
@Test
+ @RequiresCapability(NESTED_FIELDS)
public void selectNestedFields() throws IOException {
JSONObject response =
executeQuery(
@@ -237,6 +248,7 @@ public void selectNestedFields() throws IOException {
}
@Test
+ @RequiresCapability(NESTED_FIELDS)
public void selectNestedFieldWithWildcard() throws IOException {
JSONObject response =
executeQuery(
@@ -456,6 +468,7 @@ public void aggregationFunctionInHaving() throws IOException {
// TEST_INDEX_ACCOUNT);
// }
@Test
+ @RequiresCapability(RESPONSE_FORMAT)
public void fieldsWithAlias() throws IOException {
JSONObject response =
executeQuery(
@@ -506,6 +519,7 @@ public void joinQuery() throws IOException {
}
@Test
+ @RequiresCapability(RESPONSE_FORMAT)
public void joinQueryWithAlias() throws IOException {
JSONObject response =
executeQuery(
@@ -565,6 +579,7 @@ public void joinQuerySelectOnlyOnOneTable() throws Exception {
}
@Test
+ @RequiresCapability(DYNAMIC_STRING_NO_KEYWORD)
public void fieldOrder() throws IOException {
final String[] expectedFields = {"age", "firstname", "address", "gender", "email"};
@@ -574,6 +589,7 @@ public void fieldOrder() throws IOException {
}
@Test
+ @RequiresCapability(DYNAMIC_STRING_NO_KEYWORD)
public void fieldOrderOther() throws IOException {
final String[] expectedFields = {"email", "firstname", "age", "gender", "address"};
diff --git a/integ-test/src/test/java/org/opensearch/sql/legacy/SQLIntegTestCase.java b/integ-test/src/test/java/org/opensearch/sql/legacy/SQLIntegTestCase.java
index ef05923b06..05a670de39 100644
--- a/integ-test/src/test/java/org/opensearch/sql/legacy/SQLIntegTestCase.java
+++ b/integ-test/src/test/java/org/opensearch/sql/legacy/SQLIntegTestCase.java
@@ -139,6 +139,11 @@ public static void dumpCoverage() {
*/
@AfterClass
public static void cleanUpIndices() throws IOException {
+ // No client when every test in the class was skipped (e.g. @RequiresCapability on the AE
+ // route).
+ if (client() == null) {
+ return;
+ }
if (System.getProperty("tests.rest.bwcsuite") == null) {
wipeAllOpenSearchIndices();
wipeAllClusterSettings();
diff --git a/integ-test/src/test/java/org/opensearch/sql/legacy/SqlLegacyEngineSanityIT.java b/integ-test/src/test/java/org/opensearch/sql/legacy/SqlLegacyEngineSanityIT.java
index b2d22808a4..1c92cee74a 100644
--- a/integ-test/src/test/java/org/opensearch/sql/legacy/SqlLegacyEngineSanityIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/legacy/SqlLegacyEngineSanityIT.java
@@ -7,12 +7,14 @@
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_DOG;
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_PEOPLE;
+import static org.opensearch.sql.util.Capability.TEXT_FIELD_EXACT_MATCH;
import static org.opensearch.sql.util.MatcherUtils.rows;
import static org.opensearch.sql.util.MatcherUtils.verifyDataRows;
import java.io.IOException;
import org.json.JSONObject;
import org.junit.Test;
+import org.opensearch.sql.util.RequiresCapability;
/**
* Sanity tests for the legacy SQL engine. Many legacy integration tests (JoinIT, SubqueryIT,
@@ -38,6 +40,7 @@ public void testInnerJoinFallback() throws IOException {
}
@Test
+ @RequiresCapability(TEXT_FIELD_EXACT_MATCH)
public void testLeftJoinFallback() throws IOException {
JSONObject result =
executeQuery(
diff --git a/integ-test/src/test/java/org/opensearch/sql/ppl/MathematicalFunctionIT.java b/integ-test/src/test/java/org/opensearch/sql/ppl/MathematicalFunctionIT.java
index 6df60f68a7..42f6901027 100644
--- a/integ-test/src/test/java/org/opensearch/sql/ppl/MathematicalFunctionIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/ppl/MathematicalFunctionIT.java
@@ -7,6 +7,7 @@
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_BANK;
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_CALCS;
+import static org.opensearch.sql.util.Capability.FUNCTION_TYPE_COMPAT;
import static org.opensearch.sql.util.Capability.RAND_SEED_UNSUPPORTED;
import static org.opensearch.sql.util.MatcherUtils.closeTo;
import static org.opensearch.sql.util.MatcherUtils.rows;
@@ -71,6 +72,7 @@ public void testDivideFunction() throws IOException {
}
@Test
+ @RequiresCapability(FUNCTION_TYPE_COMPAT)
public void testCeil() throws IOException {
JSONObject result =
executeQuery(String.format("source=%s | eval f = ceil(age) | fields f", TEST_INDEX_BANK));
diff --git a/integ-test/src/test/java/org/opensearch/sql/ppl/SystemFunctionIT.java b/integ-test/src/test/java/org/opensearch/sql/ppl/SystemFunctionIT.java
index 276ab01da4..00eb26b43d 100644
--- a/integ-test/src/test/java/org/opensearch/sql/ppl/SystemFunctionIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/ppl/SystemFunctionIT.java
@@ -10,6 +10,7 @@
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_DATATYPE_NONNUMERIC;
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_DATATYPE_NUMERIC;
import static org.opensearch.sql.util.Capability.SCALED_FLOAT_TYPE;
+import static org.opensearch.sql.util.Capability.UNTYPED_NULL_LITERAL;
import static org.opensearch.sql.util.MatcherUtils.rows;
import static org.opensearch.sql.util.MatcherUtils.verifyDataRows;
@@ -28,6 +29,7 @@ public void init() throws Exception {
}
@Test
+ @RequiresCapability(UNTYPED_NULL_LITERAL)
public void typeof_sql_types() throws IOException {
JSONObject response =
executeQuery(
diff --git a/integ-test/src/test/java/org/opensearch/sql/ppl/TextFunctionIT.java b/integ-test/src/test/java/org/opensearch/sql/ppl/TextFunctionIT.java
index 7fe360d884..bc1b60eeba 100644
--- a/integ-test/src/test/java/org/opensearch/sql/ppl/TextFunctionIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/ppl/TextFunctionIT.java
@@ -6,6 +6,7 @@
package org.opensearch.sql.ppl;
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_STRINGS;
+import static org.opensearch.sql.util.Capability.FUNCTION_TYPE_COMPAT;
import static org.opensearch.sql.util.MatcherUtils.rows;
import static org.opensearch.sql.util.MatcherUtils.schema;
import static org.opensearch.sql.util.MatcherUtils.verifyDataRows;
@@ -14,6 +15,7 @@
import java.io.IOException;
import org.json.JSONObject;
import org.junit.jupiter.api.Test;
+import org.opensearch.sql.util.RequiresCapability;
public class TextFunctionIT extends PPLIntegTestCase {
@Override
@@ -78,6 +80,7 @@ void verifyRegexQuery(String pattern, Boolean outputRow1, Boolean outputRow2, Bo
}
@Test
+ @RequiresCapability(FUNCTION_TYPE_COMPAT)
public void testRegexp() throws IOException {
if (isCalciteEnabled()) {
verifyRegexQuery("hello", true, false, true);
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/AggregationIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/AggregationIT.java
index 0966c63e0d..66122db4aa 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/AggregationIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/AggregationIT.java
@@ -7,6 +7,9 @@
import static org.opensearch.sql.legacy.TestsConstants.*;
import static org.opensearch.sql.legacy.plugin.RestSqlAction.QUERY_API_ENDPOINT;
+import static org.opensearch.sql.util.Capability.FILTERED_AGGREGATE;
+import static org.opensearch.sql.util.Capability.FUNCTION_TYPE_COMPAT;
+import static org.opensearch.sql.util.Capability.PERCENTILE_APPROXIMATE;
import static org.opensearch.sql.util.MatcherUtils.rows;
import static org.opensearch.sql.util.MatcherUtils.schema;
import static org.opensearch.sql.util.MatcherUtils.verify;
@@ -26,6 +29,7 @@
import org.opensearch.client.RequestOptions;
import org.opensearch.client.Response;
import org.opensearch.sql.legacy.SQLIntegTestCase;
+import org.opensearch.sql.util.RequiresCapability;
public class AggregationIT extends SQLIntegTestCase {
@Override
@@ -37,6 +41,7 @@ protected void init() throws Exception {
}
@Test
+ @RequiresCapability(FILTERED_AGGREGATE)
public void testFilteredAggregatePushDown() throws IOException {
JSONObject response =
executeQuery("SELECT COUNT(*) FILTER(WHERE age > 35) FROM " + TEST_INDEX_BANK);
@@ -45,6 +50,7 @@ public void testFilteredAggregatePushDown() throws IOException {
}
@Test
+ @RequiresCapability(FILTERED_AGGREGATE)
public void testFilteredAggregateNotPushDown() throws IOException {
JSONObject response =
executeQuery(
@@ -221,6 +227,7 @@ public void testPushDownAggregationOnNullNumericValuesReturnsNull() throws IOExc
}
@Test
+ @RequiresCapability(FUNCTION_TYPE_COMPAT)
public void testPushDownAggregationOnNullDateTimeValuesFromTableReturnsNull() throws IOException {
var response =
executeQuery(
@@ -236,6 +243,7 @@ public void testPushDownAggregationOnNullDateTimeValuesFromTableReturnsNull() th
}
@Test
+ @RequiresCapability(FUNCTION_TYPE_COMPAT)
public void testPushDownAggregationOnNullDateValuesReturnsNull() throws IOException {
var response =
executeQuery(
@@ -252,6 +260,7 @@ public void testPushDownAggregationOnNullDateValuesReturnsNull() throws IOExcept
}
@Test
+ @RequiresCapability(FUNCTION_TYPE_COMPAT)
public void testPushDownAggregationOnNullTimeValuesReturnsNull() throws IOException {
var response =
executeQuery(
@@ -268,6 +277,7 @@ public void testPushDownAggregationOnNullTimeValuesReturnsNull() throws IOExcept
}
@Test
+ @RequiresCapability(FUNCTION_TYPE_COMPAT)
public void testPushDownAggregationOnNullTimeStampValuesReturnsNull() throws IOException {
var response =
executeQuery(
@@ -284,6 +294,7 @@ public void testPushDownAggregationOnNullTimeStampValuesReturnsNull() throws IOE
}
@Test
+ @RequiresCapability(FUNCTION_TYPE_COMPAT)
public void testPushDownAggregationOnNullDateTimeValuesReturnsNull() throws IOException {
var response =
executeQuery(
@@ -473,6 +484,7 @@ public void testMaxDatePushedDown() throws IOException {
}
@Test
+ @RequiresCapability(FUNCTION_TYPE_COMPAT)
public void testAvgDatePushedDown() throws IOException {
var response = executeQuery(String.format("SELECT avg(date0)" + " from %s", TEST_INDEX_CALCS));
verifySchema(response, schema("avg(date0)", null, "date"));
@@ -500,6 +512,7 @@ public void testMaxDateTimePushedDown() throws IOException {
}
@Test
+ @RequiresCapability(FUNCTION_TYPE_COMPAT)
public void testAvgDateTimePushedDown() throws IOException {
var response =
executeQuery(
@@ -524,6 +537,7 @@ public void testMaxTimePushedDown() throws IOException {
}
@Test
+ @RequiresCapability(FUNCTION_TYPE_COMPAT)
public void testAvgTimePushedDown() throws IOException {
var response = executeQuery(String.format("SELECT avg(time1)" + " from %s", TEST_INDEX_CALCS));
verifySchema(response, schema("avg(time1)", null, "time"));
@@ -551,6 +565,7 @@ public void testMaxTimeStampPushedDown() throws IOException {
}
@Test
+ @RequiresCapability(FUNCTION_TYPE_COMPAT)
public void testAvgTimeStampPushedDown() throws IOException {
var response =
executeQuery(
@@ -581,6 +596,7 @@ public void testMaxDateInMemory() throws IOException {
}
@Test
+ @RequiresCapability(FUNCTION_TYPE_COMPAT)
public void testAvgDateInMemory() throws IOException {
var response =
executeQuery(
@@ -625,6 +641,7 @@ public void testMaxDateTimeInMemory() throws IOException {
}
@Test
+ @RequiresCapability(FUNCTION_TYPE_COMPAT)
public void testAvgDateTimeInMemory() throws IOException {
var response =
executeQuery(
@@ -662,6 +679,7 @@ public void testMaxTimeInMemory() throws IOException {
}
@Test
+ @RequiresCapability(FUNCTION_TYPE_COMPAT)
public void testAvgTimeInMemory() throws IOException {
var response =
executeQuery(
@@ -702,6 +720,7 @@ public void testMaxTimeStampInMemory() throws IOException {
}
@Test
+ @RequiresCapability(FUNCTION_TYPE_COMPAT)
public void testAvgTimeStampInMemory() throws IOException {
var response =
executeQuery(
@@ -725,6 +744,7 @@ public void testPercentilePushedDown() throws IOException {
}
@Test
+ @RequiresCapability(FILTERED_AGGREGATE)
public void testFilteredPercentilePushDown() throws IOException {
JSONObject response =
executeQuery(
@@ -735,6 +755,7 @@ public void testFilteredPercentilePushDown() throws IOException {
}
@Test
+ @RequiresCapability(PERCENTILE_APPROXIMATE)
public void testPercentileGroupByPushDown() throws IOException {
var response =
executeQuery(
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/ComplexTimestampQueryIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/ComplexTimestampQueryIT.java
index c0eb800c10..bb33ab891a 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/ComplexTimestampQueryIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/ComplexTimestampQueryIT.java
@@ -7,6 +7,8 @@
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_DATE_TIME;
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_DATE_TIME_NESTED;
+import static org.opensearch.sql.util.Capability.ID_METADATA;
+import static org.opensearch.sql.util.Capability.NESTED_FIELDS;
import java.io.IOException;
import java.util.Locale;
@@ -16,6 +18,7 @@
import org.junit.Ignore;
import org.junit.Test;
import org.opensearch.sql.legacy.SQLIntegTestCase;
+import org.opensearch.sql.util.RequiresCapability;
public class ComplexTimestampQueryIT extends SQLIntegTestCase {
@Override
@@ -26,6 +29,7 @@ protected void init() throws Exception {
/** See: 3159 */
@Test
+ @RequiresCapability(ID_METADATA)
public void joinWithTimestampFieldsSchema() throws IOException {
String query =
String.format(
@@ -100,6 +104,7 @@ public void nonJoinTimestampComparison() throws IOException {
/** See: 1545 */
@Test
+ @RequiresCapability(NESTED_FIELDS)
public void selectDatetimeWithNested() throws IOException {
String query =
String.format(
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/ConditionalIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/ConditionalIT.java
index 05e6af5acb..88c1bd54ce 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/ConditionalIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/ConditionalIT.java
@@ -11,6 +11,7 @@
import static org.opensearch.sql.data.model.ExprValueUtils.LITERAL_TRUE;
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_ACCOUNT;
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_BANK_WITH_NULL_VALUES;
+import static org.opensearch.sql.util.Capability.UNTYPED_NULL_LITERAL;
import static org.opensearch.sql.util.MatcherUtils.hitAny;
import static org.opensearch.sql.util.MatcherUtils.kvInt;
import static org.opensearch.sql.util.MatcherUtils.rows;
@@ -32,6 +33,7 @@
import org.opensearch.core.xcontent.XContentParser;
import org.opensearch.search.SearchHits;
import org.opensearch.sql.legacy.SQLIntegTestCase;
+import org.opensearch.sql.util.RequiresCapability;
public class ConditionalIT extends SQLIntegTestCase {
@@ -51,6 +53,7 @@ public void ifnullShouldPassJDBC() throws IOException {
}
@Test
+ @RequiresCapability(UNTYPED_NULL_LITERAL)
public void ifnullWithNullInputTest() {
JSONObject response =
new JSONObject(
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/CsvFormatIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/CsvFormatIT.java
index d400ad646f..34850e7e5b 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/CsvFormatIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/CsvFormatIT.java
@@ -7,6 +7,7 @@
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_BANK_CSV_SANITIZE;
import static org.opensearch.sql.protocol.response.format.CsvResponseFormatter.CONTENT_TYPE;
+import static org.opensearch.sql.util.Capability.RESPONSE_FORMAT;
import static org.opensearch.sql.util.TestUtils.assertRowsEqual;
import java.io.IOException;
@@ -16,7 +17,9 @@
import org.opensearch.client.Response;
import org.opensearch.sql.common.utils.StringUtils;
import org.opensearch.sql.legacy.SQLIntegTestCase;
+import org.opensearch.sql.util.RequiresCapability;
+@RequiresCapability(RESPONSE_FORMAT)
public class CsvFormatIT extends SQLIntegTestCase {
@Override
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFormatsIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFormatsIT.java
index a24775a975..1e44a62fa2 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFormatsIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFormatsIT.java
@@ -8,6 +8,7 @@
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_DATATYPE_NONNUMERIC;
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_DATE_FORMATS;
import static org.opensearch.sql.legacy.plugin.RestSqlAction.QUERY_API_ENDPOINT;
+import static org.opensearch.sql.util.Capability.DATETIME_FORMAT_RENDERING;
import static org.opensearch.sql.util.MatcherUtils.rows;
import static org.opensearch.sql.util.MatcherUtils.schema;
import static org.opensearch.sql.util.MatcherUtils.verifyDataRows;
@@ -23,6 +24,7 @@
import org.opensearch.client.RequestOptions;
import org.opensearch.client.Response;
import org.opensearch.sql.legacy.SQLIntegTestCase;
+import org.opensearch.sql.util.RequiresCapability;
public class DateTimeFormatsIT extends SQLIntegTestCase {
@@ -34,6 +36,7 @@ public void init() throws Exception {
}
@Test
+ @RequiresCapability(DATETIME_FORMAT_RENDERING)
public void testReadingDateFormats() throws IOException {
String query =
String.format(
@@ -50,6 +53,7 @@ public void testReadingDateFormats() throws IOException {
}
@Test
+ @RequiresCapability(DATETIME_FORMAT_RENDERING)
public void testDateFormatsWithOr() throws IOException {
String query =
String.format("SELECT yyyy-MM-dd_OR_epoch_millis FROM %s", TEST_INDEX_DATE_FORMATS);
@@ -153,6 +157,7 @@ public void testDateNanosWithFormats() {
@Test
@SneakyThrows
+ @RequiresCapability(DATETIME_FORMAT_RENDERING)
public void testDateNanosWithFunctions() {
// in memory funcs
String query =
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java
index e5132eb02f..2435256fcb 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java
@@ -8,6 +8,8 @@
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_BANK;
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_CALCS;
import static org.opensearch.sql.legacy.plugin.RestSqlAction.QUERY_API_ENDPOINT;
+import static org.opensearch.sql.util.Capability.DATETIME_FORMAT_RENDERING;
+import static org.opensearch.sql.util.Capability.FUNCTION_TYPE_COMPAT;
import static org.opensearch.sql.util.MatcherUtils.rows;
import static org.opensearch.sql.util.MatcherUtils.schema;
import static org.opensearch.sql.util.MatcherUtils.verifyDataRows;
@@ -31,6 +33,7 @@
import org.opensearch.client.ResponseException;
import org.opensearch.sql.common.utils.StringUtils;
import org.opensearch.sql.legacy.SQLIntegTestCase;
+import org.opensearch.sql.util.RequiresCapability;
public class DateTimeFunctionIT extends SQLIntegTestCase {
@@ -1170,6 +1173,7 @@ void verifyDateFormat(String date, String type, String format, String formatted)
}
@Test
+ @RequiresCapability(DATETIME_FORMAT_RENDERING)
public void testDateFormat() throws IOException {
String timestamp = "1998-01-31 13:14:15.012345";
String timestampFormat =
@@ -1397,6 +1401,7 @@ protected JSONObject executeQuery(String query) throws IOException {
}
@Test
+ @RequiresCapability(FUNCTION_TYPE_COMPAT)
public void testDateStringAsTimestamp() throws IOException {
JSONObject result = executeQuery("select {timestamp '2025-07-10'} as t");
verifySchema(result, schema("{timestamp '2025-07-10'}", "t", "timestamp"));
@@ -1404,6 +1409,7 @@ public void testDateStringAsTimestamp() throws IOException {
}
@Test
+ @RequiresCapability(FUNCTION_TYPE_COMPAT)
public void testTimestampBracket() throws IOException {
JSONObject result = executeQuery("select {timestamp '2020-09-16 17:30:00'}");
verifySchema(result, schema("{timestamp '2020-09-16 17:30:00'}", null, "timestamp"));
@@ -1423,6 +1429,7 @@ public void testTimestampBracket() throws IOException {
}
@Test
+ @RequiresCapability(FUNCTION_TYPE_COMPAT)
public void testTimeBracket() throws IOException {
JSONObject result = executeQuery("select {time '17:30:00'}");
verifySchema(result, schema("{time '17:30:00'}", null, "time"));
@@ -1461,6 +1468,7 @@ private void compareBrackets(String query1, String query2, String timestamp) thr
}
@Test
+ @RequiresCapability(FUNCTION_TYPE_COMPAT)
public void testBracketedEquivalent() throws IOException {
compareBrackets("timestamp", "timestamp", "2020-09-16 17:30:00");
compareBrackets("timestamp", "ts", "2020-09-16 17:30:00");
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/ExistsPushdownIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/ExistsPushdownIT.java
index 08ceb8c35f..c3a6a4c5ea 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/ExistsPushdownIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/ExistsPushdownIT.java
@@ -5,12 +5,15 @@
package org.opensearch.sql.sql;
+import static org.opensearch.sql.util.Capability.LUCENE_PUSHDOWN_EXPLAIN;
+
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.junit.Test;
import org.opensearch.sql.legacy.SQLIntegTestCase;
import org.opensearch.sql.legacy.TestsConstants;
+import org.opensearch.sql.util.RequiresCapability;
/**
* Explain-plan integration tests asserting that {@code IS NOT NULL} / {@code IS NULL} predicates
@@ -22,6 +25,7 @@
* with a single {@code must_not[exists]} child for {@code IS NULL}. This matches what downstream
* tooling, serverless / AOSS, and the Calcite path already produce.
*/
+@RequiresCapability(LUCENE_PUSHDOWN_EXPLAIN)
public class ExistsPushdownIT extends SQLIntegTestCase {
// Anchored on the surrounding `sourceBuilder=...`, `pitId=` tokens in OpenSearchRequest's
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/GeopointFormatsIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/GeopointFormatsIT.java
index 68dc9a18f3..fc79618fc0 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/GeopointFormatsIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/GeopointFormatsIT.java
@@ -5,6 +5,7 @@
package org.opensearch.sql.sql;
+import static org.opensearch.sql.util.Capability.GEOPOINT_TYPE;
import static org.opensearch.sql.util.MatcherUtils.rows;
import static org.opensearch.sql.util.MatcherUtils.schema;
import static org.opensearch.sql.util.MatcherUtils.verifyDataRows;
@@ -17,6 +18,7 @@
import org.json.JSONObject;
import org.junit.jupiter.api.Test;
import org.opensearch.sql.legacy.SQLIntegTestCase;
+import org.opensearch.sql.util.RequiresCapability;
public class GeopointFormatsIT extends SQLIntegTestCase {
@@ -26,6 +28,7 @@ public void init() throws Exception {
}
@Test
+ @RequiresCapability(GEOPOINT_TYPE)
public void testReadingGeopoints() throws IOException {
String query = String.format("SELECT point FROM %s LIMIT 5", Index.GEOPOINTS.getName());
JSONObject result = executeJdbcRequest(query);
@@ -41,6 +44,7 @@ public void testReadingGeopoints() throws IOException {
public static final double TOLERANCE = 1E-5;
+ @RequiresCapability(GEOPOINT_TYPE)
public void testReadingGeoHash() throws IOException {
String query = String.format("SELECT point FROM %s WHERE _id='6'", Index.GEOPOINTS.getName());
JSONObject result = executeJdbcRequest(query);
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/HighlightFunctionIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/HighlightFunctionIT.java
index d0f890526b..245b87f0d4 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/HighlightFunctionIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/HighlightFunctionIT.java
@@ -5,6 +5,7 @@
package org.opensearch.sql.sql;
+import static org.opensearch.sql.util.Capability.FULLTEXT_RELEVANCE_FUNC;
import static org.opensearch.sql.util.MatcherUtils.rows;
import static org.opensearch.sql.util.MatcherUtils.schema;
import static org.opensearch.sql.util.MatcherUtils.verifyDataRows;
@@ -17,7 +18,9 @@
import org.junit.Test;
import org.opensearch.sql.legacy.SQLIntegTestCase;
import org.opensearch.sql.legacy.TestsConstants;
+import org.opensearch.sql.util.RequiresCapability;
+@RequiresCapability(FULLTEXT_RELEVANCE_FUNC)
public class HighlightFunctionIT extends SQLIntegTestCase {
@Override
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/IdentifierIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/IdentifierIT.java
index ce866dc3bd..50ddc0324d 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/IdentifierIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/IdentifierIT.java
@@ -5,6 +5,8 @@
package org.opensearch.sql.sql;
+import static org.opensearch.sql.util.Capability.IDENTIFIER_RESOLUTION;
+import static org.opensearch.sql.util.Capability.ID_METADATA;
import static org.opensearch.sql.util.MatcherUtils.rows;
import static org.opensearch.sql.util.MatcherUtils.schema;
import static org.opensearch.sql.util.MatcherUtils.verifyDataRows;
@@ -17,6 +19,7 @@
import org.junit.jupiter.api.Test;
import org.opensearch.client.Request;
import org.opensearch.sql.legacy.SQLIntegTestCase;
+import org.opensearch.sql.util.RequiresCapability;
/** Integration tests for identifiers including index and field name symbol. */
public class IdentifierIT extends SQLIntegTestCase {
@@ -56,6 +59,7 @@ public void testSpecialFieldName() throws IOException {
}
@Test
+ @RequiresCapability(IDENTIFIER_RESOLUTION)
public void testMultipleQueriesWithSpecialIndexNames() throws IOException {
createIndexWithOneDoc("test.one", "test.two");
queryAndAssertTheDoc("SELECT * FROM test.one");
@@ -63,6 +67,7 @@ public void testMultipleQueriesWithSpecialIndexNames() throws IOException {
}
@Test
+ @RequiresCapability(IDENTIFIER_RESOLUTION)
public void testDoubleUnderscoreIdentifierTest() throws IOException {
new Index("test.twounderscores").addDoc("{\"__age\": 30}");
final JSONObject result =
@@ -73,6 +78,7 @@ public void testDoubleUnderscoreIdentifierTest() throws IOException {
}
@Test
+ @RequiresCapability(ID_METADATA)
public void testMetafieldIdentifierTest() throws IOException {
// create an index, but the contents doesn't matter
String id = "12345";
@@ -94,6 +100,7 @@ public void testMetafieldIdentifierTest() throws IOException {
}
@Test
+ @RequiresCapability(ID_METADATA)
public void testMetafieldIdentifierRoutingSelectTest() throws IOException {
// create an index, but the contents doesn't really matter
String index = "test.routing_select";
@@ -132,6 +139,7 @@ public void testMetafieldIdentifierRoutingSelectTest() throws IOException {
}
@Test
+ @RequiresCapability(ID_METADATA)
public void testMetafieldIdentifierRoutingFilterTest() throws IOException {
// create an index, but the contents doesn't really matter
String index = "test.routing_filter";
@@ -172,6 +180,7 @@ public void testMetafieldIdentifierRoutingFilterTest() throws IOException {
}
@Test
+ @RequiresCapability(ID_METADATA)
public void testMetafieldIdentifierWithAliasTest() throws IOException {
// create an index, but the contents doesn't matter
String id = "99999";
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/LegacyAPICompatibilityIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/LegacyAPICompatibilityIT.java
index 155d9002ae..de80455558 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/LegacyAPICompatibilityIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/LegacyAPICompatibilityIT.java
@@ -7,6 +7,7 @@
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_ACCOUNT;
import static org.opensearch.sql.plugin.rest.RestQuerySettingsAction.SETTINGS_API_ENDPOINT;
+import static org.opensearch.sql.util.Capability.PAGINATION_CURSOR;
import java.io.IOException;
import org.json.JSONObject;
@@ -17,6 +18,7 @@
import org.opensearch.client.Response;
import org.opensearch.sql.legacy.SQLIntegTestCase;
import org.opensearch.sql.legacy.utils.StringUtils;
+import org.opensearch.sql.util.RequiresCapability;
/** For backward compatibility, check if legacy API endpoints are accessible. */
public class LegacyAPICompatibilityIT extends SQLIntegTestCase {
@@ -50,6 +52,7 @@ public void explain() {
}
@Test
+ @RequiresCapability(PAGINATION_CURSOR)
public void closeCursor() throws IOException {
String sql =
StringUtils.format("SELECT firstname FROM %s WHERE balance > 100", TEST_INDEX_ACCOUNT);
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/LikeQueryIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/LikeQueryIT.java
index 118dd9849b..6e5451192d 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/LikeQueryIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/LikeQueryIT.java
@@ -6,6 +6,7 @@
package org.opensearch.sql.sql;
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_WILDCARD;
+import static org.opensearch.sql.util.Capability.TEXT_KEYWORD_PUSHDOWN_REWRITE;
import static org.opensearch.sql.util.MatcherUtils.rows;
import static org.opensearch.sql.util.MatcherUtils.verifyDataRows;
@@ -13,6 +14,7 @@
import org.json.JSONObject;
import org.junit.Test;
import org.opensearch.sql.legacy.SQLIntegTestCase;
+import org.opensearch.sql.util.RequiresCapability;
public class LikeQueryIT extends SQLIntegTestCase {
@Override
@@ -145,6 +147,7 @@ public void test_like_on_text_field_with_greater_than_one_word() throws IOExcept
}
@Test
+ @RequiresCapability(TEXT_KEYWORD_PUSHDOWN_REWRITE)
public void test_convert_field_text_to_keyword() throws IOException {
String query = "SELECT * FROM " + TEST_INDEX_WILDCARD + " WHERE TextKeywordBody LIKE '*'";
String result = explainQuery(query);
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/MatchIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/MatchIT.java
index 5bde838e19..68f6a0070f 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/MatchIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/MatchIT.java
@@ -7,6 +7,8 @@
import static org.hamcrest.Matchers.containsString;
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_ACCOUNT;
+import static org.opensearch.sql.util.Capability.FULLTEXT_RELEVANCE_FUNC;
+import static org.opensearch.sql.util.Capability.QUERY_ERROR_MESSAGE;
import static org.opensearch.sql.util.MatcherUtils.rows;
import static org.opensearch.sql.util.MatcherUtils.schema;
import static org.opensearch.sql.util.MatcherUtils.verifyDataRows;
@@ -20,6 +22,7 @@
import org.opensearch.sql.legacy.SQLIntegTestCase;
import org.opensearch.sql.legacy.TestsConstants;
import org.opensearch.sql.legacy.utils.StringUtils;
+import org.opensearch.sql.util.RequiresCapability;
public class MatchIT extends SQLIntegTestCase {
@Override
@@ -46,6 +49,7 @@ public void match_in_having() throws IOException {
}
@Test
+ @RequiresCapability(QUERY_ERROR_MESSAGE)
public void missing_field_test() {
String query =
StringUtils.format("SELECT * FROM %s WHERE match(invalid, 'Bates')", TEST_INDEX_ACCOUNT);
@@ -61,6 +65,7 @@ public void missing_field_test() {
}
@Test
+ @RequiresCapability(QUERY_ERROR_MESSAGE)
public void missing_quoted_field_test() {
String query =
StringUtils.format("SELECT * FROM %s WHERE match('invalid', 'Bates')", TEST_INDEX_ACCOUNT);
@@ -76,6 +81,7 @@ public void missing_quoted_field_test() {
}
@Test
+ @RequiresCapability(QUERY_ERROR_MESSAGE)
public void missing_backtick_field_test() {
String query =
StringUtils.format("SELECT * FROM %s WHERE match(`invalid`, 'Bates')", TEST_INDEX_ACCOUNT);
@@ -182,6 +188,7 @@ public void match_alternate_syntaxes_return_the_same_results() throws IOExceptio
}
@Test
+ @RequiresCapability(FULLTEXT_RELEVANCE_FUNC)
public void matchPhraseQueryTest() throws IOException {
final String result =
explainQuery(
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/MathematicalFunctionIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/MathematicalFunctionIT.java
index b7f2ced5fb..d345643a89 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/MathematicalFunctionIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/MathematicalFunctionIT.java
@@ -7,6 +7,7 @@
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_BANK;
import static org.opensearch.sql.legacy.plugin.RestSqlAction.QUERY_API_ENDPOINT;
+import static org.opensearch.sql.util.Capability.FUNCTION_TYPE_COMPAT;
import static org.opensearch.sql.util.MatcherUtils.rows;
import static org.opensearch.sql.util.MatcherUtils.schema;
import static org.opensearch.sql.util.MatcherUtils.verifyDataRows;
@@ -22,6 +23,7 @@
import org.opensearch.client.RequestOptions;
import org.opensearch.client.Response;
import org.opensearch.sql.legacy.SQLIntegTestCase;
+import org.opensearch.sql.util.RequiresCapability;
public class MathematicalFunctionIT extends SQLIntegTestCase {
@@ -40,6 +42,7 @@ public void testPI() throws IOException {
}
@Test
+ @RequiresCapability(FUNCTION_TYPE_COMPAT)
public void testCeil() throws IOException {
JSONObject result = executeQuery("select ceil(0)");
verifySchema(result, schema("ceil(0)", null, "long"));
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/MultiMatchIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/MultiMatchIT.java
index 0bc091b0d2..1bb40b41c8 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/MultiMatchIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/MultiMatchIT.java
@@ -6,6 +6,7 @@
package org.opensearch.sql.sql;
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_BEER;
+import static org.opensearch.sql.util.Capability.FULLTEXT_RELEVANCE_FUNC;
import static org.opensearch.sql.util.MatcherUtils.rows;
import static org.opensearch.sql.util.MatcherUtils.verifyDataRows;
@@ -13,6 +14,7 @@
import org.json.JSONObject;
import org.junit.Test;
import org.opensearch.sql.legacy.SQLIntegTestCase;
+import org.opensearch.sql.util.RequiresCapability;
public class MultiMatchIT extends SQLIntegTestCase {
@Override
@@ -53,6 +55,7 @@ public void test_all_params() {
}
@Test
+ @RequiresCapability(FULLTEXT_RELEVANCE_FUNC)
public void verify_wildcard_test() {
String query1 = "SELECT Id FROM " + TEST_INDEX_BEER + " WHERE multi_match(['Tags'], 'taste')";
JSONObject result1 = executeJdbcRequest(query1);
@@ -141,6 +144,7 @@ public void test_all_params_multimatchquery_alternate_parameter_syntax() {
}
@Test
+ @RequiresCapability(FULLTEXT_RELEVANCE_FUNC)
public void multi_match_alternate_syntax() throws IOException {
String query =
"SELECT Id FROM " + TEST_INDEX_BEER + " WHERE CreationDate = multi_match('2014-01-22');";
@@ -149,6 +153,7 @@ public void multi_match_alternate_syntax() throws IOException {
}
@Test
+ @RequiresCapability(FULLTEXT_RELEVANCE_FUNC)
public void multimatch_alternate_syntax() throws IOException {
String query =
"SELECT Id FROM " + TEST_INDEX_BEER + " WHERE CreationDate = multimatch('2014-01-22');";
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/NestedIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/NestedIT.java
index 18d93dbb2a..3bf6ba72a7 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/NestedIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/NestedIT.java
@@ -10,6 +10,7 @@
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_NESTED_TYPE;
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_NESTED_TYPE_WITHOUT_ARRAYS;
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_NESTED_WITH_NULLS;
+import static org.opensearch.sql.util.Capability.NESTED_FIELDS;
import static org.opensearch.sql.util.MatcherUtils.rows;
import static org.opensearch.sql.util.MatcherUtils.schema;
import static org.opensearch.sql.util.MatcherUtils.verifyDataRows;
@@ -27,7 +28,9 @@
import org.junit.Test;
import org.junit.jupiter.api.Disabled;
import org.opensearch.sql.legacy.SQLIntegTestCase;
+import org.opensearch.sql.util.RequiresCapability;
+@RequiresCapability(NESTED_FIELDS)
public class NestedIT extends SQLIntegTestCase {
@Override
public void init() throws IOException {
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/NullLiteralIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/NullLiteralIT.java
index f885b6d4e0..854cae2837 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/NullLiteralIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/NullLiteralIT.java
@@ -5,6 +5,7 @@
package org.opensearch.sql.sql;
+import static org.opensearch.sql.util.Capability.UNTYPED_NULL_LITERAL;
import static org.opensearch.sql.util.MatcherUtils.rows;
import static org.opensearch.sql.util.MatcherUtils.schema;
import static org.opensearch.sql.util.MatcherUtils.verifyDataRows;
@@ -13,6 +14,7 @@
import org.json.JSONObject;
import org.junit.Test;
import org.opensearch.sql.legacy.SQLIntegTestCase;
+import org.opensearch.sql.util.RequiresCapability;
/**
* This manual IT for NULL literal cannot be replaced with comparison test because other database
@@ -22,6 +24,7 @@
public class NullLiteralIT extends SQLIntegTestCase {
@Test
+ @RequiresCapability(UNTYPED_NULL_LITERAL)
public void testNullLiteralSchema() {
verifySchema(
query("SELECT NULL, ABS(NULL), 1 + NULL, NULL + 1.0"),
@@ -32,6 +35,7 @@ public void testNullLiteralSchema() {
}
@Test
+ @RequiresCapability(UNTYPED_NULL_LITERAL)
public void testNullLiteralInOperator() {
verifyDataRows(query("SELECT NULL = NULL, NULL AND TRUE"), rows(null, null));
}
@@ -42,6 +46,7 @@ public void testNullLiteralInFunction() {
}
@Test
+ @RequiresCapability(UNTYPED_NULL_LITERAL)
public void testNullLiteralInInterval() {
verifyDataRows(
query("SELECT INTERVAL NULL DAY, INTERVAL 60 * 60 * 24 * (NULL - FLOOR(NULL)) SECOND"),
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/PaginationBlackboxIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/PaginationBlackboxIT.java
index 84289d8f57..02a627c72c 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/PaginationBlackboxIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/PaginationBlackboxIT.java
@@ -5,6 +5,8 @@
package org.opensearch.sql.sql;
+import static org.opensearch.sql.util.Capability.PAGINATION_CURSOR;
+
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import java.io.IOException;
@@ -17,10 +19,12 @@
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator;
import org.opensearch.sql.legacy.SQLIntegTestCase;
+import org.opensearch.sql.util.RequiresCapability;
import org.opensearch.sql.util.TestUtils;
// This class has only one test case, because it is parametrized and takes significant time
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
+@RequiresCapability(PAGINATION_CURSOR)
public class PaginationBlackboxIT extends SQLIntegTestCase {
private final Index index;
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/PaginationFallbackIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/PaginationFallbackIT.java
index dfb0bb2080..675bbde2c7 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/PaginationFallbackIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/PaginationFallbackIT.java
@@ -7,14 +7,17 @@
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX;
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_ONLINE;
+import static org.opensearch.sql.util.Capability.PAGINATION_CURSOR;
import static org.opensearch.sql.util.TestUtils.verifyIsV1Cursor;
import static org.opensearch.sql.util.TestUtils.verifyIsV2Cursor;
import java.io.IOException;
import org.junit.Test;
import org.opensearch.sql.legacy.SQLIntegTestCase;
+import org.opensearch.sql.util.RequiresCapability;
import org.opensearch.sql.util.TestUtils;
+@RequiresCapability(PAGINATION_CURSOR)
public class PaginationFallbackIT extends SQLIntegTestCase {
@Override
public void init() throws IOException {
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/PaginationFilterIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/PaginationFilterIT.java
index 9a945ec86f..221e67c910 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/PaginationFilterIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/PaginationFilterIT.java
@@ -5,6 +5,8 @@
package org.opensearch.sql.sql;
+import static org.opensearch.sql.util.Capability.PAGINATION_CURSOR;
+
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import java.io.IOException;
@@ -19,6 +21,7 @@
import org.junit.jupiter.api.DisplayNameGenerator;
import org.opensearch.sql.legacy.SQLIntegTestCase;
import org.opensearch.sql.legacy.TestsConstants;
+import org.opensearch.sql.util.RequiresCapability;
/**
* Test pagination with `WHERE` clause using a parametrized test. See constructor {@link
@@ -26,6 +29,7 @@
* #STATEMENT_TO_NUM_OF_PAGES} to see how these parameters are generated.
*/
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
+@RequiresCapability(PAGINATION_CURSOR)
public class PaginationFilterIT extends SQLIntegTestCase {
/**
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/PaginationIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/PaginationIT.java
index 938a5d1fcd..c94a81cd50 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/PaginationIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/PaginationIT.java
@@ -8,6 +8,7 @@
import static org.opensearch.sql.legacy.TestUtils.getResponseBody;
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_CALCS;
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_ONLINE;
+import static org.opensearch.sql.util.Capability.PAGINATION_CURSOR;
import java.io.IOException;
import lombok.SneakyThrows;
@@ -21,8 +22,10 @@
import org.opensearch.client.ResponseException;
import org.opensearch.sql.common.setting.Settings;
import org.opensearch.sql.legacy.SQLIntegTestCase;
+import org.opensearch.sql.util.RequiresCapability;
import org.opensearch.sql.util.TestUtils;
+@RequiresCapability(PAGINATION_CURSOR)
public class PaginationIT extends SQLIntegTestCase {
@Override
public void init() throws IOException {
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/PaginationWindowIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/PaginationWindowIT.java
index 4c387e2c17..a0d6ee5b31 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/PaginationWindowIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/PaginationWindowIT.java
@@ -6,6 +6,7 @@
package org.opensearch.sql.sql;
import static org.opensearch.sql.legacy.TestsConstants.*;
+import static org.opensearch.sql.util.Capability.PAGINATION_CURSOR;
import java.io.IOException;
import java.util.ArrayList;
@@ -15,7 +16,9 @@
import org.junit.Test;
import org.opensearch.client.ResponseException;
import org.opensearch.sql.legacy.SQLIntegTestCase;
+import org.opensearch.sql.util.RequiresCapability;
+@RequiresCapability(PAGINATION_CURSOR)
public class PaginationWindowIT extends SQLIntegTestCase {
@Override
public void init() throws IOException {
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/PreparedStatementIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/PreparedStatementIT.java
index 8200f64b66..0a156c9dba 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/PreparedStatementIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/PreparedStatementIT.java
@@ -5,11 +5,15 @@
package org.opensearch.sql.sql;
+import static org.opensearch.sql.util.Capability.PREPARED_STATEMENT;
+
import org.json.JSONObject;
import org.junit.Test;
import org.opensearch.sql.legacy.SQLIntegTestCase;
import org.opensearch.sql.legacy.TestsConstants;
+import org.opensearch.sql.util.RequiresCapability;
+@RequiresCapability(PREPARED_STATEMENT)
public class PreparedStatementIT extends SQLIntegTestCase {
@Override
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/QueryStringIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/QueryStringIT.java
index 3d4e08b4cd..2e42413b17 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/QueryStringIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/QueryStringIT.java
@@ -6,11 +6,13 @@
package org.opensearch.sql.sql;
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_BEER;
+import static org.opensearch.sql.util.Capability.FULLTEXT_RELEVANCE_FUNC;
import java.io.IOException;
import org.json.JSONObject;
import org.junit.Test;
import org.opensearch.sql.legacy.SQLIntegTestCase;
+import org.opensearch.sql.util.RequiresCapability;
public class QueryStringIT extends SQLIntegTestCase {
@Override
@@ -70,6 +72,7 @@ public void all_params_test() throws IOException {
}
@Test
+ @RequiresCapability(FULLTEXT_RELEVANCE_FUNC)
public void wildcard_test() throws IOException {
String query1 = "SELECT Id FROM " + TEST_INDEX_BEER + " WHERE query_string(['Tags'], 'taste')";
JSONObject result1 = executeJdbcRequest(query1);
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/QueryValidationIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/QueryValidationIT.java
index 2cdfc67d22..9c4df75679 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/QueryValidationIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/QueryValidationIT.java
@@ -8,6 +8,7 @@
import static org.hamcrest.Matchers.is;
import static org.opensearch.core.rest.RestStatus.BAD_REQUEST;
import static org.opensearch.sql.legacy.plugin.RestSqlAction.QUERY_API_ENDPOINT;
+import static org.opensearch.sql.util.Capability.QUERY_ERROR_MESSAGE;
import static org.opensearch.sql.util.MatcherUtils.featureValueOf;
import java.io.IOException;
@@ -22,11 +23,13 @@
import org.opensearch.client.ResponseException;
import org.opensearch.core.rest.RestStatus;
import org.opensearch.sql.legacy.SQLIntegTestCase;
+import org.opensearch.sql.util.RequiresCapability;
/**
* The query validation IT only covers test for error cases that not doable in comparison test. For
* all other tests, comparison test should be favored over manual written test like this.
*/
+@RequiresCapability(QUERY_ERROR_MESSAGE)
public class QueryValidationIT extends SQLIntegTestCase {
@Rule public final ExpectedException exceptionRule = ExpectedException.none();
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/RawFormatIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/RawFormatIT.java
index 0f085a1cde..33f891b22e 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/RawFormatIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/RawFormatIT.java
@@ -7,6 +7,7 @@
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_BANK_RAW_SANITIZE;
import static org.opensearch.sql.protocol.response.format.RawResponseFormatter.CONTENT_TYPE;
+import static org.opensearch.sql.util.Capability.RESPONSE_FORMAT;
import static org.opensearch.sql.util.TestUtils.assertRowsEqual;
import java.io.IOException;
@@ -17,7 +18,9 @@
import org.opensearch.client.Response;
import org.opensearch.sql.common.utils.StringUtils;
import org.opensearch.sql.legacy.SQLIntegTestCase;
+import org.opensearch.sql.util.RequiresCapability;
+@RequiresCapability(RESPONSE_FORMAT)
public class RawFormatIT extends SQLIntegTestCase {
@Override
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/SQLCorrectnessIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/SQLCorrectnessIT.java
index 6056a1c416..72941ee9e0 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/SQLCorrectnessIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/SQLCorrectnessIT.java
@@ -5,6 +5,9 @@
package org.opensearch.sql.sql;
+import static org.opensearch.sql.util.BackendCapabilities.requireCapability;
+import static org.opensearch.sql.util.Capability.UNTYPED_NULL_LITERAL;
+
import com.google.common.io.Resources;
import java.io.IOException;
import java.nio.file.Files;
@@ -27,6 +30,7 @@ protected void init() throws Exception {
@Test
public void runAllTests() throws Exception {
+ requireCapability(UNTYPED_NULL_LITERAL);
verifyQueries(EXPR_TEST_DIR, expr -> "SELECT " + expr);
verifyQueries(QUERY_TEST_DIR, Function.identity());
}
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/ScoreQueryIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/ScoreQueryIT.java
index a1f71dcf6c..4244daf9f3 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/ScoreQueryIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/ScoreQueryIT.java
@@ -6,6 +6,7 @@
package org.opensearch.sql.sql;
import static org.hamcrest.Matchers.containsString;
+import static org.opensearch.sql.util.Capability.FULLTEXT_RELEVANCE_FUNC;
import static org.opensearch.sql.util.MatcherUtils.rows;
import static org.opensearch.sql.util.MatcherUtils.schema;
import static org.opensearch.sql.util.MatcherUtils.verifyDataAddressRows;
@@ -18,7 +19,9 @@
import org.junit.Test;
import org.opensearch.sql.legacy.SQLIntegTestCase;
import org.opensearch.sql.legacy.TestsConstants;
+import org.opensearch.sql.util.RequiresCapability;
+@RequiresCapability(FULLTEXT_RELEVANCE_FUNC)
public class ScoreQueryIT extends SQLIntegTestCase {
@Override
protected void init() throws Exception {
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/SimpleQueryStringIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/SimpleQueryStringIT.java
index 8742dedbc7..05bfa483b6 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/SimpleQueryStringIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/SimpleQueryStringIT.java
@@ -7,6 +7,7 @@
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_BEER;
import static org.opensearch.sql.protocol.response.format.JsonResponseFormatter.CONTENT_TYPE;
+import static org.opensearch.sql.util.Capability.FULLTEXT_RELEVANCE_FUNC;
import java.io.IOException;
import org.json.JSONObject;
@@ -14,6 +15,7 @@
import org.opensearch.client.Request;
import org.opensearch.client.Response;
import org.opensearch.sql.legacy.SQLIntegTestCase;
+import org.opensearch.sql.util.RequiresCapability;
public class SimpleQueryStringIT extends SQLIntegTestCase {
@Override
@@ -63,6 +65,7 @@ public void test_all_params() throws IOException {
}
@Test
+ @RequiresCapability(FULLTEXT_RELEVANCE_FUNC)
public void verify_wildcard_test() throws IOException {
String query1 =
"SELECT Id FROM " + TEST_INDEX_BEER + " WHERE simple_query_string(['Tags'], 'taste')";
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/StandalonePaginationIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/StandalonePaginationIT.java
index 01daded897..4dbc348cb8 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/StandalonePaginationIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/StandalonePaginationIT.java
@@ -9,6 +9,7 @@
import static org.opensearch.sql.executor.QueryType.SQL;
import static org.opensearch.sql.ppl.StandaloneIT.getDataSourceMetadataStorage;
import static org.opensearch.sql.ppl.StandaloneIT.getDataSourceUserRoleHelper;
+import static org.opensearch.sql.util.Capability.PAGINATION_CURSOR;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
@@ -51,9 +52,11 @@
import org.opensearch.sql.planner.physical.PhysicalPlan;
import org.opensearch.sql.storage.DataSourceFactory;
import org.opensearch.sql.util.InternalRestHighLevelClient;
+import org.opensearch.sql.util.RequiresCapability;
import org.opensearch.sql.util.StandaloneModule;
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
+@RequiresCapability(PAGINATION_CURSOR)
public class StandalonePaginationIT extends SQLIntegTestCase {
private QueryService queryService;
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/SystemFunctionIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/SystemFunctionIT.java
index 7129d058c0..b5504b9ecf 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/SystemFunctionIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/SystemFunctionIT.java
@@ -7,12 +7,15 @@
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_DATATYPE_NONNUMERIC;
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_DATATYPE_NUMERIC;
+import static org.opensearch.sql.util.Capability.FUNCTION_TYPE_COMPAT;
+import static org.opensearch.sql.util.Capability.UNTYPED_NULL_LITERAL;
import static org.opensearch.sql.util.MatcherUtils.rows;
import static org.opensearch.sql.util.MatcherUtils.verifyDataRows;
import org.json.JSONObject;
import org.junit.Test;
import org.opensearch.sql.legacy.SQLIntegTestCase;
+import org.opensearch.sql.util.RequiresCapability;
public class SystemFunctionIT extends SQLIntegTestCase {
@@ -23,6 +26,7 @@ protected void init() throws Exception {
}
@Test
+ @RequiresCapability(UNTYPED_NULL_LITERAL)
public void typeof_sql_types() {
JSONObject response =
executeJdbcRequest(
@@ -40,6 +44,7 @@ public void typeof_sql_types() {
}
@Test
+ @RequiresCapability(FUNCTION_TYPE_COMPAT)
public void typeof_opensearch_types() {
JSONObject response =
executeJdbcRequest(
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/TextFunctionIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/TextFunctionIT.java
index 314132fed0..a793be2deb 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/TextFunctionIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/TextFunctionIT.java
@@ -6,6 +6,7 @@
package org.opensearch.sql.sql;
import static org.opensearch.sql.legacy.plugin.RestSqlAction.QUERY_API_ENDPOINT;
+import static org.opensearch.sql.util.Capability.FUNCTION_TYPE_COMPAT;
import static org.opensearch.sql.util.MatcherUtils.rows;
import static org.opensearch.sql.util.MatcherUtils.schema;
import static org.opensearch.sql.util.MatcherUtils.verifyDataRows;
@@ -20,6 +21,7 @@
import org.opensearch.client.RequestOptions;
import org.opensearch.client.Response;
import org.opensearch.sql.legacy.SQLIntegTestCase;
+import org.opensearch.sql.util.RequiresCapability;
public class TextFunctionIT extends SQLIntegTestCase {
@@ -47,6 +49,7 @@ void verifyQueryWithNullOutput(String query, String type) throws IOException {
}
@Test
+ @RequiresCapability(FUNCTION_TYPE_COMPAT)
public void testRegexp() throws IOException {
verifyQuery("'a' regexp 'b'", "integer", 0);
verifyQuery("'a' regexp '.*'", "integer", 1);
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/VectorSearchExecutionIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/VectorSearchExecutionIT.java
index 36e78567d5..401732fff5 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/VectorSearchExecutionIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/VectorSearchExecutionIT.java
@@ -5,6 +5,7 @@
package org.opensearch.sql.sql;
+import static org.opensearch.sql.util.Capability.VECTOR_SEARCH;
import static org.opensearch.sql.util.TestUtils.createIndexByRestClient;
import static org.opensearch.sql.util.TestUtils.isIndexExist;
import static org.opensearch.sql.util.TestUtils.performRequest;
@@ -20,6 +21,7 @@
import org.opensearch.client.Request;
import org.opensearch.client.Response;
import org.opensearch.sql.legacy.SQLIntegTestCase;
+import org.opensearch.sql.util.RequiresCapability;
/**
* Happy-path execution tests for the vectorSearch() SQL table function. These tests run an actual
@@ -31,6 +33,7 @@
* is absent. Run locally against a cluster that has opensearch-knn installed. Provisioning k-NN in
* CI is a separate follow-up.
*/
+@RequiresCapability(VECTOR_SEARCH)
public class VectorSearchExecutionIT extends SQLIntegTestCase {
private static final String TEST_INDEX = "vector_exec_test";
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/VectorSearchExplainIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/VectorSearchExplainIT.java
index 8719189b13..b9efa7e0fb 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/VectorSearchExplainIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/VectorSearchExplainIT.java
@@ -5,6 +5,8 @@
package org.opensearch.sql.sql;
+import static org.opensearch.sql.util.Capability.VECTOR_SEARCH;
+
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
@@ -15,12 +17,14 @@
import org.junit.Test;
import org.opensearch.sql.legacy.SQLIntegTestCase;
import org.opensearch.sql.legacy.TestsConstants;
+import org.opensearch.sql.util.RequiresCapability;
/**
* Explain-plan integration tests for vectorSearch SQL table function. These tests verify DSL
* push-down shape via _explain. They do NOT require the k-NN plugin since _explain only parses and
* plans the query without executing it against a knn index.
*/
+@RequiresCapability(VECTOR_SEARCH)
public class VectorSearchExplainIT extends SQLIntegTestCase {
// Matches WrapperQueryBuilder's base64 payload in explain JSON. The explain output escapes
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/VectorSearchIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/VectorSearchIT.java
index 8ae3167b40..093ea58e48 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/VectorSearchIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/VectorSearchIT.java
@@ -6,6 +6,7 @@
package org.opensearch.sql.sql;
import static org.hamcrest.Matchers.containsString;
+import static org.opensearch.sql.util.Capability.VECTOR_SEARCH;
import java.io.IOException;
import org.junit.Assume;
@@ -15,12 +16,14 @@
import org.opensearch.client.ResponseException;
import org.opensearch.sql.legacy.SQLIntegTestCase;
import org.opensearch.sql.legacy.TestsConstants;
+import org.opensearch.sql.util.RequiresCapability;
/**
* Integration tests for vectorSearch SQL table function — validation and error paths. These tests
* verify that invalid inputs are rejected with clear error messages. Explain-plan DSL shape tests
* live in {@link VectorSearchExplainIT}.
*/
+@RequiresCapability(VECTOR_SEARCH)
public class VectorSearchIT extends SQLIntegTestCase {
@Override
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/VectorSearchSubqueryIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/VectorSearchSubqueryIT.java
index 04346f87a7..2f894dbaed 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/VectorSearchSubqueryIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/VectorSearchSubqueryIT.java
@@ -6,12 +6,14 @@
package org.opensearch.sql.sql;
import static org.hamcrest.Matchers.containsString;
+import static org.opensearch.sql.util.Capability.VECTOR_SEARCH;
import java.io.IOException;
import org.junit.Test;
import org.opensearch.client.ResponseException;
import org.opensearch.sql.legacy.SQLIntegTestCase;
import org.opensearch.sql.legacy.TestsConstants;
+import org.opensearch.sql.util.RequiresCapability;
/**
* Integration tests for vectorSearch() used inside subqueries. Locks in the rejection of outer
@@ -22,6 +24,7 @@
* Uses _explain-only plus error-path queries, so the k-NN plugin is not required — the planner
* validation fires during planning, before any k-NN execution.
*/
+@RequiresCapability(VECTOR_SEARCH)
public class VectorSearchSubqueryIT extends SQLIntegTestCase {
@Override
diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/WindowFunctionIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/WindowFunctionIT.java
index 95c1f7433d..ad248b98d6 100644
--- a/integ-test/src/test/java/org/opensearch/sql/sql/WindowFunctionIT.java
+++ b/integ-test/src/test/java/org/opensearch/sql/sql/WindowFunctionIT.java
@@ -5,6 +5,7 @@
package org.opensearch.sql.sql;
+import static org.opensearch.sql.util.Capability.PERCENTILE_APPROXIMATE;
import static org.opensearch.sql.util.MatcherUtils.rows;
import static org.opensearch.sql.util.MatcherUtils.verifyDataRows;
import static org.opensearch.sql.util.MatcherUtils.verifyDataRowsInOrder;
@@ -13,6 +14,7 @@
import org.junit.Test;
import org.opensearch.sql.legacy.SQLIntegTestCase;
import org.opensearch.sql.legacy.TestsConstants;
+import org.opensearch.sql.util.RequiresCapability;
public class WindowFunctionIT extends SQLIntegTestCase {
@@ -125,6 +127,7 @@ public void testDistinctCountPartition() {
}
@Test
+ @RequiresCapability(PERCENTILE_APPROXIMATE)
public void testPercentileOverNull() {
JSONObject response =
new JSONObject(
@@ -145,6 +148,7 @@ public void testPercentileOverNull() {
}
@Test
+ @RequiresCapability(PERCENTILE_APPROXIMATE)
public void testPercentileOver() {
JSONObject response =
new JSONObject(
@@ -165,6 +169,7 @@ public void testPercentileOver() {
}
@Test
+ @RequiresCapability(PERCENTILE_APPROXIMATE)
public void testPercentilePartition() {
JSONObject response =
new JSONObject(
diff --git a/integ-test/src/test/java/org/opensearch/sql/util/Capability.java b/integ-test/src/test/java/org/opensearch/sql/util/Capability.java
index 3bac06e7fc..1d4067f141 100644
--- a/integ-test/src/test/java/org/opensearch/sql/util/Capability.java
+++ b/integ-test/src/test/java/org/opensearch/sql/util/Capability.java
@@ -499,7 +499,79 @@ public enum Capability {
STREAMSTATS_SORT_NOT_HONORED(
"streamstats computes its window over the backend scan order on the analytics-engine route,"
+ " ignoring a preceding | sort (the OVER clause has no explicit ORDER BY), so the window"
- + " values diverge from the v2/Calcite path which honors the sort.");
+ + " values diverge from the v2/Calcite path which honors the sort."),
+
+ // Capabilities below were migrated from build.gradle analytics-engine excludes (commit 1ccf431).
+ // BACKEND layer: divergence rooted in the AE/DataFusion execution + composite/parquet storage.
+
+ /** BACKEND: kNN/vector search has no analytics-engine (DataFusion) backend. */
+ VECTOR_SEARCH(
+ "Vector/kNN search is unsupported on the analytics-engine route: DataFusion has no kNN"
+ + " backend."),
+
+ /** BACKEND: geo_point fields are not held by the composite/parquet store. */
+ GEOPOINT_TYPE(
+ "geo_point fields are unsupported on the analytics-engine route: the composite/parquet store"
+ + " does not hold the geo_point type."),
+
+ /**
+ * BACKEND: dotted index names and underscore-prefixed identifiers don't resolve on the AE route.
+ */
+ IDENTIFIER_RESOLUTION(
+ "Dotted index names and underscore-prefixed field identifiers don't resolve on the"
+ + " analytics-engine route."),
+
+ // FRONTEND layer: divergence rooted in the Calcite parser/planner replacing the V2 engine.
+
+ /** FRONTEND: CSV/raw/pretty response formatters are not wired in the Calcite path. */
+ RESPONSE_FORMAT(
+ "CSV/raw/pretty response formats are not produced by the Calcite path used by the"
+ + " analytics-engine route."),
+
+ /** FRONTEND: stateful pagination/cursor/PIT is not implemented in the Calcite path. */
+ PAGINATION_CURSOR(
+ "Pagination, cursor, and point-in-time are unsupported on the analytics-engine route: the"
+ + " Calcite path has no stateful cursor."),
+
+ /** FRONTEND: JDBC prepared statements are not implemented in the Calcite path. */
+ PREPARED_STATEMENT(
+ "Prepared statements are unsupported on the analytics-engine route (Calcite path)."),
+
+ /**
+ * FRONTEND: legacy method-query syntax (regexp_query/wildcard_query) is not in the Calcite
+ * grammar.
+ */
+ LEGACY_METHOD_QUERY(
+ "Legacy method-query syntax (regexp_query/wildcard_query/query/matchquery) is not in the"
+ + " Calcite grammar used by the analytics-engine route."),
+
+ /** FRONTEND: error/validation message text differs under the Calcite path. */
+ QUERY_ERROR_MESSAGE(
+ "Query validation and error-message text differ on the analytics-engine route (Calcite"
+ + " produces different wording for the same semantic error)."),
+
+ /** FRONTEND: explain output is a Calcite plan, not the V2 OpenSearch DSL text. */
+ EXPLAIN_FORMAT(
+ "Explain output differs on the analytics-engine route: the Calcite path emits a different"
+ + " plan shape than the V2 OpenSearch DSL text the test asserts."),
+
+ /**
+ * FRONTEND: Calcite function return types/signatures differ from V2 (CEIL, REGEXP, typeof, AVG).
+ */
+ FUNCTION_TYPE_COMPAT(
+ "Function return types and signatures differ on the analytics-engine route: Calcite uses"
+ + " standard SQL types (e.g. CEIL->double, REGEXP->boolean, typeof ANSI names, AVG"
+ + " rejects temporal) where V2 used OpenSearch-specific behavior."),
+
+ /** BACKEND: untyped NULL literal in a no-FROM query can't be serialized to Substrait. */
+ UNTYPED_NULL_LITERAL(
+ "An untyped NULL literal in a no-FROM query (SELECT NULL, NULL in operators/intervals,"
+ + " typeof(NULL)) can't be serialized to Substrait on the analytics-engine route."),
+
+ /** BACKEND: FILTER(WHERE) on aggregates can't be executed via Substrait streaming. */
+ FILTERED_AGGREGATE(
+ "FILTER(WHERE) on aggregates can't be executed on the analytics-engine route: the Substrait"
+ + " streaming path doesn't support filtered aggregates.");
private final String reason;