This is an automated email from the ASF dual-hosted git repository.
xiangfu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git
The following commit(s) were added to refs/heads/master by this push:
new d4d1f8f9063 Add Multiple Query Requests field into
validateMultiStageQuery API (#16746)
d4d1f8f9063 is described below
commit d4d1f8f90634b34afc6a9d4cf91ef17a92a40a89
Author: Chaitanya Deepthi <[email protected]>
AuthorDate: Fri Sep 5 20:58:39 2025 -0700
Add Multiple Query Requests field into validateMultiStageQuery API (#16746)
* Make the response to take in multiple query inputs
* Change the logs
* Make the api backward compatible
* Change the logs
* Add nullable annotation
---
.../api/resources/PinotQueryResource.java | 96 +++++---
.../tests/MultiStageEngineIntegrationTest.java | 252 ++++++++++++++-------
2 files changed, 235 insertions(+), 113 deletions(-)
diff --git
a/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotQueryResource.java
b/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotQueryResource.java
index a2278d12412..f83a96e63ff 100644
---
a/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotQueryResource.java
+++
b/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotQueryResource.java
@@ -160,54 +160,70 @@ public class PinotQueryResource {
@POST
@Path("validateMultiStageQuery")
- public MultiStageQueryValidationResponse
validateMultiStageQuery(MultiStageQueryValidationRequest request,
+ public List<MultiStageQueryValidationResponse>
validateMultiStageQuery(MultiStageQueryValidationRequest request,
@Context HttpHeaders httpHeaders) {
- String sqlQuery = request.getSql().trim();
- if (request.getSql() == null || sqlQuery.isEmpty()) {
- return new MultiStageQueryValidationResponse(false, "Request is missing
the query string field 'sql'", null);
- }
-
- Map<String, String> queryOptionsMap =
RequestUtils.parseQuery(sqlQuery).getOptions();
- String database =
DatabaseUtils.extractDatabaseFromQueryRequest(queryOptionsMap, httpHeaders);
-
- try {
- TableCache tableCache;
- if (CollectionUtils.isNotEmpty(request.getTableConfigs()) &&
CollectionUtils.isNotEmpty(request.getSchemas())) {
- tableCache =
- new StaticTableCache(request.getTableConfigs(),
request.getSchemas(), request.getLogicalTableConfigs(),
- request.isIgnoreCase());
- LOGGER.info("Validating multi-stage query compilation using static
table cache for query: {}",
- request.getSql());
- } else {
- // Use TableCache from environment if static fields are not specified
- tableCache = _pinotHelixResourceManager.getTableCache();
- LOGGER.info("Validating multi-stage query compilation using Zk table
cache for query: {}", request.getSql());
- }
- try (QueryEnvironment.CompiledQuery compiledQuery = new
QueryEnvironment(database, tableCache, null).compile(
- sqlQuery)) {
- return new MultiStageQueryValidationResponse(true, null, null);
+ List<String> sqlQueries = request.getSqls();
+ String sql = request.getSql();
+ List<MultiStageQueryValidationResponse> multiStageQueryValidationResponses
= new ArrayList<>();
+ if ((sql == null || sql.isEmpty()) && (sqlQueries == null ||
sqlQueries.isEmpty())) {
+ MultiStageQueryValidationResponse multiStageQueryValidationResponse =
+ new MultiStageQueryValidationResponse(false, "Request is missing the
queries string field 'sql'", null, null);
+
multiStageQueryValidationResponses.add(multiStageQueryValidationResponse);
+ }
+ if (sqlQueries == null || sqlQueries.isEmpty()) {
+ sqlQueries = new ArrayList<>();
+ sqlQueries.add(sql);
+ }
+ for (String sqlQuery : sqlQueries) {
+ Map<String, String> queryOptionsMap =
RequestUtils.parseQuery(sqlQuery).getOptions();
+ String database =
DatabaseUtils.extractDatabaseFromQueryRequest(queryOptionsMap, httpHeaders);
+ try {
+ TableCache tableCache;
+ if (CollectionUtils.isNotEmpty(request.getTableConfigs()) &&
CollectionUtils.isNotEmpty(request.getSchemas())) {
+ tableCache =
+ new StaticTableCache(request.getTableConfigs(),
request.getSchemas(), request.getLogicalTableConfigs(),
+ request.isIgnoreCase());
+ LOGGER.info("Validating multi-stage query: {} compilation using
static table cache ", sqlQuery);
+ } else {
+ // Use TableCache from environment if static fields are not specified
+ tableCache = _pinotHelixResourceManager.getTableCache();
+ LOGGER.info("Validating multi-stage query: {} compilation using Zk
table cache", sqlQuery);
+ }
+ try (QueryEnvironment.CompiledQuery compiledQuery = new
QueryEnvironment(database, tableCache, null).compile(
+ sqlQuery)) {
+ MultiStageQueryValidationResponse multiStageQueryValidationResponse =
+ new MultiStageQueryValidationResponse(true, null, null,
sqlQuery);
+
multiStageQueryValidationResponses.add(multiStageQueryValidationResponse);
+ }
+ } catch (QueryException e) {
+ LOGGER.error("Caught exception while compiling multi-stage query: {}",
e.getMessage());
+ MultiStageQueryValidationResponse multiStageQueryValidationResponse =
+ new MultiStageQueryValidationResponse(false, e.getMessage(),
e.getErrorCode(), sqlQuery);
+
multiStageQueryValidationResponses.add(multiStageQueryValidationResponse);
+ } catch (Exception e) {
+ LOGGER.error("Caught exception while validating multi-stage query:
{}", e.getMessage());
+ MultiStageQueryValidationResponse multiStageQueryValidationResponse =
+ new MultiStageQueryValidationResponse(false, "Unexpected error: "
+ e.getMessage(), QueryErrorCode.UNKNOWN,
+ sqlQuery);
+
multiStageQueryValidationResponses.add(multiStageQueryValidationResponse);
}
- } catch (QueryException e) {
- LOGGER.info("Caught exception while compiling multi-stage query: {}",
e.getMessage());
- return new MultiStageQueryValidationResponse(false, e.getMessage(),
e.getErrorCode());
- } catch (Exception e) {
- LOGGER.error("Caught exception while validating multi-stage query: {}",
e.getMessage());
- return new MultiStageQueryValidationResponse(false, "Unexpected error: "
+ e.getMessage(),
- QueryErrorCode.UNKNOWN);
}
+ return multiStageQueryValidationResponses;
}
public static class MultiStageQueryValidationResponse {
private final boolean _compiledSuccessfully;
private final String _errorMessage;
private final QueryErrorCode _errorCode;
+ private final String _sql;
public MultiStageQueryValidationResponse(boolean compiledSuccessfully,
@Nullable String errorMessage,
- @Nullable QueryErrorCode errorCode) {
+ @Nullable QueryErrorCode errorCode, String sql) {
_compiledSuccessfully = compiledSuccessfully;
_errorMessage = errorMessage;
_errorCode = errorCode;
+ _sql = sql;
}
public boolean isCompiledSuccessfully() {
@@ -223,6 +239,10 @@ public class PinotQueryResource {
public QueryErrorCode getErrorCode() {
return _errorCode;
}
+
+ public String getSql() {
+ return _sql;
+ }
}
public static class MultiStageQueryValidationRequest {
@@ -231,20 +251,28 @@ public class PinotQueryResource {
private final List<Schema> _schemas;
private final List<LogicalTableConfig> _logicalTableConfigs;
private final boolean _ignoreCase;
+ private final List<String> _sqls;
@JsonCreator
public MultiStageQueryValidationRequest(@JsonProperty("sql") String sql,
@JsonProperty("tableConfigs") @Nullable List<TableConfig> tableConfigs,
@JsonProperty("schemas") @Nullable List<Schema> schemas,
@JsonProperty("logicalTableConfigs") @Nullable
List<LogicalTableConfig> logicalTableConfigs,
- @JsonProperty("ignoreCase") boolean ignoreCase) {
+ @JsonProperty("sqls") List<String> sqls, @JsonProperty("ignoreCase")
boolean ignoreCase) {
_sql = sql;
_tableConfigs = tableConfigs;
_schemas = schemas;
_logicalTableConfigs = logicalTableConfigs;
_ignoreCase = ignoreCase;
+ _sqls = sqls;
}
+ @Nullable
+ public List<String> getSqls() {
+ return _sqls;
+ }
+
+ @Nullable
public String getSql() {
return _sql;
}
diff --git
a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/MultiStageEngineIntegrationTest.java
b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/MultiStageEngineIntegrationTest.java
index b45a47b153d..d91e879289a 100644
---
a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/MultiStageEngineIntegrationTest.java
+++
b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/MultiStageEngineIntegrationTest.java
@@ -29,6 +29,7 @@ import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -1716,47 +1717,66 @@ public class MultiStageEngineIntegrationTest extends
BaseClusterIntegrationTestS
@Test
public void testValidateQueryApiSuccess()
throws Exception {
+ MultiStageQueryValidationRequest request =
+ new MultiStageQueryValidationRequest("SELECT * FROM mytable", null,
null, null, null, false);
+ String requestJson = JsonUtils.objectToString(request);
JsonNode result = JsonUtils.stringToJsonNode(
- sendPostRequest(getControllerBaseApiUrl() + "/validateMultiStageQuery",
- "{\"sql\": \"SELECT * FROM mytable\"}", null));
- assertTrue(result.get("compiledSuccessfully").asBoolean());
- assertTrue(result.get("errorCode").isNull());
- assertTrue(result.get("errorMessage").isNull());
+ sendPostRequest(getControllerBaseApiUrl() +
"/validateMultiStageQuery", requestJson, null));
+
+ assertTrue(result.isArray(), "Response should be an array");
+ assertEquals(1, result.size(), "Should have exactly one response");
+ JsonNode queryResponse = result.get(0);
+ assertTrue(queryResponse.get("compiledSuccessfully").asBoolean());
+ assertTrue(queryResponse.get("errorCode").isNull());
+ assertTrue(queryResponse.get("errorMessage").isNull());
+ assertEquals("SELECT * FROM mytable", queryResponse.get("sql").asText());
}
@Test
public void testValidateQueryApiError()
throws Exception {
+ MultiStageQueryValidationRequest request =
+ new MultiStageQueryValidationRequest("SELECT invalidColumn FROM
invalidTable", null, null, null, null, false);
+ String requestJson = JsonUtils.objectToString(request);
JsonNode result = JsonUtils.stringToJsonNode(
- sendPostRequest(getControllerBaseApiUrl() + "/validateMultiStageQuery",
- "{\"sql\": \"SELECT invalidColumn FROM invalidTable\"}", null));
- assertFalse(result.get("compiledSuccessfully").asBoolean());
- assertEquals(result.get("errorCode").asText(),
QueryErrorCode.TABLE_DOES_NOT_EXIST.name());
- assertFalse(result.get("errorMessage").isNull());
+ sendPostRequest(getControllerBaseApiUrl() +
"/validateMultiStageQuery", requestJson, null));
+ assertTrue(result.isArray(), "Response should be an array");
+ assertEquals(1, result.size(), "Should have exactly one response");
+
+ JsonNode queryResponse = result.get(0);
+ assertFalse(queryResponse.get("compiledSuccessfully").asBoolean());
+ assertEquals(queryResponse.get("errorCode").asText(),
QueryErrorCode.TABLE_DOES_NOT_EXIST.name());
+ assertFalse(queryResponse.get("errorMessage").isNull());
+ assertEquals("SELECT invalidColumn FROM invalidTable",
queryResponse.get("sql").asText());
+ request = new MultiStageQueryValidationRequest("SELECT CAST('abc' AS
INT)", null, null, null, null, false);
+
+ requestJson = JsonUtils.objectToString(request);
result = JsonUtils.stringToJsonNode(
- sendPostRequest(getControllerBaseApiUrl() + "/validateMultiStageQuery",
- "{\"sql\": \"SELECT CAST('abc' AS INT)\"}", null));
- assertFalse(result.get("compiledSuccessfully").asBoolean());
- assertEquals(result.get("errorCode").asText(),
QueryErrorCode.QUERY_PLANNING.name());
- assertFalse(result.get("errorMessage").isNull());
+ sendPostRequest(getControllerBaseApiUrl() +
"/validateMultiStageQuery", requestJson, null));
+
+ assertTrue(result.isArray(), "Response should be an array");
+ assertEquals(1, result.size(), "Should have exactly one response");
+
+ queryResponse = result.get(0);
+ assertFalse(queryResponse.get("compiledSuccessfully").asBoolean());
+ assertEquals(queryResponse.get("errorCode").asText(),
QueryErrorCode.QUERY_PLANNING.name());
+ assertFalse(queryResponse.get("errorMessage").isNull());
+ assertEquals("SELECT CAST('abc' AS INT)",
queryResponse.get("sql").asText());
}
@Test
- public void testValidateQueryApiSuccessfulQueries() throws Exception {
- JsonNode tableConfigsNode = JsonUtils.stringToJsonNode(
- sendGetRequest(getControllerBaseApiUrl() + "/tables/mytable"));
- JsonNode schemaNode = JsonUtils.stringToJsonNode(
- sendGetRequest(getControllerBaseApiUrl() + "/schemas/mytable"));
-
- String[] successfulQueries = {
- "SELECT COUNT(*) FROM mytable",
+ public void testValidateQueryApiSuccessfulQueries()
+ throws Exception {
+ JsonNode tableConfigsNode =
+ JsonUtils.stringToJsonNode(sendGetRequest(getControllerBaseApiUrl() +
"/tables/mytable"));
+ JsonNode schemaNode =
JsonUtils.stringToJsonNode(sendGetRequest(getControllerBaseApiUrl() +
"/schemas/mytable"));
+ List<String> successfulQueries = Arrays.asList("SELECT COUNT(*) FROM
mytable",
"SELECT DivAirportSeqIDs, COUNT(*) FROM mytable GROUP BY
DivAirportSeqIDs",
"SELECT DivAirportSeqIDs FROM mytable WHERE
arrayToMV(DivAirportSeqIDs) > 0 LIMIT 10",
"SELECT DivAirportSeqIDs, AirlineID FROM mytable ORDER BY
DivAirportSeqIDs LIMIT 5",
"SELECT SUM(arrayToMV(DivAirportSeqIDs)) AS total FROM mytable",
- "SELECT AVG(arrayToMV(DivAirportSeqIDs)) FROM mytable WHERE AirlineID
IS NOT NULL"
- };
+ "SELECT AVG(arrayToMV(DivAirportSeqIDs)) FROM mytable WHERE AirlineID
IS NOT NULL");
List<TableConfig> tableConfigs = new ArrayList<>();
JsonNode offlineConfig = tableConfigsNode.get("OFFLINE");
@@ -1771,27 +1791,82 @@ public class MultiStageEngineIntegrationTest extends
BaseClusterIntegrationTestS
Schema schema = JsonUtils.jsonNodeToObject(schemaNode, Schema.class);
List<Schema> schemas = Collections.singletonList(schema);
- for (String query : successfulQueries) {
- MultiStageQueryValidationRequest request = new
MultiStageQueryValidationRequest(
- query, tableConfigs, schemas, null, false);
+ MultiStageQueryValidationRequest request =
+ new MultiStageQueryValidationRequest(null, tableConfigs, schemas,
null, successfulQueries, false);
+
+ String requestJson = JsonUtils.objectToString(request);
+ JsonNode result = JsonUtils.stringToJsonNode(
+ sendPostRequest(getControllerBaseApiUrl() +
"/validateMultiStageQuery", requestJson, null));
- String requestJson = JsonUtils.objectToString(request);
- JsonNode result = JsonUtils.stringToJsonNode(
- sendPostRequest(getControllerBaseApiUrl() +
"/validateMultiStageQuery", requestJson, null));
+ assertTrue(result.isArray(), "Response should be an array");
+ assertEquals(successfulQueries.size(), result.size(), "Should have
response for each query");
+
+ for (int i = 0; i < result.size(); i++) {
+ JsonNode queryResponse = result.get(i);
+ String expectedQuery = successfulQueries.get(i);
+
+ assertTrue(queryResponse.get("compiledSuccessfully").asBoolean(),
+ "Query should compile successfully: " + expectedQuery);
+ assertTrue(queryResponse.get("errorCode").isNull(), "Error code should
be null for query: " + expectedQuery);
+ assertTrue(queryResponse.get("errorMessage").isNull(),
+ "Error message should be null for query: " + expectedQuery);
+ assertEquals(expectedQuery, queryResponse.get("sql").asText(), "SQL
should match the input query");
+ }
+ }
+
+ @Test
+ public void testValidateQueryApiBatchMixedResults()
+ throws Exception {
+ JsonNode tableConfigsNode =
+ JsonUtils.stringToJsonNode(sendGetRequest(getControllerBaseApiUrl() +
"/tables/mytable"));
+ JsonNode schemaNode =
JsonUtils.stringToJsonNode(sendGetRequest(getControllerBaseApiUrl() +
"/schemas/mytable"));
+ List<String> mixedQueries = Arrays.asList("SELECT COUNT(*) FROM mytable",
"SELECT invalidColumn FROM mytable",
+ "SELECT DivAirportSeqIDs FROM mytable LIMIT 10", "SELECT * FROM
nonExistentTable");
- assertTrue(result.get("compiledSuccessfully").asBoolean(),
- "Query should compile successfully: " + query);
- assertTrue(result.get("errorCode").isNull());
- assertTrue(result.get("errorMessage").isNull());
+ List<TableConfig> tableConfigs = new ArrayList<>();
+ JsonNode offlineConfig = tableConfigsNode.get("OFFLINE");
+ if (offlineConfig != null && !offlineConfig.isMissingNode() &&
!offlineConfig.isEmpty()) {
+ tableConfigs.add(JsonUtils.jsonNodeToObject(offlineConfig,
TableConfig.class));
}
+
+ Schema schema = JsonUtils.jsonNodeToObject(schemaNode, Schema.class);
+ List<Schema> schemas = Collections.singletonList(schema);
+
+ MultiStageQueryValidationRequest request =
+ new MultiStageQueryValidationRequest(null, tableConfigs, schemas,
null, mixedQueries, false);
+
+ String requestJson = JsonUtils.objectToString(request);
+ JsonNode result = JsonUtils.stringToJsonNode(
+ sendPostRequest(getControllerBaseApiUrl() +
"/validateMultiStageQuery", requestJson, null));
+
+ assertTrue(result.isArray(), "Response should be an array");
+ assertEquals(4, result.size(), "Should have 4 result entries");
+
+ JsonNode result1 = result.get(0);
+ assertTrue(result1.get("compiledSuccessfully").asBoolean(), "First query
should succeed");
+ assertEquals("SELECT COUNT(*) FROM mytable", result1.get("sql").asText());
+
+ JsonNode result2 = result.get(1);
+ assertFalse(result2.get("compiledSuccessfully").asBoolean(), "Second query
should fail");
+ assertEquals("SELECT invalidColumn FROM mytable",
result2.get("sql").asText());
+ assertNotNull(result2.get("errorMessage").asText());
+
+ JsonNode result3 = result.get(2);
+ assertTrue(result3.get("compiledSuccessfully").asBoolean(), "Third query
should succeed");
+ assertEquals("SELECT DivAirportSeqIDs FROM mytable LIMIT 10",
result3.get("sql").asText());
+
+ JsonNode result4 = result.get(3);
+ assertFalse(result4.get("compiledSuccessfully").asBoolean(), "Fourth query
should fail");
+ assertEquals("SELECT * FROM nonExistentTable",
result4.get("sql").asText());
+ assertNotNull(result4.get("errorMessage").asText());
}
@Test
- public void testValidateQueryApiUnsuccessfulQueries() throws Exception {
+ public void testValidateQueryApiUnsuccessfulQueries()
+ throws Exception {
JsonNode tableConfigsNode =
JsonUtils.stringToJsonNode(sendGetRequest(getControllerBaseApiUrl() +
"/tables/mytable"));
- JsonNode schemaNode =
- JsonUtils.stringToJsonNode(sendGetRequest(getControllerBaseApiUrl() +
"/schemas/mytable"));
+ JsonNode schemaNode =
JsonUtils.stringToJsonNode(sendGetRequest(getControllerBaseApiUrl() +
"/schemas/mytable"));
List<TableConfig> tableConfigs = new ArrayList<>();
JsonNode offlineConfig = tableConfigsNode.get("OFFLINE");
@@ -1806,39 +1881,49 @@ public class MultiStageEngineIntegrationTest extends
BaseClusterIntegrationTestS
Schema schema = JsonUtils.jsonNodeToObject(schemaNode, Schema.class);
List<Schema> schemas = Collections.singletonList(schema);
- // Invalid column in the query
- MultiStageQueryValidationRequest request = new
MultiStageQueryValidationRequest(
- "SELECT nonExistentColumn FROM mytable", tableConfigs, schemas, null,
true);
+ MultiStageQueryValidationRequest request =
+ new MultiStageQueryValidationRequest("SELECT nonExistentColumn FROM
mytable",
+ tableConfigs, schemas, null, null, true);
String requestJson = JsonUtils.objectToString(request);
JsonNode result = JsonUtils.stringToJsonNode(
sendPostRequest(getControllerBaseApiUrl() +
"/validateMultiStageQuery", requestJson, null));
- assertFalse(result.get("compiledSuccessfully").asBoolean());
- assertEquals(result.get("errorCode").asText(),
QueryErrorCode.QUERY_VALIDATION.name());
- // Cannot apply '>' to arguments of type '<INTEGER> to <ARRAY>
+ assertTrue(result.isArray(), "Response should be an array");
+ assertEquals(1, result.size(), "Should have exactly one response");
+ JsonNode queryResponse = result.get(0);
+ assertFalse(queryResponse.get("compiledSuccessfully").asBoolean());
+ assertEquals(queryResponse.get("errorCode").asText(),
QueryErrorCode.QUERY_VALIDATION.name());
+
String query = "SELECT DivAirportSeqIDs FROM mytable WHERE
DivAirportSeqIDs > 0 LIMIT 10";
- request = new MultiStageQueryValidationRequest(query, tableConfigs,
schemas, null, false);
+ request = new MultiStageQueryValidationRequest(query, tableConfigs,
schemas, null, null, false);
requestJson = JsonUtils.objectToString(request);
result = JsonUtils.stringToJsonNode(
sendPostRequest(getControllerBaseApiUrl() +
"/validateMultiStageQuery", requestJson, null));
- assertFalse(result.get("compiledSuccessfully").asBoolean(), "Query should
not compile successfully: " + query);
- assertEquals(result.get("errorCode").asText(),
QueryErrorCode.QUERY_VALIDATION.name());
- assertFalse(result.get("errorMessage").isNull(), "Error message should not
be null for: " + query);
+ assertTrue(result.isArray(), "Response should be an array");
+ assertEquals(1, result.size(), "Should have exactly one response");
+ queryResponse = result.get(0);
+ assertFalse(queryResponse.get("compiledSuccessfully").asBoolean(),
+ "Query should not compile successfully: " + query);
+ assertEquals(queryResponse.get("errorCode").asText(),
QueryErrorCode.QUERY_VALIDATION.name());
+ assertFalse(queryResponse.get("errorMessage").isNull(), "Error message
should not be null for: " + query);
- // Non-existent table
query = "SELECT count(*) FROM nonExistentTable";
- request = new MultiStageQueryValidationRequest(query, tableConfigs,
schemas, null, false);
+ request = new MultiStageQueryValidationRequest(query, tableConfigs,
schemas, null, null, false);
requestJson = JsonUtils.objectToString(request);
result = JsonUtils.stringToJsonNode(
sendPostRequest(getControllerBaseApiUrl() +
"/validateMultiStageQuery", requestJson, null));
- assertFalse(result.get("compiledSuccessfully").asBoolean(), "Query should
not compile successfully: " + query);
- assertEquals(result.get("errorCode").asText(),
QueryErrorCode.TABLE_DOES_NOT_EXIST.name());
- assertFalse(result.get("errorMessage").isNull(), "Error message should not
be null for: " + query);
+ assertTrue(result.isArray(), "Response should be an array");
+ assertEquals(1, result.size(), "Should have exactly one response");
+ queryResponse = result.get(0);
+ assertFalse(queryResponse.get("compiledSuccessfully").asBoolean(),
+ "Query should not compile successfully: " + query);
+ assertEquals(queryResponse.get("errorCode").asText(),
QueryErrorCode.TABLE_DOES_NOT_EXIST.name());
+ assertFalse(queryResponse.get("errorMessage").isNull(), "Error message
should not be null for: " + query);
}
@Test
@@ -1880,11 +1965,6 @@ public class MultiStageEngineIntegrationTest extends
BaseClusterIntegrationTestS
upsertConfig.setEnablePreload(true);
upsertConfig.setDropOutOfOrderRecord(false);
upsertConfig.setNewSegmentTrackingTimeMs(10000L);
-
upsertConfig.setMetadataManagerClass("ai.startree.pinot.upsert.rocksdb.RocksDBTableUpsertMetadataManager");
-
- Map<String, String> metadataManagerConfigs = new HashMap<>();
- metadataManagerConfigs.put("rocksdb.preload.num_partition_overwrite", "2");
- upsertConfig.setMetadataManagerConfigs(metadataManagerConfigs);
upsertConfig.setDefaultPartialUpsertStrategy(UpsertConfig.Strategy.OVERWRITE);
upsertConfig.setUpsertViewRefreshIntervalMs(3000L);
@@ -1909,27 +1989,33 @@ public class MultiStageEngineIntegrationTest extends
BaseClusterIntegrationTestS
List<Schema> schemas = Collections.singletonList(schema);
String query = "SELECT nonExistentColumn FROM staticTableTest";
- // Invalid column in the static table query
+
MultiStageQueryValidationRequest request =
- new MultiStageQueryValidationRequest(query, tableConfigs, schemas,
null, true);
+ new MultiStageQueryValidationRequest(query, tableConfigs, schemas,
null, null, true);
String requestJson = JsonUtils.objectToString(request);
JsonNode result = JsonUtils.stringToJsonNode(
sendPostRequest(getControllerBaseApiUrl() +
"/validateMultiStageQuery", requestJson, null));
- assertFalse(result.get("compiledSuccessfully").asBoolean());
- assertEquals(result.get("errorCode").asText(),
QueryErrorCode.QUERY_VALIDATION.name());
- // Successful query with existing column
+ assertTrue(result.isArray(), "Response should be an array");
+ assertEquals(1, result.size(), "Should have exactly one response");
+ JsonNode queryResponse = result.get(0);
+ assertFalse(queryResponse.get("compiledSuccessfully").asBoolean());
+ assertEquals(queryResponse.get("errorCode").asText(),
QueryErrorCode.QUERY_VALIDATION.name());
+
query = "SELECT event_id FROM staticTableTest";
- request = new MultiStageQueryValidationRequest(query, tableConfigs,
schemas, null, false);
+ request = new MultiStageQueryValidationRequest(query, tableConfigs,
schemas, null, null, false);
requestJson = JsonUtils.objectToString(request);
result = JsonUtils.stringToJsonNode(
sendPostRequest(getControllerBaseApiUrl() +
"/validateMultiStageQuery", requestJson, null));
- assertTrue(result.get("compiledSuccessfully").asBoolean(), "Query should
compile successfully: " + query);
- assertTrue(result.get("errorCode").isNull());
- assertTrue(result.get("errorMessage").isNull());
+ assertTrue(result.isArray(), "Response should be an array");
+ assertEquals(1, result.size(), "Should have exactly one response");
+ queryResponse = result.get(0);
+ assertTrue(queryResponse.get("compiledSuccessfully").asBoolean(), "Query
should compile successfully: " + query);
+ assertTrue(queryResponse.get("errorCode").isNull());
+ assertTrue(queryResponse.get("errorMessage").isNull());
}
@Test
@@ -1951,29 +2037,37 @@ public class MultiStageEngineIntegrationTest extends
BaseClusterIntegrationTestS
Schema schema = JsonUtils.jsonNodeToObject(schemaNode, Schema.class);
List<Schema> schemas = Collections.singletonList(schema);
- // Test case-sensitive mode
- MultiStageQueryValidationRequest request = new
MultiStageQueryValidationRequest(
- "SELECT divairportseqids FROM mytable", tableConfigs, schemas, null,
false);
+ MultiStageQueryValidationRequest request =
+ new MultiStageQueryValidationRequest("SELECT divairportseqids FROM
mytable", tableConfigs, schemas, null, null,
+ false);
String requestJson = JsonUtils.objectToString(request);
JsonNode result = JsonUtils.stringToJsonNode(
sendPostRequest(getControllerBaseApiUrl() +
"/validateMultiStageQuery", requestJson, null));
- assertTrue(result.get("compiledSuccessfully").asBoolean(),
+
+ assertTrue(result.isArray(), "Response should be an array");
+ assertEquals(1, result.size(), "Should have exactly one response");
+ JsonNode queryResponse = result.get(0);
+ assertTrue(queryResponse.get("compiledSuccessfully").asBoolean(),
"Query should compile successfully in case-sensitive mode");
- assertTrue(result.get("errorCode").isNull(), "Error code should be null in
case-sensitive mode");
- assertTrue(result.get("errorMessage").isNull(), "Error message should be
null in case-sensitive mode");
+ assertTrue(queryResponse.get("errorCode").isNull(), "Error code should be
null in case-sensitive mode");
+ assertTrue(queryResponse.get("errorMessage").isNull(), "Error message
should be null in case-sensitive mode");
- // Test case-insensitive mode
- request = new MultiStageQueryValidationRequest(
- "SELECT divairportseqids FROM mytable", tableConfigs, schemas, null,
true);
+ request =
+ new MultiStageQueryValidationRequest("SELECT divairportseqids FROM
mytable", tableConfigs, schemas, null, null,
+ true);
requestJson = JsonUtils.objectToString(request);
result = JsonUtils.stringToJsonNode(
sendPostRequest(getControllerBaseApiUrl() +
"/validateMultiStageQuery", requestJson, null));
- assertTrue(result.get("compiledSuccessfully").asBoolean(),
+
+ assertTrue(result.isArray(), "Response should be an array");
+ assertEquals(1, result.size(), "Should have exactly one response");
+ queryResponse = result.get(0);
+ assertTrue(queryResponse.get("compiledSuccessfully").asBoolean(),
"Query should compile successfully in case-insensitive mode");
- assertTrue(result.get("errorCode").isNull(), "Error code should be null in
case-insensitive mode");
- assertTrue(result.get("errorMessage").isNull(), "Error message should be
null in case-insensitive mode");
+ assertTrue(queryResponse.get("errorCode").isNull(), "Error code should be
null in case-insensitive mode");
+ assertTrue(queryResponse.get("errorMessage").isNull(), "Error message
should be null in case-insensitive mode");
}
private void checkQueryResultForDBTest(String column, String tableName)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]