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]

Reply via email to