From 965bb01dba878210f06c66ff03314bea8fcd9da2 Mon Sep 17 00:00:00 2001 From: Chen Dai Date: Tue, 23 Jun 2026 14:25:38 -0700 Subject: [PATCH 1/2] test(integ-test): gate analytics-engine excludes via @RequiresCapability Migrate the analytics-engine IT exclusions to method/class-level @RequiresCapability annotations so each test self-skips when the analytics engine is active, instead of relying on build.gradle excludes. Add coarse capabilities (backend: vector/geopoint/identifier, untyped NULL literal, filtered aggregate; frontend: response format, pagination/cursor, prepared statement, legacy method query, query error, explain format, function type compat) and reuse existing capabilities where they fit. SQLCorrectnessIT is outside the SQLIntegTestCase hierarchy, so it calls BackendCapabilities.requireCapability directly. Signed-off-by: Chen Dai --- .../sql/legacy/CsvFormatResponseIT.java | 3 + .../org/opensearch/sql/legacy/CursorIT.java | 3 + .../org/opensearch/sql/legacy/JdbcTestIT.java | 6 ++ .../sql/legacy/JoinAliasWriterRuleIT.java | 16 ++++ .../sql/legacy/MalformedQueryIT.java | 4 + .../opensearch/sql/legacy/MethodQueryIT.java | 8 ++ .../sql/legacy/ObjectFieldSelectIT.java | 3 + .../sql/legacy/PointInTimeLeakIT.java | 3 + .../sql/legacy/PrettyFormatResponseIT.java | 16 ++++ .../sql/legacy/SqlLegacyEngineSanityIT.java | 3 + .../sql/ppl/MathematicalFunctionIT.java | 2 + .../opensearch/sql/ppl/SystemFunctionIT.java | 2 + .../opensearch/sql/ppl/TextFunctionIT.java | 3 + .../org/opensearch/sql/sql/AggregationIT.java | 21 ++++++ .../sql/sql/ComplexTimestampQueryIT.java | 5 ++ .../org/opensearch/sql/sql/ConditionalIT.java | 3 + .../org/opensearch/sql/sql/CsvFormatIT.java | 3 + .../opensearch/sql/sql/DateTimeFormatsIT.java | 5 ++ .../sql/sql/DateTimeFunctionIT.java | 8 ++ .../opensearch/sql/sql/ExistsPushdownIT.java | 4 + .../opensearch/sql/sql/GeopointFormatsIT.java | 4 + .../sql/sql/HighlightFunctionIT.java | 3 + .../org/opensearch/sql/sql/IdentifierIT.java | 9 +++ .../sql/sql/LegacyAPICompatibilityIT.java | 3 + .../org/opensearch/sql/sql/LikeQueryIT.java | 3 + .../java/org/opensearch/sql/sql/MatchIT.java | 7 ++ .../sql/sql/MathematicalFunctionIT.java | 3 + .../org/opensearch/sql/sql/MultiMatchIT.java | 5 ++ .../java/org/opensearch/sql/sql/NestedIT.java | 3 + .../org/opensearch/sql/sql/NullLiteralIT.java | 5 ++ .../sql/sql/PaginationBlackboxIT.java | 4 + .../sql/sql/PaginationFallbackIT.java | 3 + .../sql/sql/PaginationFilterIT.java | 4 + .../org/opensearch/sql/sql/PaginationIT.java | 3 + .../sql/sql/PaginationWindowIT.java | 3 + .../sql/sql/PreparedStatementIT.java | 4 + .../org/opensearch/sql/sql/QueryStringIT.java | 3 + .../opensearch/sql/sql/QueryValidationIT.java | 3 + .../org/opensearch/sql/sql/RawFormatIT.java | 3 + .../opensearch/sql/sql/SQLCorrectnessIT.java | 4 + .../org/opensearch/sql/sql/ScoreQueryIT.java | 3 + .../sql/sql/SimpleQueryStringIT.java | 3 + .../sql/sql/StandalonePaginationIT.java | 3 + .../opensearch/sql/sql/SystemFunctionIT.java | 5 ++ .../opensearch/sql/sql/TextFunctionIT.java | 3 + .../sql/sql/VectorSearchExecutionIT.java | 3 + .../sql/sql/VectorSearchExplainIT.java | 4 + .../opensearch/sql/sql/VectorSearchIT.java | 3 + .../sql/sql/VectorSearchSubqueryIT.java | 3 + .../opensearch/sql/sql/WindowFunctionIT.java | 5 ++ .../org/opensearch/sql/util/Capability.java | 74 ++++++++++++++++++- 51 files changed, 308 insertions(+), 1 deletion(-) diff --git a/integ-test/src/test/java/org/opensearch/sql/legacy/CsvFormatResponseIT.java b/integ-test/src/test/java/org/opensearch/sql/legacy/CsvFormatResponseIT.java index b75da57c571..bd5b928aebe 100644 --- a/integ-test/src/test/java/org/opensearch/sql/legacy/CsvFormatResponseIT.java +++ b/integ-test/src/test/java/org/opensearch/sql/legacy/CsvFormatResponseIT.java @@ -20,6 +20,7 @@ import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_NESTED_TYPE; import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_NESTED_WITH_QUOTES; import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_ONLINE; +import static org.opensearch.sql.util.Capability.RESPONSE_FORMAT; import java.io.IOException; import java.util.ArrayList; @@ -39,8 +40,10 @@ import org.opensearch.client.RequestOptions; import org.opensearch.client.Response; import org.opensearch.sql.legacy.executor.csv.CSVResult; +import org.opensearch.sql.util.RequiresCapability; /** Tests to cover requests with "?format=csv" parameter */ +@RequiresCapability(RESPONSE_FORMAT) public class CsvFormatResponseIT extends SQLIntegTestCase { private boolean flatOption = false; diff --git a/integ-test/src/test/java/org/opensearch/sql/legacy/CursorIT.java b/integ-test/src/test/java/org/opensearch/sql/legacy/CursorIT.java index 5dea06b7634..0b0a510cb3d 100644 --- a/integ-test/src/test/java/org/opensearch/sql/legacy/CursorIT.java +++ b/integ-test/src/test/java/org/opensearch/sql/legacy/CursorIT.java @@ -12,6 +12,7 @@ import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_DATE_TIME; import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_NESTED_SIMPLE; import static org.opensearch.sql.legacy.plugin.RestSqlAction.QUERY_API_ENDPOINT; +import static org.opensearch.sql.util.Capability.PAGINATION_CURSOR; import static org.opensearch.sql.util.TestUtils.verifyIsV2Cursor; import java.io.IOException; @@ -27,7 +28,9 @@ import org.opensearch.client.ResponseException; import org.opensearch.sql.common.setting.Settings; import org.opensearch.sql.legacy.utils.StringUtils; +import org.opensearch.sql.util.RequiresCapability; +@RequiresCapability(PAGINATION_CURSOR) public class CursorIT extends SQLIntegTestCase { private static final String CURSOR = "cursor"; diff --git a/integ-test/src/test/java/org/opensearch/sql/legacy/JdbcTestIT.java b/integ-test/src/test/java/org/opensearch/sql/legacy/JdbcTestIT.java index 4ad88c632ba..a0d74cd5977 100644 --- a/integ-test/src/test/java/org/opensearch/sql/legacy/JdbcTestIT.java +++ b/integ-test/src/test/java/org/opensearch/sql/legacy/JdbcTestIT.java @@ -7,6 +7,8 @@ import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; +import static org.opensearch.sql.util.Capability.DATETIME_FORMAT_RENDERING; +import static org.opensearch.sql.util.Capability.PERCENTILE_APPROXIMATE; import java.io.IOException; import org.json.JSONArray; @@ -14,6 +16,7 @@ import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; +import org.opensearch.sql.util.RequiresCapability; public class JdbcTestIT extends SQLIntegTestCase { @@ -25,6 +28,7 @@ protected void init() throws Exception { loadIndex(Index.WEBLOG); } + @RequiresCapability(PERCENTILE_APPROXIMATE) public void testPercentilesQuery() { JSONObject response = executeJdbcRequest( @@ -43,6 +47,7 @@ public void testPercentilesQuery() { // https://github.com/opensearch-project/sql/issues/537 @Test + @RequiresCapability(PERCENTILE_APPROXIMATE) public void testSlowQuery() throws IOException { // set slow log threshold = 0s updateClusterSettings(new ClusterSetting(PERSISTENT, "plugins.sql.slowlog", "0")); @@ -89,6 +94,7 @@ public void testDivisionInQuery() { assertThat(response.getJSONArray("datarows").getJSONArray(0).getDouble(0), equalTo(16827.0)); } + @RequiresCapability(DATETIME_FORMAT_RENDERING) public void testGroupByInQuery() { JSONObject response = executeJdbcRequest( diff --git a/integ-test/src/test/java/org/opensearch/sql/legacy/JoinAliasWriterRuleIT.java b/integ-test/src/test/java/org/opensearch/sql/legacy/JoinAliasWriterRuleIT.java index 3933338f0a6..63d37b3ed6a 100644 --- a/integ-test/src/test/java/org/opensearch/sql/legacy/JoinAliasWriterRuleIT.java +++ b/integ-test/src/test/java/org/opensearch/sql/legacy/JoinAliasWriterRuleIT.java @@ -6,6 +6,8 @@ package org.opensearch.sql.legacy; import static org.hamcrest.Matchers.equalTo; +import static org.opensearch.sql.util.Capability.EXPLAIN_FORMAT; +import static org.opensearch.sql.util.Capability.QUERY_ERROR_MESSAGE; import java.io.IOException; import org.junit.Ignore; @@ -13,6 +15,7 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import org.opensearch.client.ResponseException; +import org.opensearch.sql.util.RequiresCapability; /** Test cases for writing missing join table aliases. */ public class JoinAliasWriterRuleIT extends SQLIntegTestCase { @@ -26,6 +29,7 @@ protected void init() throws Exception { } @Test + @RequiresCapability(EXPLAIN_FORMAT) public void noTableAliasNoCommonColumns() throws IOException { sameExplain( query( @@ -45,6 +49,7 @@ public void noTableAliasNoCommonColumns() throws IOException { } @Test + @RequiresCapability(EXPLAIN_FORMAT) public void oneTableAliasNoCommonColumns() throws IOException { sameExplain( query( @@ -61,6 +66,7 @@ public void oneTableAliasNoCommonColumns() throws IOException { } @Test + @RequiresCapability(EXPLAIN_FORMAT) public void bothTableAliasNoCommonColumns() throws IOException { sameExplain( query( @@ -78,6 +84,7 @@ public void bothTableAliasNoCommonColumns() throws IOException { @Test @Ignore + @RequiresCapability(EXPLAIN_FORMAT) public void tableNamesWithTypeName() throws IOException { sameExplain( query( @@ -98,6 +105,7 @@ public void tableNamesWithTypeName() throws IOException { @Ignore @Test + @RequiresCapability(EXPLAIN_FORMAT) public void tableNamesWithTypeNameExplicitTableAlias() throws IOException { sameExplain( query( @@ -114,6 +122,7 @@ public void tableNamesWithTypeNameExplicitTableAlias() throws IOException { } @Test + @RequiresCapability(EXPLAIN_FORMAT) public void actualTableNameAsAliasOnColumnFields() throws IOException { sameExplain( query( @@ -130,6 +139,7 @@ public void actualTableNameAsAliasOnColumnFields() throws IOException { } @Test + @RequiresCapability(EXPLAIN_FORMAT) public void actualTableNameAsAliasOnColumnFieldsTwo() throws IOException { sameExplain( query( @@ -150,6 +160,7 @@ public void actualTableNameAsAliasOnColumnFieldsTwo() throws IOException { } @Test + @RequiresCapability(EXPLAIN_FORMAT) public void columnsWithTableAliasNotAffected() throws IOException { sameExplain( query( @@ -166,6 +177,7 @@ public void columnsWithTableAliasNotAffected() throws IOException { } @Test + @RequiresCapability(QUERY_ERROR_MESSAGE) public void commonColumnWithoutTableAliasDifferentTables() throws IOException { exception.expect(ResponseException.class); exception.expectMessage("Field name [firstname] is ambiguous"); @@ -179,6 +191,7 @@ public void commonColumnWithoutTableAliasDifferentTables() throws IOException { } @Test + @RequiresCapability(QUERY_ERROR_MESSAGE) public void sameTablesNoAliasAndNoAliasOnColumns() throws IOException { exception.expect(ResponseException.class); exception.expectMessage("Not unique table/alias: [opensearch-sql_test_index_bank]"); @@ -192,6 +205,7 @@ public void sameTablesNoAliasAndNoAliasOnColumns() throws IOException { } @Test + @RequiresCapability(QUERY_ERROR_MESSAGE) public void sameTablesNoAliasWithTableNameAsAliasOnColumns() throws IOException { exception.expect(ResponseException.class); exception.expectMessage("Not unique table/alias: [opensearch-sql_test_index_bank]"); @@ -206,6 +220,7 @@ public void sameTablesNoAliasWithTableNameAsAliasOnColumns() throws IOException } @Test + @RequiresCapability(EXPLAIN_FORMAT) public void sameTablesWithExplicitAliasOnFirst() throws IOException { sameExplain( query( @@ -221,6 +236,7 @@ public void sameTablesWithExplicitAliasOnFirst() throws IOException { } @Test + @RequiresCapability(EXPLAIN_FORMAT) public void sameTablesWithExplicitAliasOnSecond() throws IOException { sameExplain( query( diff --git a/integ-test/src/test/java/org/opensearch/sql/legacy/MalformedQueryIT.java b/integ-test/src/test/java/org/opensearch/sql/legacy/MalformedQueryIT.java index 84b60fdabd7..bf49f239465 100644 --- a/integ-test/src/test/java/org/opensearch/sql/legacy/MalformedQueryIT.java +++ b/integ-test/src/test/java/org/opensearch/sql/legacy/MalformedQueryIT.java @@ -5,6 +5,8 @@ package org.opensearch.sql.legacy; +import static org.opensearch.sql.util.Capability.QUERY_ERROR_MESSAGE; + import java.io.IOException; import java.util.Locale; import org.apache.hc.core5.http.ParseException; @@ -12,8 +14,10 @@ import org.json.JSONObject; import org.junit.Assert; import org.opensearch.client.ResponseException; +import org.opensearch.sql.util.RequiresCapability; /** Tests for clean handling of various types of invalid queries */ +@RequiresCapability(QUERY_ERROR_MESSAGE) public class MalformedQueryIT extends SQLIntegTestCase { @Override protected void init() throws Exception { diff --git a/integ-test/src/test/java/org/opensearch/sql/legacy/MethodQueryIT.java b/integ-test/src/test/java/org/opensearch/sql/legacy/MethodQueryIT.java index 7589304af0a..4f39b8d4efa 100644 --- a/integ-test/src/test/java/org/opensearch/sql/legacy/MethodQueryIT.java +++ b/integ-test/src/test/java/org/opensearch/sql/legacy/MethodQueryIT.java @@ -7,12 +7,15 @@ import static org.hamcrest.Matchers.both; import static org.hamcrest.Matchers.containsString; +import static org.opensearch.sql.util.Capability.EXPLAIN_FORMAT; +import static org.opensearch.sql.util.Capability.LEGACY_METHOD_QUERY; import java.io.IOException; import java.util.Locale; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; +import org.opensearch.sql.util.RequiresCapability; /** * 定製方法查詢. @@ -41,6 +44,7 @@ protected void init() throws Exception { * @throws IOException */ @Test + @RequiresCapability(EXPLAIN_FORMAT) public void queryTest() throws IOException { final String result = explainQuery( @@ -70,6 +74,7 @@ public void queryTest() throws IOException { * @throws IOException */ @Test + @RequiresCapability(EXPLAIN_FORMAT) public void matchQueryTest() throws IOException { final String result = explainQuery( @@ -153,6 +158,7 @@ public void scoreQueryTest() throws IOException { } @Test + @RequiresCapability(LEGACY_METHOD_QUERY) public void regexpQueryTest() throws IOException { final String result = explainQuery( @@ -168,6 +174,7 @@ public void regexpQueryTest() throws IOException { } @Test + @RequiresCapability(LEGACY_METHOD_QUERY) public void negativeRegexpQueryTest() throws IOException { final String result = explainQuery( @@ -198,6 +205,7 @@ public void negativeRegexpQueryTest() throws IOException { * @throws IOException */ @Test + @RequiresCapability(LEGACY_METHOD_QUERY) public void wildcardQueryTest() throws IOException { final String result = explainQuery( diff --git a/integ-test/src/test/java/org/opensearch/sql/legacy/ObjectFieldSelectIT.java b/integ-test/src/test/java/org/opensearch/sql/legacy/ObjectFieldSelectIT.java index aadd79469db..4f64cdb704d 100644 --- a/integ-test/src/test/java/org/opensearch/sql/legacy/ObjectFieldSelectIT.java +++ b/integ-test/src/test/java/org/opensearch/sql/legacy/ObjectFieldSelectIT.java @@ -6,6 +6,7 @@ package org.opensearch.sql.legacy; import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_DEEP_NESTED; +import static org.opensearch.sql.util.Capability.STRUCT_PARENT_FIELD; import static org.opensearch.sql.util.MatcherUtils.rows; import static org.opensearch.sql.util.MatcherUtils.schema; import static org.opensearch.sql.util.MatcherUtils.verifyDataRows; @@ -16,11 +17,13 @@ import org.junit.Test; import org.opensearch.sql.common.setting.Settings; import org.opensearch.sql.legacy.utils.StringUtils; +import org.opensearch.sql.util.RequiresCapability; /** * Integration test for OpenSearch object field (and nested field). This class is focused on simple * SELECT-FROM query to ensure right column number and value is returned. */ +@RequiresCapability(STRUCT_PARENT_FIELD) public class ObjectFieldSelectIT extends SQLIntegTestCase { @Override diff --git a/integ-test/src/test/java/org/opensearch/sql/legacy/PointInTimeLeakIT.java b/integ-test/src/test/java/org/opensearch/sql/legacy/PointInTimeLeakIT.java index ab0f196ce33..9c4513a973a 100644 --- a/integ-test/src/test/java/org/opensearch/sql/legacy/PointInTimeLeakIT.java +++ b/integ-test/src/test/java/org/opensearch/sql/legacy/PointInTimeLeakIT.java @@ -7,6 +7,7 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThan; +import static org.opensearch.sql.util.Capability.PAGINATION_CURSOR; import java.io.IOException; import org.json.JSONArray; @@ -17,12 +18,14 @@ import org.opensearch.client.Response; import org.opensearch.client.ResponseException; import org.opensearch.sql.legacy.utils.StringUtils; +import org.opensearch.sql.util.RequiresCapability; /** * Integration test verifying PIT contexts are created only when needed and properly cleaned up. * * @see Issue #5002 */ +@RequiresCapability(PAGINATION_CURSOR) public class PointInTimeLeakIT extends SQLIntegTestCase { private static final String TEST_INDEX = "test-logs-2025.01.01"; diff --git a/integ-test/src/test/java/org/opensearch/sql/legacy/PrettyFormatResponseIT.java b/integ-test/src/test/java/org/opensearch/sql/legacy/PrettyFormatResponseIT.java index b4218db6abf..7e4950a5fab 100644 --- a/integ-test/src/test/java/org/opensearch/sql/legacy/PrettyFormatResponseIT.java +++ b/integ-test/src/test/java/org/opensearch/sql/legacy/PrettyFormatResponseIT.java @@ -10,6 +10,9 @@ import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; +import static org.opensearch.sql.util.Capability.DYNAMIC_STRING_NO_KEYWORD; +import static org.opensearch.sql.util.Capability.NESTED_FIELDS; +import static org.opensearch.sql.util.Capability.RESPONSE_FORMAT; import com.google.common.collect.Sets; import java.io.IOException; @@ -27,6 +30,7 @@ import org.junit.Ignore; import org.junit.Test; import org.opensearch.client.Request; +import org.opensearch.sql.util.RequiresCapability; /** * @@ -97,6 +101,7 @@ protected Request getSqlRequest(String request, boolean explain) { // This is testing a deprecated feature @Test + @RequiresCapability(RESPONSE_FORMAT) public void wrongIndexType() throws IOException { String type = "wrongType"; try { @@ -167,18 +172,21 @@ public void selectScore() throws IOException { } @Test + @RequiresCapability(NESTED_FIELDS) public void selectAllFromNestedWithoutFieldInFrom() throws IOException { assertNestedFieldQueryResultContainsColumnsAndData( "SELECT * FROM %s", regularFields, fields("message", "comment")); } @Test + @RequiresCapability(NESTED_FIELDS) public void selectAllFromNestedWithFieldInFrom() throws IOException { assertNestedFieldQueryResultContainsColumnsAndData( "SELECT * FROM %s e, e.message m", regularFields, messageFields); } @Test + @RequiresCapability(NESTED_FIELDS) public void selectAllFromNestedWithMultipleFieldsInFrom() throws IOException { assertNestedFieldQueryResultContainsColumnsAndData( "SELECT * FROM %s e, e.message m, e.comment c", @@ -186,12 +194,14 @@ public void selectAllFromNestedWithMultipleFieldsInFrom() throws IOException { } @Test + @RequiresCapability(NESTED_FIELDS) public void selectAllNestedFromNestedWithFieldInFrom() throws IOException { assertNestedFieldQueryResultContainsColumnsAndData( "SELECT m.* FROM %s e, e.message m", messageFields); } @Test + @RequiresCapability(NESTED_FIELDS) public void selectSpecificRegularFieldAndAllFromNestedWithFieldInFrom() throws IOException { assertNestedFieldQueryResultContainsColumnsAndData( "SELECT e.someField, m.* FROM %s e, e.message m", fields("someField"), messageFields); @@ -218,6 +228,7 @@ private Set 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/SqlLegacyEngineSanityIT.java b/integ-test/src/test/java/org/opensearch/sql/legacy/SqlLegacyEngineSanityIT.java index b2d22808a49..1c92cee74a9 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 6df60f68a7b..42f69010270 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 276ab01da4c..00eb26b43dd 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 7fe360d8844..bc1b60eebac 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 0966c63e0d6..66122db4aa9 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 c0eb800c103..bb33ab891a6 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 05e6af5acbc..88c1bd54ce0 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 d400ad646fc..34850e7e5bc 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 a24775a9755..1e44a62fa24 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 e5132eb02f1..2435256fcb5 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 08ceb8c35f9..c3a6a4c5ea3 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 68dc9a18f34..fc79618fc07 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 d0f890526b7..245b87f0d41 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 ce866dc3bdf..50ddc0324d2 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 155d9002aed..de804555587 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 118dd9849b4..6e5451192d8 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 5bde838e190..68f6a0070f7 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 b7f2ced5fbd..d345643a89e 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 0bc091b0d20..1bb40b41c8b 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 18d93dbb2a0..3bf6ba72a78 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 f885b6d4e0d..854cae2837d 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 84289d8f57e..02a627c72c4 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 dfb0bb2080e..675bbde2c7a 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 9a945ec86f5..221e67c910b 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 938a5d1fcd5..c94a81cd50a 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 4c387e2c171..a0d6ee5b318 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 8200f64b668..0a156c9dba5 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 3d4e08b4cdc..2e42413b170 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 2cdfc67d228..9c4df756792 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 0f085a1cdeb..33f891b22e6 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 6056a1c4168..72941ee9e09 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 a1f71dcf6c4..4244daf9f38 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 8742dedbc70..05bfa483b6f 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 01daded897d..4dbc348cb8a 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 7129d058c00..b5504b9ecf1 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 314132fed0a..a793be2debf 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 36e78567d54..401732fff56 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 8719189b13a..b9efa7e0fb4 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 8ae3167b40b..093ea58e489 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 04346f87a76..2f894dbaed2 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 95c1f7433dc..ad248b98d62 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 3bac06e7fca..1d4067f1414 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; From d92e9943e45c0c093b1d9608c9e3195c9d99c8eb Mon Sep 17 00:00:00 2001 From: Chen Dai Date: Thu, 25 Jun 2026 13:19:10 -0700 Subject: [PATCH 2/2] test(integ-test): skip index cleanup when client is null Signed-off-by: Chen Dai --- .../java/org/opensearch/sql/legacy/SQLIntegTestCase.java | 5 +++++ 1 file changed, 5 insertions(+) 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 ef05923b060..05a670de393 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();