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 b75da57c57..bd5b928aeb 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 5dea06b763..0b0a510cb3 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 4ad88c632b..a0d74cd597 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 3933338f0a..63d37b3ed6 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 84b60fdabd..bf49f23946 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 7589304af0..4f39b8d4ef 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 aadd79469d..4f64cdb704 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 ab0f196ce3..9c4513a973 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 b4218db6ab..7e4950a5fa 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/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;