You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pinot.apache.org by mc...@apache.org on 2021/02/26 19:21:51 UTC

[incubator-pinot] branch master updated: Implement QueryOp class. (#6583)

This is an automated email from the ASF dual-hosted git repository.

mcvsubbu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-pinot.git


The following commit(s) were added to refs/heads/master by this push:
     new 7a989f7  Implement QueryOp class. (#6583)
7a989f7 is described below

commit 7a989f72d495c4c72904fa3b811259ac6e37043d
Author: Liang Mingqiang <mi...@linkedin.com>
AuthorDate: Fri Feb 26 11:21:30 2021 -0800

    Implement QueryOp class. (#6583)
    
    * Implement QueryOp class.
    
    Implement QueryOp class, which take a file that has queries, and
    a file that has results, run the queries through the broker/server
    and compare the results with the result file.
    
    * address comments: reformat code; verify routing table is updated
    in SegmentOp
    
    * address jackjlli's comments
    
    * address mcvsubbu's comments
    
    * address jackjlli's comments: throwing a generic Exception
    
    * use println instead of printf
    
    Co-authored-by: Ming Liang <mi...@miliang-mn1.linkedin.biz>
---
 .../pinot/compat/tests/CompatibilityOpsRunner.java |  11 +-
 .../org/apache/pinot/compat/tests/QueryOp.java     |  95 +++++-
 .../apache/pinot/compat/tests/QueryProcessor.java  |  98 ++++++
 .../org/apache/pinot/compat/tests/SegmentOp.java   |  26 +-
 .../pinot/compat/tests/SqlResultComparator.java    | 353 +++++++++++++++++++++
 .../compat-tests/configs/feature-test-1.json       |  11 +
 .../queries/feature-test-1-sql.queries             |  89 ++++++
 .../src/test/resources/compat-tests/query-op.yaml  |  49 +++
 .../query-results/feature-test-1-rest-sql.results  |  85 +++++
 .../resources/compat-tests/table-segment-op.yaml   |   5 +
 10 files changed, 812 insertions(+), 10 deletions(-)

diff --git a/pinot-integration-tests/src/test/java/org/apache/pinot/compat/tests/CompatibilityOpsRunner.java b/pinot-integration-tests/src/test/java/org/apache/pinot/compat/tests/CompatibilityOpsRunner.java
index fe9144c..7350cf9 100644
--- a/pinot-integration-tests/src/test/java/org/apache/pinot/compat/tests/CompatibilityOpsRunner.java
+++ b/pinot-integration-tests/src/test/java/org/apache/pinot/compat/tests/CompatibilityOpsRunner.java
@@ -18,14 +18,10 @@
  */
 package org.apache.pinot.compat.tests;
 
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.databind.JsonMappingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
-import java.io.IOException;
 import java.io.InputStream;
-import org.apache.pinot.compat.tests.BaseOp;
-import org.apache.pinot.compat.tests.CompatTestOperation;
+
 
 public class CompatibilityOpsRunner {
   private static final String ROOT_DIR = "compat-tests";
@@ -36,8 +32,7 @@ public class CompatibilityOpsRunner {
     _configFileName = configFileName;
   }
 
-  private boolean runOps()
-      throws IOException, JsonParseException, JsonMappingException {
+  private boolean runOps() throws Exception {
     String filePath = ROOT_DIR + "/" + _configFileName;
     InputStream inputStream = getClass().getClassLoader().getResourceAsStream(filePath);
 
@@ -56,7 +51,7 @@ public class CompatibilityOpsRunner {
     return passed;
   }
 
-  public static void main(String[] args) throws  Exception {
+  public static void main(String[] args) throws Exception {
     if (args.length < 1 || args.length > 1) {
       throw new IllegalArgumentException("Need exactly one file name as argument");
     }
diff --git a/pinot-integration-tests/src/test/java/org/apache/pinot/compat/tests/QueryOp.java b/pinot-integration-tests/src/test/java/org/apache/pinot/compat/tests/QueryOp.java
index 48e4ba0..eeafb15 100644
--- a/pinot-integration-tests/src/test/java/org/apache/pinot/compat/tests/QueryOp.java
+++ b/pinot-integration-tests/src/test/java/org/apache/pinot/compat/tests/QueryOp.java
@@ -19,6 +19,14 @@
 package org.apache.pinot.compat.tests;
 
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.databind.JsonNode;
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import org.apache.pinot.spi.utils.JsonUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 
 /**
@@ -30,6 +38,11 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
  */
 @JsonIgnoreProperties(ignoreUnknown = true)
 public class QueryOp extends BaseOp {
+  private static final Logger LOGGER = LoggerFactory.getLogger(QueryOp.class);
+
+  private static final String NUM_DOCS_SCANNED_KEY = "numDocsScanned";
+  private static final String TIME_USED_MS_KEY = "timeUsedMs";
+  private static final String COMMENT_DELIMITER = "#";
   private String _queryFileName;
   private String _expectedResultsFileName;
 
@@ -37,6 +50,11 @@ public class QueryOp extends BaseOp {
     super(OpType.QUERY_OP);
   }
 
+  private boolean shouldIgnore(String line) {
+    String trimmedLine = line.trim();
+    return trimmedLine.isEmpty() || trimmedLine.startsWith(COMMENT_DELIMITER);
+  }
+
   public String getQueryFileName() {
     return _queryFileName;
   }
@@ -56,6 +74,81 @@ public class QueryOp extends BaseOp {
   @Override
   boolean runOp() {
     System.out.println("Verifying queries in " + _queryFileName + " against results in " + _expectedResultsFileName);
-    return true;
+    try {
+      return verifyQueries();
+    } catch (Exception e) {
+      LOGGER.error("FAILED to verify queries in {}: {}", _queryFileName, e);
+      return false;
+    }
+  }
+
+  boolean verifyQueries()
+      throws Exception {
+    boolean testPassed = false;
+
+    try (BufferedReader queryReader = new BufferedReader(
+        new InputStreamReader(new FileInputStream(_queryFileName), StandardCharsets.UTF_8));
+        BufferedReader expectedResultReader = new BufferedReader(
+            new InputStreamReader(new FileInputStream(_expectedResultsFileName), StandardCharsets.UTF_8))) {
+
+      int succeededQueryCount = 0;
+      int totalQueryCount = 0;
+      int queryLineNum = 0;
+      String query;
+
+      while ((query = queryReader.readLine()) != null) {
+        queryLineNum++;
+        if (shouldIgnore(query)) {
+          continue;
+        }
+
+        JsonNode expectedJson = null;
+        try {
+          String expectedResultLine = expectedResultReader.readLine();
+          while (shouldIgnore(expectedResultLine)) {
+            expectedResultLine = expectedResultReader.readLine();
+          }
+          expectedJson = JsonUtils.stringToJsonNode(expectedResultLine);
+        } catch (Exception e) {
+          LOGGER.error("Comparison FAILED: Line: {} Exception caught while getting expected response for query: '{}'",
+              queryLineNum, query, e);
+        }
+
+        JsonNode actualJson = null;
+        if (expectedJson != null) {
+          try {
+            actualJson = QueryProcessor.postSqlQuery(query);
+          } catch (Exception e) {
+            LOGGER.error("Comparison FAILED: Line: {} Exception caught while running query: '{}'", queryLineNum, query,
+                e);
+          }
+        }
+
+        if (expectedJson != null && actualJson != null) {
+          try {
+            boolean passed = SqlResultComparator.areEqual(actualJson, expectedJson, query);
+            if (passed) {
+              succeededQueryCount++;
+              LOGGER.debug("Comparison PASSED: Line: {}, query: '{}', actual response: {}, expected response: {}",
+                  queryLineNum, query, actualJson, expectedJson);
+            } else {
+              LOGGER.error("Comparison FAILED: Line: {}, query: '{}', actual response: {}, expected response: {}",
+                  queryLineNum, query, actualJson, expectedJson);
+            }
+          } catch (Exception e) {
+            LOGGER.error(
+                "Comparison FAILED: Line: {} Exception caught while comparing query: '{}' actual response: {}, expected response: {}",
+                queryLineNum, query, actualJson, expectedJson, e);
+          }
+        }
+        totalQueryCount++;
+      }
+
+      LOGGER.info("Total {} out of {} queries passed.", succeededQueryCount, totalQueryCount);
+      if (succeededQueryCount == totalQueryCount) {
+        testPassed = true;
+      }
+    }
+    return testPassed;
   }
 }
diff --git a/pinot-integration-tests/src/test/java/org/apache/pinot/compat/tests/QueryProcessor.java b/pinot-integration-tests/src/test/java/org/apache/pinot/compat/tests/QueryProcessor.java
new file mode 100644
index 0000000..6109134
--- /dev/null
+++ b/pinot-integration-tests/src/test/java/org/apache/pinot/compat/tests/QueryProcessor.java
@@ -0,0 +1,98 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.pinot.compat.tests;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.Map;
+import org.apache.pinot.spi.utils.JsonUtils;
+
+
+public class QueryProcessor {
+
+  private static final String BROKER_BASE_API_URL = ClusterDescriptor.CONTROLLER_URL;
+
+  /**
+   * Queries the broker's sql query endpoint (/sql)
+   */
+  public static JsonNode postSqlQuery(String query)
+      throws Exception {
+    return postSqlQuery(query, BROKER_BASE_API_URL);
+  }
+
+  /**
+   * Queries the broker's sql query endpoint (/sql)
+   */
+  private static JsonNode postSqlQuery(String query, String brokerBaseApiUrl)
+      throws Exception {
+    ObjectNode payload = JsonUtils.newObjectNode();
+    payload.put("sql", query);
+    payload.put("queryOptions", "groupByMode=sql;responseFormat=sql");
+
+    return JsonUtils.stringToJsonNode(sendPostRequest(brokerBaseApiUrl + "/sql", payload.toString()));
+  }
+
+  private static String sendPostRequest(String urlString, String payload)
+      throws IOException {
+    return sendPostRequest(urlString, payload, Collections.EMPTY_MAP);
+  }
+
+  private static String sendPostRequest(String urlString, String payload, Map<String, String> headers)
+      throws IOException {
+    HttpURLConnection httpConnection = (HttpURLConnection) new URL(urlString).openConnection();
+    httpConnection.setRequestMethod("POST");
+    if (headers != null) {
+      for (String key : headers.keySet()) {
+        httpConnection.setRequestProperty(key, headers.get(key));
+      }
+    }
+
+    if (payload != null && !payload.isEmpty()) {
+      httpConnection.setDoOutput(true);
+      try (BufferedWriter writer = new BufferedWriter(
+          new OutputStreamWriter(httpConnection.getOutputStream(), StandardCharsets.UTF_8))) {
+        writer.write(payload, 0, payload.length());
+        writer.flush();
+      }
+    }
+    return constructResponse(httpConnection.getInputStream());
+  }
+
+  private static String constructResponse(InputStream inputStream)
+      throws IOException {
+    try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
+      StringBuilder responseBuilder = new StringBuilder();
+      String line;
+      while ((line = reader.readLine()) != null) {
+        responseBuilder.append(line);
+      }
+      return responseBuilder.toString();
+    }
+  }
+}
diff --git a/pinot-integration-tests/src/test/java/org/apache/pinot/compat/tests/SegmentOp.java b/pinot-integration-tests/src/test/java/org/apache/pinot/compat/tests/SegmentOp.java
index 7e63212..99e8301 100644
--- a/pinot-integration-tests/src/test/java/org/apache/pinot/compat/tests/SegmentOp.java
+++ b/pinot-integration-tests/src/test/java/org/apache/pinot/compat/tests/SegmentOp.java
@@ -19,6 +19,7 @@
 package org.apache.pinot.compat.tests;
 
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.databind.JsonNode;
 import java.io.File;
 import java.io.IOException;
 import java.net.URI;
@@ -154,7 +155,8 @@ public class SegmentOp extends BaseOp {
       FileUtils.forceMkdir(localOutputTempDir);
       File segmentTarFile = generateSegment(localOutputTempDir);
       uploadSegment(segmentTarFile);
-      return verifySegmentInState(CommonConstants.Helix.StateModel.SegmentStateModel.ONLINE);
+      return verifySegmentInState(CommonConstants.Helix.StateModel.SegmentStateModel.ONLINE)
+          && verifyRoutingTableUpdated();
     } catch (Exception e) {
       LOGGER.error("Failed to create and upload segment for input data file {}.", _inputDataFileName, e);
       return false;
@@ -241,6 +243,28 @@ public class SegmentOp extends BaseOp {
     return true;
   }
 
+  // TODO: verify by getting the number of rows before adding the segment, and the number of rows after adding the
+  //       segment, then make sure that it has increased by the number of rows in the segment.
+  private boolean verifyRoutingTableUpdated()
+      throws Exception {
+    String query = "SELECT count(*) FROM " + _tableName;
+    JsonNode result = QueryProcessor.postSqlQuery(query);
+    long startTime = System.currentTimeMillis();
+    while (SqlResultComparator.isEmpty(result)) {
+      if ((System.currentTimeMillis() - startTime) > DEFAULT_MAX_SLEEP_TIME_MS) {
+        LOGGER
+            .error("Upload segment verification failed, routing table has not been updated after max wait time {} ms.",
+                DEFAULT_MAX_SLEEP_TIME_MS);
+        return false;
+      }
+      LOGGER.warn("Routing table has not been updated yet, will retry after {} ms.", DEFAULT_SLEEP_INTERVAL_MS);
+      Thread.sleep(DEFAULT_SLEEP_INTERVAL_MS);
+      result = QueryProcessor.postSqlQuery(query);
+    }
+    LOGGER.info("Routing table has been updated.");
+    return true;
+  }
+
   /**
    * Deletes the segment for the given segment name and table name.
    * @return true if delete successful, else false.
diff --git a/pinot-integration-tests/src/test/java/org/apache/pinot/compat/tests/SqlResultComparator.java b/pinot-integration-tests/src/test/java/org/apache/pinot/compat/tests/SqlResultComparator.java
new file mode 100644
index 0000000..c117452
--- /dev/null
+++ b/pinot-integration-tests/src/test/java/org/apache/pinot/compat/tests/SqlResultComparator.java
@@ -0,0 +1,353 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.pinot.compat.tests;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.calcite.config.Lex;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlNodeList;
+import org.apache.calcite.sql.SqlOrderBy;
+import org.apache.calcite.sql.parser.SqlParseException;
+import org.apache.calcite.sql.parser.SqlParser;
+import org.apache.calcite.sql.parser.babel.SqlBabelParserImpl;
+import org.apache.calcite.sql.validate.SqlConformanceEnum;
+import org.apache.pinot.spi.utils.JsonUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class SqlResultComparator {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(SqlResultComparator.class);
+
+  private static final String FIELD_RESULT_TABLE = "resultTable";
+  private static final String FIELD_DATA_SCHEMA = "dataSchema";
+  private static final String FIELD_ROWS = "rows";
+  private static final String FIELD_COLUMN_DATA_TYPES = "columnDataTypes";
+  private static final String FIELD_IS_SUPERSET = "isSuperset";
+  private static final String FIELD_NUM_DOCS_SCANNED = "numDocsScanned";
+  private static final String FIELD_EXCEPTIONS = "exceptions";
+  private static final String FIELD_NUM_SERVERS_QUERIED = "numServersQueried";
+  private static final String FIELD_NUM_SERVERS_RESPONDED = "numServersResponded";
+  private static final String FIELD_NUM_SEGMENTS_QUERIED = "numSegmentsQueried";
+  private static final String FIELD_NUM_SEGMENTS_PROCESSED = "numSegmentsProcessed";
+  private static final String FIELD_NUM_SEGMENTS_MATCHED = "numSegmentsMatched";
+  private static final String FIELD_NUM_CONSUMING_SEGMENTS_QUERIED = "numConsumingSegmentsQueried";
+  private static final String FIELD_NUM_ENTRIES_SCANNED_IN_FILTER = "numEntriesScannedInFilter";
+  private static final String FIELD_NUM_ENTRIES_SCANNED_POST_FILTER = "numEntriesScannedPostFilter";
+  private static final String FIELD_NUM_GROUPS_LIMIT_REACHED = "numGroupsLimitReached";
+
+  private static final String FIELD_TYPE_INT = "INT";
+  private static final String FIELD_TYPE_LONG = "LONG";
+  private static final String FIELD_TYPE_FLOAT = "FLOAT";
+  private static final String FIELD_TYPE_DOUBLE = "DOUBLE";
+  private static final String FIELD_TYPE_STRING = "STRING";
+  private static final String FIELD_TYPE_BYTES = "BYTES";
+  private static final String FIELD_TYPE_INT_ARRAY = "INT_ARRAY";
+  private static final String FIELD_TYPE_LONG_ARRAY = "LONG_ARRAY";
+  private static final String FIELD_TYPE_FLOAT_ARRAY = "FLOAT_ARRAY";
+  private static final String FIELD_TYPE_DOUBLE_ARRAY = "DOUBLE_ARRAY";
+  private static final String FIELD_TYPE_STRING_ARRAY = "STRING_ARRAY";
+  private static final String FIELD_TYPE_BYTES_ARRRAY = "BYTES_ARRRAY";
+
+  private static final SqlParser.Config SQL_PARSER_CONFIG =
+      SqlParser.configBuilder().setLex(Lex.MYSQL_ANSI).setConformance(SqlConformanceEnum.BABEL)
+          .setParserFactory(SqlBabelParserImpl.FACTORY).build();
+
+  public static boolean areEqual(JsonNode actual, JsonNode expected, String query)
+      throws IOException {
+    if (hasExceptions(actual)) {
+      return false;
+    }
+
+    if (areEmpty(actual, expected)) {
+      return true;
+    }
+
+    if (!areDataSchemaEqual(actual, expected)) {
+      return false;
+    }
+
+    ArrayNode actualRows = (ArrayNode) actual.get(FIELD_RESULT_TABLE).get(FIELD_ROWS);
+    ArrayNode expectedRows = (ArrayNode) expected.get(FIELD_RESULT_TABLE).get(FIELD_ROWS);
+    ArrayNode columnDataTypes = (ArrayNode) expected.get(FIELD_RESULT_TABLE).get(FIELD_DATA_SCHEMA).
+        get(FIELD_COLUMN_DATA_TYPES);
+
+    convertNumbersToString(expectedRows, columnDataTypes);
+    convertNumbersToString(actualRows, columnDataTypes);
+
+    List<String> actualElementsSerialized = new ArrayList<>();
+    List<String> expectedElementsSerialized = new ArrayList<>();
+    for (int i = 0; i < actualRows.size(); i++) {
+      actualElementsSerialized.add(actualRows.get(i).toString());
+    }
+    for (int i = 0; i < expectedRows.size(); i++) {
+      expectedElementsSerialized.add(expectedRows.get(i).toString());
+    }
+    /*
+     * If the test compares the returned results to be a subset of total qualified results, ignore the comparison of
+     * result length and metadata(numDocsScanned, numEntriesScannedInFilter, numEntriesScannedPostFilter, etc).
+     */
+    if (expected.has(FIELD_IS_SUPERSET) && expected.get(FIELD_IS_SUPERSET).asBoolean(false)) {
+      return areElementsSubset(actualElementsSerialized, expectedElementsSerialized);
+    } else {
+      return areLengthsEqual(actual, expected) && areElementsEqual(actualElementsSerialized, expectedElementsSerialized,
+          query) && areMetadataEqual(actual, expected);
+    }
+  }
+
+  public static boolean hasExceptions(JsonNode actual) {
+    if (actual.get(FIELD_EXCEPTIONS).size() != 0) {
+      LOGGER.error("Got exception: {} when querying!", actual.get(FIELD_EXCEPTIONS));
+      return true;
+    }
+    return false;
+  }
+
+  public static boolean areMetadataEqual(JsonNode actual, JsonNode expected) {
+    return areNumServersQueriedEqual(actual, expected) && areNumServersRespondedEqual(actual, expected)
+        && areNumSegmentsQueriedEqual(actual, expected) && areNumSegmentsProcessedEqual(actual, expected)
+        && areNumSegmentsMatchedEqual(actual, expected) && areNumConsumingSegmentsQueriedEqual(actual, expected)
+        && areNumDocsScannedEqual(actual, expected) && areNumEntriesScannedInFilterEqual(actual, expected)
+        && areNumEntriesScannedPostFilterEqual(actual, expected) && areNumGroupsLimitReachedEqual(actual, expected);
+  }
+
+  private static boolean areNumGroupsLimitReachedEqual(JsonNode actual, JsonNode expected) {
+    boolean actualNumGroupsLimitReached = actual.get(FIELD_NUM_GROUPS_LIMIT_REACHED).asBoolean();
+    boolean expectedNumGroupsLimitReached = expected.get(FIELD_NUM_GROUPS_LIMIT_REACHED).asBoolean();
+    if (actualNumGroupsLimitReached != expectedNumGroupsLimitReached) {
+      LOGGER.error("The numGroupsLimitReached don't match! Actual: {}, Expected: {}", actualNumGroupsLimitReached,
+          expectedNumGroupsLimitReached);
+      return false;
+    }
+    return true;
+  }
+
+  private static boolean areNumConsumingSegmentsQueriedEqual(JsonNode actual, JsonNode expected) {
+    long actualNumConsumingSegmentsQueried = actual.get(FIELD_NUM_CONSUMING_SEGMENTS_QUERIED).asLong();
+    long expectedNumConsumingSegmentsQueried = expected.get(FIELD_NUM_CONSUMING_SEGMENTS_QUERIED).asLong();
+    if (actualNumConsumingSegmentsQueried != expectedNumConsumingSegmentsQueried) {
+      LOGGER.error("The numConsumingSegmentsQueried don't match! Actual: {}, Expected: {}",
+          actualNumConsumingSegmentsQueried, expectedNumConsumingSegmentsQueried);
+      return false;
+    }
+    return true;
+  }
+
+  private static boolean areNumSegmentsProcessedEqual(JsonNode actual, JsonNode expected) {
+    long actualNumSegmentsProcessed = actual.get(FIELD_NUM_SEGMENTS_PROCESSED).asLong();
+    long expectedNumSegmentsProcessed = expected.get(FIELD_NUM_SEGMENTS_PROCESSED).asLong();
+    if (actualNumSegmentsProcessed != expectedNumSegmentsProcessed) {
+      LOGGER.error("The numSegmentsProcessed don't match! Actual: {}, Expected: {}", actualNumSegmentsProcessed,
+          expectedNumSegmentsProcessed);
+      return false;
+    }
+    return true;
+  }
+
+  private static boolean areNumSegmentsQueriedEqual(JsonNode actual, JsonNode expected) {
+    long actualNumSegmentsQueried = actual.get(FIELD_NUM_SEGMENTS_QUERIED).asLong();
+    long expectedNumSegmentsQueried = expected.get(FIELD_NUM_SEGMENTS_QUERIED).asLong();
+    if (actualNumSegmentsQueried != expectedNumSegmentsQueried) {
+      LOGGER.error("The numSegmentsQueried don't match! Actual: {}, Expected: {}", actualNumSegmentsQueried,
+          expectedNumSegmentsQueried);
+      return false;
+    }
+    return true;
+  }
+
+  private static boolean areNumSegmentsMatchedEqual(JsonNode actual, JsonNode expected) {
+    long actualNumSegmentsMatched = actual.get(FIELD_NUM_SEGMENTS_MATCHED).asLong();
+    long expectedNumSegmentsMatched = expected.get(FIELD_NUM_SEGMENTS_MATCHED).asLong();
+    if (actualNumSegmentsMatched != expectedNumSegmentsMatched) {
+      LOGGER.error("The numSegmentsMatched don't match! Actual: {}, Expected: {}", actualNumSegmentsMatched,
+          expectedNumSegmentsMatched);
+      return false;
+    }
+    return true;
+  }
+
+  private static boolean areNumServersRespondedEqual(JsonNode actual, JsonNode expected) {
+    long actualNumServersResponded = actual.get(FIELD_NUM_SERVERS_RESPONDED).asLong();
+    long expectedNumServersResponded = expected.get(FIELD_NUM_SERVERS_RESPONDED).asLong();
+    if (actualNumServersResponded != expectedNumServersResponded) {
+      LOGGER.error("The numServersResponded don't match! Actual: {}, Expected: {}", actualNumServersResponded,
+          expectedNumServersResponded);
+      return false;
+    }
+    return true;
+  }
+
+  private static boolean areNumServersQueriedEqual(JsonNode actual, JsonNode expected) {
+    long actualNumServersQueried = actual.get(FIELD_NUM_SERVERS_QUERIED).asLong();
+    long expectedNumServersQueried = expected.get(FIELD_NUM_SERVERS_QUERIED).asLong();
+    if (actualNumServersQueried != expectedNumServersQueried) {
+      LOGGER.error("The numServersQueried don't match! Actual: {}, Expected: {}", actualNumServersQueried,
+          expectedNumServersQueried);
+      return false;
+    }
+    return true;
+  }
+
+  private static boolean areNumEntriesScannedInFilterEqual(JsonNode actual, JsonNode expected) {
+    long actualNumEntriesScannedInFilter = actual.get(FIELD_NUM_ENTRIES_SCANNED_IN_FILTER).asLong();
+    long expectedNumEntriesScannedInFilter = expected.get(FIELD_NUM_ENTRIES_SCANNED_IN_FILTER).asLong();
+    if (actualNumEntriesScannedInFilter != expectedNumEntriesScannedInFilter) {
+      LOGGER
+          .error("The numEntriesScannedInFilter don't match! Actual: {}, Expected: {}", actualNumEntriesScannedInFilter,
+              expectedNumEntriesScannedInFilter);
+      return false;
+    }
+    return true;
+  }
+
+  private static boolean areNumEntriesScannedPostFilterEqual(JsonNode actual, JsonNode expected) {
+    long actualNumEntriesScannedPostFilter = actual.get(FIELD_NUM_ENTRIES_SCANNED_POST_FILTER).asLong();
+    long expectedNumEntriesScannedPostFilter = expected.get(FIELD_NUM_ENTRIES_SCANNED_POST_FILTER).asLong();
+    if (actualNumEntriesScannedPostFilter != expectedNumEntriesScannedPostFilter) {
+      LOGGER.error("The numEntriesScannedPostFilter don't match! Actual: {}, Expected: {}",
+          actualNumEntriesScannedPostFilter, expectedNumEntriesScannedPostFilter);
+      return false;
+    }
+    return true;
+  }
+
+  private static boolean areNumDocsScannedEqual(JsonNode actual, JsonNode expected) {
+    int actualNumDocsScanned = actual.get(FIELD_NUM_DOCS_SCANNED).asInt();
+    int expectedNumDocsScanned = expected.get(FIELD_NUM_DOCS_SCANNED).asInt();
+    if (actualNumDocsScanned != expectedNumDocsScanned) {
+      LOGGER.error("The numDocsScanned don't match! Actual: {}, Expected: {}", actualNumDocsScanned,
+          expectedNumDocsScanned);
+      return false;
+    }
+    return true;
+  }
+
+  private static boolean areEmpty(JsonNode actual, JsonNode expected) {
+    if (isEmpty(actual) && isEmpty(expected)) {
+      LOGGER.debug("Empty results, nothing to compare.");
+      return true;
+    }
+    return false;
+  }
+
+  public static boolean isEmpty(JsonNode response) {
+    int numDocsScanned = response.get(FIELD_NUM_DOCS_SCANNED).asInt();
+    return numDocsScanned == 0 || !response.has(FIELD_RESULT_TABLE)
+        || response.get(FIELD_RESULT_TABLE).get(FIELD_ROWS).size() == 0;
+  }
+
+  private static boolean areLengthsEqual(JsonNode actual, JsonNode expected) {
+    int actualLength = actual.get(FIELD_RESULT_TABLE).get(FIELD_ROWS).size();
+    int expectedLength = expected.get(FIELD_RESULT_TABLE).get(FIELD_ROWS).size();
+    if (actualLength != expectedLength) {
+      LOGGER.error("The length of results don't match! Actual: {}, Expected: {}", actualLength, expectedLength);
+      return false;
+    }
+    return true;
+  }
+
+  private static boolean areDataSchemaEqual(JsonNode actual, JsonNode expected) {
+    JsonNode actualDataSchema = actual.get(FIELD_RESULT_TABLE).get(FIELD_DATA_SCHEMA);
+    JsonNode expecteDataSchema = expected.get(FIELD_RESULT_TABLE).get(FIELD_DATA_SCHEMA);
+
+    String actualDataSchemaStr = actualDataSchema.toString();
+    String expecteDataSchemaStr = expecteDataSchema.toString();
+    if (!actualDataSchemaStr.equals(expecteDataSchemaStr)) {
+      LOGGER.error("The dataSchema don't match! Actual: {}, Expected: {}", actualDataSchema, expecteDataSchema);
+      return false;
+    }
+    return true;
+  }
+
+  private static boolean areElementsSubset(List<String> actualElementsSerialized,
+      List<String> expectedElementsSerialized) {
+    boolean result = expectedElementsSerialized.containsAll(actualElementsSerialized);
+    if (!result) {
+      LOGGER.error("Actual result '{}' is not a subset of '{}'", actualElementsSerialized, expectedElementsSerialized);
+    }
+    return result;
+  }
+
+  private static boolean areElementsEqual(List<String> actualElementsSerialized,
+      List<String> expectedElementsSerialized, String query) {
+    if (isOrdered(query)) {
+      if (!actualElementsSerialized.equals(expectedElementsSerialized)) {
+        LOGGER.error("The results of the ordered query don't match! Actual: {}, Expected: {}", actualElementsSerialized,
+            expectedElementsSerialized);
+        return false;
+      }
+      return true;
+    }
+
+    // sort elements
+    actualElementsSerialized.sort(null);
+    expectedElementsSerialized.sort(null);
+    if (!actualElementsSerialized.equals(expectedElementsSerialized)) {
+      LOGGER.error("The results of the non-ordered query don't match. Sorted-expected: '{}', sorted-actual: '{}'",
+          expectedElementsSerialized, actualElementsSerialized);
+      return false;
+    }
+    return true;
+  }
+
+  private static void convertNumbersToString(ArrayNode rows, ArrayNode columnDataTypes)
+      throws IOException {
+    for (int i = 0; i < rows.size(); i++) {
+      for (int j = 0; j < columnDataTypes.size(); j++) {
+        ArrayNode row = (ArrayNode) rows.get(i);
+        String type = columnDataTypes.get(j).asText();
+        if (type.equals(FIELD_TYPE_FLOAT) || type.equals(FIELD_TYPE_DOUBLE)) {
+          double round = Math.round(Double.valueOf(row.get(j).asText()) * 100) / 100.0;
+          String str = String.valueOf(round);
+          row.set(j, JsonUtils.stringToJsonNode(str));
+        } else if (type.equals(FIELD_TYPE_FLOAT_ARRAY) || type.equals(FIELD_TYPE_DOUBLE_ARRAY)) {
+          ArrayNode jsonArray = (ArrayNode) rows.get(i).get(j);
+          List<String> arrayStr = new ArrayList<>();
+          for (int k = 0; k < jsonArray.size(); k++) {
+            double round = Math.round(Double.valueOf(jsonArray.get(k).asText()) * 100) / 100;
+            arrayStr.add(String.valueOf(round));
+          }
+          row.set(j, JsonUtils.stringToJsonNode(arrayStr.toString()));
+        }
+      }
+    }
+  }
+
+  private static boolean isOrdered(String query) {
+    SqlParser sqlParser = SqlParser.create(query, SQL_PARSER_CONFIG);
+    try {
+      SqlNode sqlNode = sqlParser.parseQuery();
+      boolean isOrderBy = sqlNode.getKind() == SqlKind.ORDER_BY;
+      if (!isOrderBy) {
+        return false;
+      }
+      SqlOrderBy sqlOrderBy = (SqlOrderBy) sqlNode;
+      SqlNodeList orderByColumns = sqlOrderBy.orderList;
+      return orderByColumns != null && orderByColumns.size() != 0;
+    } catch (SqlParseException e) {
+      throw new RuntimeException("Cannot parse query: " + query, e);
+    }
+  }
+}
diff --git a/pinot-integration-tests/src/test/resources/compat-tests/configs/feature-test-1.json b/pinot-integration-tests/src/test/resources/compat-tests/configs/feature-test-1.json
index f9d6ac5..7e6a7cc 100644
--- a/pinot-integration-tests/src/test/resources/compat-tests/configs/feature-test-1.json
+++ b/pinot-integration-tests/src/test/resources/compat-tests/configs/feature-test-1.json
@@ -1,4 +1,15 @@
 {
+  "fieldConfigList": [
+    {
+      "encodingType": "RAW",
+      "indexType": "TEXT",
+      "name": "textDim1",
+      "properties": {
+        "deriveNumDocsPerChunkForRawIndex": "true",
+        "rawIndexWriterVersion": "3"
+      }
+    }
+  ],
   "metadata": {
     "customConfigs": {
       "d2Name": ""
diff --git a/pinot-integration-tests/src/test/resources/compat-tests/queries/feature-test-1-sql.queries b/pinot-integration-tests/src/test/resources/compat-tests/queries/feature-test-1-sql.queries
new file mode 100644
index 0000000..f0d63e9
--- /dev/null
+++ b/pinot-integration-tests/src/test/resources/compat-tests/queries/feature-test-1-sql.queries
@@ -0,0 +1,89 @@
+# Aggregation
+SELECT count(*) FROM FeatureTest1
+SELECT sum(intMetric1), sumMV(intDimMV1), min(intMetric1), minMV(intDimMV2), max(longDimSV1), maxMV(intDimMV1) FROM FeatureTest1
+SELECT count(longDimSV1), countMV(intDimMV1), avg(floatMetric1), avgMV(intDimMV2), minMaxRange(doubleMetric1), minMaxRangeMV(intDimMV2) FROM FeatureTest1
+SELECT percentile(longDimSV1, 80), percentileMV(intDimMV1, 90), percentileEst(longDimSV1, 80), percentileEstMV(intDimMV1, 90), percentileTDigest(longDimSV1, 80), percentileTDigestMV(intDimMV1, 90) FROM FeatureTest1
+SELECT distinctCount(longDimSV1), distinctCountMV(intDimMV1), distinctCountHLL(longDimSV1), distinctCountHLLMV(intDimMV1) FROM FeatureTest1
+
+# Selection
+SELECT longDimSV2, stringDimSV1, textDim1, bytesDimSV1 FROM FeatureTest1 ORDER BY longDimSV2 LIMIT 9
+SELECT longDimSV2, stringDimSV1, textDim1, bytesDimSV1 FROM FeatureTest1 ORDER BY longDimSV2 DESC LIMIT 8
+SELECT longDimSV2, stringDimSV1, textDim1, bytesDimSV1 FROM FeatureTest1 ORDER BY longDimSV2 DESC, stringDimSV1 LIMIT 8
+
+# Selection & Filtering
+SELECT textDim1, longDimSV2, doubleMetric1 FROM FeatureTest1 WHERE bytesDimSV1 = 'deed0507'
+# This is a subset comparison query: there are 4 qualified records in total, the query limit the number of returned records as 2,
+# the test compares the returned results to be a subset of total qualified results.
+# To generate the result file, use this query instead: SELECT textDim1, longDimSV2, doubleMetric1 FROM FeatureTest1 WHERE bytesDimSV1 = 'deed0507'
+SELECT textDim1, longDimSV2, doubleMetric1 FROM FeatureTest1 WHERE bytesDimSV1 = 'deed0507' LIMIT 2
+# This is a query exhausting all records: there are 4 qualified records in total, the query limit the number of returned records as 10
+SELECT textDim1, longDimSV2, doubleMetric1 FROM FeatureTest1 WHERE bytesDimSV1 = 'deed0507' LIMIT 10
+SELECT stringDimSV1, longDimSV1, intDimMV1, intDimMV2, stringDimMV2 FROM FeatureTest1 WHERE stringDimSV1 != 's1-6' AND longDimSV1 BETWEEN 10 AND 1000 OR (intDimMV1 < 42 AND stringDimMV2 IN ('m2-0-0', 'm2-2-0') AND intDimMV2 NOT IN (6,72)) ORDER BY longDimSV1 LIMIT 5
+SELECT stringDimSV1, longDimSV1, intDimMV1, intDimMV2, stringDimMV2 FROM FeatureTest1 WHERE stringDimSV1 != 's1-6' AND longDimSV1 BETWEEN 10 AND 1000 OR (intDimMV1 < 42 AND stringDimMV2 IN ('m2-0-0', 'm2-2-0') AND intDimMV2 NOT IN (6,72)) ORDER BY longDimSV1 DESC
+SELECT stringDimSV1, longDimSV1, intDimMV1, intDimMV2, stringDimMV2 FROM FeatureTest1 WHERE stringDimSV1 != 's1-6' AND longDimSV1 BETWEEN 10 AND 1000 OR (intDimMV1 < 42 AND stringDimMV2 IN ('m2-0-0', 'm2-2-0') AND intDimMV2 NOT IN (6,72)) ORDER BY longDimSV1 DESC, stringDimSV1 LIMIT 3
+
+# Selection & Grouping on Aggregation
+SELECT longDimSV1, intDimMV1, count(*) FROM FeatureTest1 GROUP BY longDimSV1, intDimMV1 ORDER BY longDimSV1 LIMIT 5
+SELECT longDimSV1, intDimMV1, sum(intMetric1), sumMV(intDimMV1), min(intMetric1), minMV(intDimMV2), max(longDimSV1), maxMV(intDimMV1) FROM FeatureTest1 GROUP BY longDimSV1, intDimMV1 ORDER BY longDimSV1 LIMIT 5
+SELECT longDimSV1, intDimMV1, count(longDimSV1), countMV(intDimMV1), avg(floatMetric1), avgMV(intDimMV2), minMaxRange(doubleMetric1), minMaxRangeMV(intDimMV2) FROM FeatureTest1 GROUP BY longDimSV1, intDimMV1 ORDER BY longDimSV1 LIMIT 5
+SELECT longDimSV1, intDimMV1, percentile(longDimSV1, 80), percentileMV(intDimMV1, 90), percentileEst(longDimSV1, 80), percentileEstMV(intDimMV1, 90), percentileTDigest(longDimSV1, 80), percentileTDigestMV(intDimMV1, 90) FROM FeatureTest1 GROUP BY longDimSV1, intDimMV1 ORDER BY longDimSV1 LIMIT 5
+SELECT longDimSV1, intDimMV1, distinctCount(longDimSV1), distinctCountMV(intDimMV1), distinctCountHLL(longDimSV1), distinctCountHLLMV(intDimMV1) FROM FeatureTest1 GROUP BY longDimSV1, intDimMV1 ORDER BY longDimSV1 LIMIT 5
+
+# Selection & Filtering & Grouping on Aggregation
+SELECT longDimSV1, intDimMV1, count(*) FROM FeatureTest1 WHERE stringDimSV1 != 's1-6' AND longDimSV1 BETWEEN 10 AND 1000 OR (intDimMV1 < 42 AND stringDimMV2 IN ('m2-0-0', 'm2-2-0') AND intDimMV2 NOT IN (6,72)) GROUP BY longDimSV1, intDimMV1 ORDER BY longDimSV1, intDimMV1 LIMIT 5
+SELECT longDimSV1, intDimMV1, sum(intMetric1), sumMV(intDimMV1), min(intMetric1), minMV(intDimMV2), max(longDimSV1), maxMV(intDimMV1) FROM FeatureTest1 WHERE stringDimSV1 != 's1-6' AND longDimSV1 BETWEEN 10 AND 1000 OR (intDimMV1 < 42 AND stringDimMV2 IN ('m2-0-0', 'm2-2-0') AND intDimMV2 NOT IN (6,72)) GROUP BY longDimSV1, intDimMV1 ORDER BY longDimSV1, intDimMV1 LIMIT 5
+SELECT longDimSV1, intDimMV1, count(longDimSV1), countMV(intDimMV1), avg(floatMetric1), avgMV(intDimMV2), minMaxRange(doubleMetric1), minMaxRangeMV(intDimMV2) FROM FeatureTest1 WHERE stringDimSV1 != 's1-6' AND longDimSV1 BETWEEN 10 AND 1000 OR (intDimMV1 < 42 AND stringDimMV2 IN ('m2-0-0', 'm2-2-0') AND intDimMV2 NOT IN (6,72)) GROUP BY longDimSV1, intDimMV1 ORDER BY longDimSV1, intDimMV1 LIMIT 5
+SELECT longDimSV1, intDimMV1, percentile(longDimSV1, 80), percentileMV(intDimMV1, 90), percentileEst(longDimSV1, 80), percentileEstMV(intDimMV1, 90), percentileTDigest(longDimSV1, 80), percentileTDigestMV(intDimMV1, 90) FROM FeatureTest1 WHERE stringDimSV1 != 's1-6' AND longDimSV1 BETWEEN 10 AND 1000 OR (intDimMV1 < 42 AND stringDimMV2 IN ('m2-0-0', 'm2-2-0') AND intDimMV2 NOT IN (6,72)) GROUP BY longDimSV1, intDimMV1 ORDER BY longDimSV1, intDimMV1 LIMIT 5
+SELECT longDimSV1, intDimMV1, distinctCount(longDimSV1), distinctCountMV(intDimMV1), distinctCountHLL(longDimSV1), distinctCountHLLMV(intDimMV1) FROM FeatureTest1 WHERE stringDimSV1 != 's1-6' AND longDimSV1 BETWEEN 10 AND 1000 OR (intDimMV1 < 42 AND stringDimMV2 IN ('m2-0-0', 'm2-2-0') AND intDimMV2 NOT IN (6,72)) GROUP BY longDimSV1, intDimMV1 ORDER BY longDimSV1, intDimMV1 LIMIT 5
+
+# Transformation Functions
+SELECT add(longDimSV1, sub(longDimSV2, 3)), mod(intMetric1, 10), div(doubleMetric1, mult(floatMetric1, 5)) FROM FeatureTest1 ORDER BY add(longDimSV1, sub(longDimSV2, 3)) DESC, mod(intMetric1, 10)
+SELECT floor(sqrt(doubleMetric1)), ceil(ln(longDimSV1)), exp(mod(abs(longDimSV2), 3)) FROM FeatureTest1 ORDER BY floor(sqrt(doubleMetric1)), ceil(ln(longDimSV1)), exp(mod(abs(longDimSV2), 3)) DESC
+SELECT count(*) FROM FeatureTest1 GROUP BY arrayLength(intDimMV1), arrayLength(valueIn(stringDimMV2, 'm2-2-0', 'm2-3-0'))
+SELECT valueIn(intDimMV1, 3, 32), count(*) FROM FeatureTest1 GROUP BY valueIn(intDimMV1, 3, 32)
+SELECT upper(stringDimSV1), lower(textDim1), reverse(stringDimSV2), ltrim(substr(textDim1, 4, 9)), rtrim(substr(textDim1, 4, 9)) from FeatureTest1 ORDER BY upper(stringDimSV1) LIMIT 10
+SELECT stringDimSV2, replace(stringDimSV2, 'foo', 'bar'), codePoint(stringDimSV2), rpad(stringDimSV2, 11, 'abc'), lpad(stringDimSV2, 11, 'xyz') from FeatureTest1 WHERE strPos(stringDimSV2, '2', 2) > 1 OR startsWith(stringDimSV2, 'foo') = 'true' ORDER BY codePoint(stringDimSV2), replace(stringDimSV2, 'foo', 'bar') LIMIT 10
+
+# Groovy Scripts
+SELECT longDimSV1, longDimSV2, groovy('{"returnType":"LONG","isSingleValue":true}', 'arg0 + arg1', longDimSV1, longDimSV2) FROM FeatureTest1 ORDER BY longDimSV1, longDimSV2 DESC LIMIT 10
+SELECT count(*), groovy('{"returnType":"STRING", "isSingleValue":true}', 'def result; if (arg0 < 0) { result = "NEGATIVE"; } else if (arg0 < 10) { result = "SMALL";} else if (arg0 < 50) { result = "MEDIUM";} else{result = "LARGE"}; return result', longDimSV1) FROM FeatureTest1 GROUP BY groovy('{"returnType":"STRING", "isSingleValue":true}', 'def result; if (arg0 < 0) { result = "NEGATIVE"; } else if (arg0 < 10) { result = "SMALL";} else if (arg0 < 50) { result = "MEDIUM";} else{result =  [...]
+SELECT groovy('{"returnType":"INT","isSingleValue":true}', 'arg0.toList().max()', intDimMV1) FROM FeatureTest1 ORDER BY groovy('{"returnType":"INT","isSingleValue":true}', 'arg0.toList().max()', intDimMV1) LIMIT 10
+
+# Text Search
+SELECT stringDimSV1, textDim1 FROM FeatureTest1 WHERE text_match(textDim1, 'Java')
+SELECT stringDimSV1, textDim1 FROM FeatureTest1 WHERE text_match(textDim1, 'Java AND C++')
+SELECT stringDimSV1, textDim1 FROM FeatureTest1 WHERE text_match(textDim1, 'Java OR C++') AND longDimSV1 > 20 LIMIT 20
+SELECT stringDimSV1, textDim1 FROM FeatureTest1 WHERE text_match(textDim1, 'Java C++') AND longDimSV1 > 20 LIMIT 20
+SELECT stringDimSV1, textDim1 FROM FeatureTest1 WHERE text_match(textDim1, '"Java C++"') LIMIT 20
+SELECT stringDimSV1, textDim1 FROM FeatureTest1 WHERE text_match(textDim1, '"java c++" "golang python"') LIMIT 20
+SELECT stringDimSV1, textDim1 FROM FeatureTest1 WHERE text_match(textDim1, '"Java C++" AND (golang python)') LIMIT 20
+SELECT stringDimSV1, textDim1 FROM FeatureTest1 WHERE text_match(textDim1, '(Java OR C++) AND (golang python)') AND longDimSV1 > 20 LIMIT 20
+SELECT stringDimSV1, textDim1 FROM FeatureTest1 WHERE text_match(textDim1, 'go*') LIMIT 20
+SELECT stringDimSV1, textDim1 FROM FeatureTest1 WHERE text_match(textDim1, 'word go*') LIMIT 20
+SELECT stringDimSV1, textDim1 FROM FeatureTest1 WHERE text_match(textDim1, '/go.*g/') LIMIT 20
+SELECT stringDimSV1, count(stringDimSV1) FROM FeatureTest1 WHERE text_match(textDim1, 'Java') GROUP BY stringDimSV1 ORDER BY count(stringDimSV1) DESC LIMIT 20
+
+# Map
+SELECT stringDimSV1, mapValue(mapDim1__KEYS, 'k1', mapDim1__VALUES), mapValue(mapDim1__KEYS, 'k4', mapDim1__VALUES) FROM FeatureTest1 LIMIT 5
+SELECT stringDimSV1, mapValue(mapDim1__KEYS, 'k1', mapDim1__VALUES), mapValue(mapDim1__KEYS, 'k4', mapDim1__VALUES) FROM FeatureTest1 ORDER BY mapValue(mapDim1__KEYS, 'k1', mapDim1__VALUES) LIMIT 5
+SELECT max(mapValue(mapDim1__KEYS, 'k2', mapDim1__VALUES)), min(mapValue(mapDim1__KEYS, 'k3', mapDim1__VALUES)) FROM FeatureTest1
+SELECT max(mapValue(mapDim1__KEYS, 'k2', mapDim1__VALUES)), min(mapValue(mapDim1__KEYS, 'k3', mapDim1__VALUES)) FROM FeatureTest1 GROUP BY mapValue(mapDim1__KEYS, 'k1', mapDim1__VALUES) ORDER BY max(mapValue(mapDim1__KEYS, 'k2', mapDim1__VALUES)) LIMIT 5
+SELECT mapValue(mapDim1__KEYS, 'k1', mapDim1__VALUES), mapValue(mapDim1__KEYS, 'k2', mapDim1__VALUES) FROM FeatureTest1 WHERE mapValue(mapDim1__KEYS, 'k1', mapDim1__VALUES) <= 4  LIMIT 5
+SELECT mapValue(mapDim1__KEYS, 'k1', mapDim1__VALUES), mapValue(mapDim1__KEYS, 'k2', mapDim1__VALUES) FROM FeatureTest1 WHERE mapValue(mapDim1__KEYS, 'non-existing-key', mapDim1__VALUES) <= 4
+SELECT mapValue(mapDim1__KEYS, 'non-existing-key', mapDim1__VALUES) FROM FeatureTest1 WHERE mapDim1__KEYS = 'non-existing-key'
+
+# Json Map
+SELECT stringDimSV1, jsonExtractScalar(mapDim2json, '$.k1', 'INT'), jsonExtractScalar(mapDim2json, '$.k4', 'INT') FROM FeatureTest1 LIMIT 5
+SELECT stringDimSV1, jsonExtractScalar(mapDim2json, '$.k1', 'INT'), jsonExtractScalar(mapDim2json, '$.k4', 'INT') FROM FeatureTest1 ORDER BY jsonExtractScalar(mapDim2json, '$.k1', 'INT') LIMIT 5
+SELECT max(jsonExtractScalar(mapDim2json, '$.k2', 'INT')), min(jsonExtractScalar(mapDim2json, '$.k3', 'INT')) FROM FeatureTest1
+SELECT max(jsonExtractScalar(mapDim2json, '$.k2', 'INT')), min(jsonExtractScalar(mapDim2json, '$.k3', 'INT')) FROM FeatureTest1 GROUP BY jsonExtractScalar(mapDim2json, '$.k1', 'INT') ORDER BY max(jsonExtractScalar(mapDim2json, '$.k2', 'INT')) LIMIT 5
+SELECT jsonExtractScalar(mapDim2json, '$.k1', 'INT'), jsonExtractScalar(mapDim2json, '$.k2', 'INT') FROM FeatureTest1 WHERE jsonExtractScalar(mapDim2json, '$.k1', 'INT') <= 4  LIMIT 5
+SELECT jsonExtractScalar(mapDim2json, '$.non-existing-key', 'INT', '-1') FROM FeatureTest1
+SELECT jsonExtractScalar(mapDim2json, '$.non-existing-key', 'INT') FROM FeatureTest1 WHERE jsonExtractKey(mapDim2json, '$.*') in ("$['non-existing-key']")
+
+# Misc
+SELECT count(*) FROM FeatureTest1 WHERE regexp_like(textDim1, '^Java.*') GROUP BY longDimSV1
+SELECT count(*) FROM FeatureTest1 WHERE regexp_like(stringDimMV2, 'm2.*0') GROUP BY stringDimMV2 LIMIT 3
+SELECT stringDimSV1, longDimSV1, intDimMV1 FROM FeatureTest1 ORDER BY stringDimSV1 DESC, longDimSV1 LIMIT 3
+SELECT stringDimSV1, longDimSV1, intDimMV1 FROM FeatureTest1 ORDER BY stringDimSV1 DESC, longDimSV1 DESC LIMIT 3
+SELECT * FROM FeatureTest1 ORDER BY longDimSV1 DESC, longMetric1 LIMIT 3
\ No newline at end of file
diff --git a/pinot-integration-tests/src/test/resources/compat-tests/query-op.yaml b/pinot-integration-tests/src/test/resources/compat-tests/query-op.yaml
new file mode 100644
index 0000000..03b6acf
--- /dev/null
+++ b/pinot-integration-tests/src/test/resources/compat-tests/query-op.yaml
@@ -0,0 +1,49 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# Operations to be done.
+description: Debug yaml file for query ops
+operations:
+  - type: tableOp
+    description: Create table feature-test-1.json
+    op: CREATE
+    schemaFileName: pinot-integration-tests/src/test/resources/compat-tests/configs/FeatureTest1-schema.json
+    tableConfigFileName: pinot-integration-tests/src/test/resources/compat-tests/configs/feature-test-1.json
+  - type: segmentOp
+    description: Build and upload segment using FeatureTest1-data-00.csv
+    op: UPLOAD
+    inputDataFileName: pinot-integration-tests/src/test/resources/compat-tests/data/FeatureTest1-data-00.csv
+    schemaFileName: pinot-integration-tests/src/test/resources/compat-tests/configs/FeatureTest1-schema.json
+    tableConfigFileName: pinot-integration-tests/src/test/resources/compat-tests/configs/feature-test-1.json
+    recordReaderConfigFileName: pinot-integration-tests/src/test/resources/compat-tests/data/recordReaderConfig.json
+    segmentName: FeatureTest1_Segment
+  - type: queryOp
+    description: Run query on FeatureTest1 using SQL
+    queryFileName: pinot-integration-tests/src/test/resources/compat-tests/queries/feature-test-1-sql.queries
+    expectedResultsFileName: pinot-integration-tests/src/test/resources/compat-tests/query-results/feature-test-1-rest-sql.results
+  - type: segmentOp
+    description: Delete segment FeatureTest1_Segment
+    op: DELETE
+    tableConfigFileName: pinot-integration-tests/src/test/resources/compat-tests/configs/feature-test-1.json
+    segmentName: FeatureTest1_Segment
+  - type: tableOp
+    description: Delete table feature-test-1.json
+    op: DELETE
+    schemaFileName: pinot-integration-tests/src/test/resources/compat-tests/configs/FeatureTest1-schema.json
+    tableConfigFileName: pinot-integration-tests/src/test/resources/compat-tests/configs/feature-test-1.json
\ No newline at end of file
diff --git a/pinot-integration-tests/src/test/resources/compat-tests/query-results/feature-test-1-rest-sql.results b/pinot-integration-tests/src/test/resources/compat-tests/query-results/feature-test-1-rest-sql.results
new file mode 100644
index 0000000..64774c1
--- /dev/null
+++ b/pinot-integration-tests/src/test/resources/compat-tests/query-results/feature-test-1-rest-sql.results
@@ -0,0 +1,85 @@
+# Aggregation
+{"resultTable":{"dataSchema":{"columnDataTypes":["LONG"],"columnNames":["count(*)"]},"rows":[[10]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":10,"numEntriesScannedInFilter":0,"numEntriesScannedPostFilter":0,"numGroupsLimitReached":false,"totalDocs":10,"timeUsedMs":4,"segmentStatistics":[],"traceInfo":{},"minConsumingFreshnessTimeMs":0}
+{"resultTable":{"dataSchema":{"columnDataTypes":["DOUBLE","DOUBLE","DOUBLE","DOUBLE","DOUBLE","DOUBLE"],"columnNames":["sum(intMetric1)","summv(intDimMV1)","min(intMetric1)","minmv(intDimMV2)","max(longDimSV1)","maxmv(intDimMV1)"]},"rows":[[4.294967536E9,-2.147479976E9,0.0,6.0,7611.0,462.0]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":10,"numEntriesSc [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["LONG","LONG","DOUBLE","DOUBLE","DOUBLE","DOUBLE"],"columnNames":["count(*)","countmv(intDimMV1)","avg(floatMetric1)","avgmv(intDimMV2)","minmaxrange(doubleMetric1)","minmaxrangemv(intDimMV2)"]},"rows":[[10,19,114.09000263214111,1516.9,250.00000000000003,6656.0]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScann [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["DOUBLE","DOUBLE","LONG","LONG","DOUBLE","DOUBLE"],"columnNames":["percentile(longDimSV1, 80.0)","percentilemv(intDimMV1, 90.0)","percentileest(longDimSV1, 80.0)","percentileestmv(intDimMV1, 90.0)","percentiletdigest(longDimSV1, 80.0)","percentiletdigestmv(intDimMV1, 90.0)"]},"rows":[[7611.0,462.0,7611,462,7611.0,462.0]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegme [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["INT","INT","LONG","LONG"],"columnNames":["distinctcount(longDimSV1)","distinctcountmv(intDimMV1)","distinctcounthll(longDimSV1)","distinctcounthllmv(intDimMV1)"]},"rows":[[6,8,6,8]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":10,"numEntriesScannedInFilter":0,"numEntriesScannedPostFilter":20,"numGroupsL [...]
+
+# Selection
+{"resultTable":{"dataSchema":{"columnDataTypes":["LONG","STRING","STRING","BYTES"],"columnNames":["longDimSV2","stringDimSV1","textDim1","bytesDimSV1"]},"rows":[[2,"s1-0","Java C++ Python","4877625602"],[2,"s1-0","Java C++ Python","01a0bc"],[21,"s1-2","Java C++ golang","13225573e3f5"],[21,"s1-2","Java C++ golang","deadbeef"],[22,"s1-4","Java C++ golang","deed0507"],[32,"s1-5","golang shell bash",""],[6777,"s1-7","golang Java","d54d0507"],[7621,"s1-6","C++ golang python","deed0507"],[7621 [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["LONG","STRING","STRING","BYTES"],"columnNames":["longDimSV2","stringDimSV1","textDim1","bytesDimSV1"]},"rows":[[7621,"s1-6","C++ golang python","deed0507"],[7621,"s1-6","C++ golang python","deed0507"],[7621,"s1-6","C++ golang python","deed0507"],[6777,"s1-7","golang Java","d54d0507"],[32,"s1-5","golang shell bash",""],[22,"s1-4","Java C++ golang","deed0507"],[21,"s1-2","Java C++ golang","13225573e3f5"],[21,"s1-2","Java C++ golang","deadbe [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["LONG","STRING","STRING","BYTES"],"columnNames":["longDimSV2","stringDimSV1","textDim1","bytesDimSV1"]},"rows":[[7621,"s1-6","C++ golang python","deed0507"],[7621,"s1-6","C++ golang python","deed0507"],[7621,"s1-6","C++ golang python","deed0507"],[6777,"s1-7","golang Java","d54d0507"],[32,"s1-5","golang shell bash",""],[22,"s1-4","Java C++ golang","deed0507"],[21,"s1-2","Java C++ golang","13225573e3f5"],[21,"s1-2","Java C++ golang","deadbe [...]
+
+# Selection & Filtering
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","LONG","DOUBLE"],"columnNames":["textDim1","longDimSV2","doubleMetric1"]},"rows":[["Java C++ golang",22,24.1],["C++ golang python",7621,263.1],["C++ golang python",7621,263.1],["C++ golang python",7621,263.1]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":4,"numEntriesScannedInFilter":10,"numEntr [...]
+{"isSuperset":true,"resultTable":{"dataSchema":{"columnDataTypes":["STRING","LONG","DOUBLE"],"columnNames":["textDim1","longDimSV2","doubleMetric1"]},"rows":[["Java C++ golang",22,24.1],["C++ golang python",7621,263.1],["C++ golang python",7621,263.1],["C++ golang python",7621,263.1]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":4,"numEntriesScannedInF [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","LONG","DOUBLE"],"columnNames":["textDim1","longDimSV2","doubleMetric1"]},"rows":[["Java C++ golang",22,24.1],["C++ golang python",7621,263.1],["C++ golang python",7621,263.1],["C++ golang python",7621,263.1]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":4,"numEntriesScannedInFilter":10,"numEntr [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","LONG","INT_ARRAY","INT_ARRAY","STRING_ARRAY"],"columnNames":["stringDimSV1","longDimSV1","intDimMV1","intDimMV2","stringDimMV2"]},"rows":[["s1-5",-9223372036854775808,[-2147483648],[92,22],["m2-2-0"]],["s1-2",11,[32,42],[62,72],["m2-2-0","m2-2-1"]],["s1-2",11,[32,42],[62,72],["m2-3-0","m2-3-1"]],["s1-4",41,[42,52],[72,82],["m2-2-0","m2-2-1"]]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1," [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","LONG","INT_ARRAY","INT_ARRAY","STRING_ARRAY"],"columnNames":["stringDimSV1","longDimSV1","intDimMV1","intDimMV2","stringDimMV2"]},"rows":[["s1-4",41,[42,52],[72,82],["m2-2-0","m2-2-1"]],["s1-2",11,[32,42],[62,72],["m2-2-0","m2-2-1"]],["s1-2",11,[32,42],[62,72],["m2-3-0","m2-3-1"]],["s1-5",-9223372036854775808,[-2147483648],[92,22],["m2-2-0"]]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1," [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","LONG","INT_ARRAY","INT_ARRAY","STRING_ARRAY"],"columnNames":["stringDimSV1","longDimSV1","intDimMV1","intDimMV2","stringDimMV2"]},"rows":[["s1-4",41,[42,52],[72,82],["m2-2-0","m2-2-1"]],["s1-2",11,[32,42],[62,72],["m2-3-0","m2-3-1"]],["s1-2",11,[32,42],[62,72],["m2-2-0","m2-2-1"]]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSeg [...]
+
+# Selection & Grouping on Aggregation
+{"resultTable":{"dataSchema":{"columnDataTypes":["LONG","INT","LONG"],"columnNames":["longDimSV1","intDimMV1","count(*)"]},"rows":[[-9223372036854775808,-2147483648,1],[1,3,2],[1,4,2],[11,42,2],[11,32,2]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":10,"numEntriesScannedInFilter":0,"numEntriesScannedPostFilter":20,"numGroupsLimitReached":false,"totalDo [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["LONG","INT","DOUBLE","DOUBLE","DOUBLE","DOUBLE","DOUBLE","DOUBLE"],"columnNames":["longDimSV1","intDimMV1","sum(intMetric1)","summv(intDimMV1)","min(intMetric1)","minmv(intDimMV2)","max(longDimSV1)","maxmv(intDimMV1)"]},"rows":[[-9223372036854775808,-2147483648,0.0,-2.147483648E9,0.0,22.0,-9.223372036854776E18,-2.147483648E9],[1,3,20.0,14.0,10.0,6.0,1.0,4.0],[1,4,20.0,14.0,10.0,6.0,1.0,4.0],[11,42,20.0,148.0,10.0,62.0,11.0,42.0],[11,32,20 [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["LONG","INT","LONG","LONG","DOUBLE","DOUBLE","DOUBLE","DOUBLE"],"columnNames":["longDimSV1","intDimMV1","count(*)","countmv(intDimMV1)","avg(floatMetric1)","avgmv(intDimMV2)","minmaxrange(doubleMetric1)","minmaxrangemv(intDimMV2)"]},"rows":[[-9223372036854775808,-2147483648,1,1,0.0,57.0,0.0,70.0],[1,3,2,4,12.100000381469727,6.5,0.0,1.0],[1,4,2,4,12.100000381469727,6.5,0.0,1.0],[11,42,2,4,22.100000381469727,67.0,0.0,10.0],[11,32,2,4,22.1000 [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["LONG","INT","DOUBLE","DOUBLE","LONG","LONG","DOUBLE","DOUBLE"],"columnNames":["longDimSV1","intDimMV1","percentile(longDimSV1, 80.0)","percentilemv(intDimMV1, 90.0)","percentileest(longDimSV1, 80.0)","percentileestmv(intDimMV1, 90.0)","percentiletdigest(longDimSV1, 80.0)","percentiletdigestmv(intDimMV1, 90.0)"]},"rows":[[-9223372036854775808,-2147483648,-9.223372036854776E18,-2.147483648E9,-9223372036854775808,-2147483648,-9.2233720368547 [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["LONG","INT","INT","INT","LONG","LONG"],"columnNames":["longDimSV1","intDimMV1","distinctcount(longDimSV1)","distinctcountmv(intDimMV1)","distinctcounthll(longDimSV1)","distinctcounthllmv(intDimMV1)"]},"rows":[[-9223372036854775808,-2147483648,1,1,1,1],[1,3,1,2,1,2],[1,4,1,2,1,2],[11,42,1,2,1,2],[11,32,1,2,1,2]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatche [...]
+
+# Selection & Filtering & Grouping on Aggregation
+{"resultTable":{"dataSchema":{"columnDataTypes":["LONG","INT","LONG"],"columnNames":["longDimSV1","intDimMV1","count(*)"]},"rows":[[-9223372036854775808,-2147483648,1],[11,32,2],[11,42,2],[41,42,1],[41,52,1]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":4,"numEntriesScannedInFilter":33,"numEntriesScannedPostFilter":8,"numGroupsLimitReached":false,"tota [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["LONG","INT","DOUBLE","DOUBLE","DOUBLE","DOUBLE","DOUBLE","DOUBLE"],"columnNames":["longDimSV1","intDimMV1","sum(intMetric1)","summv(intDimMV1)","min(intMetric1)","minmv(intDimMV2)","max(longDimSV1)","maxmv(intDimMV1)"]},"rows":[[-9223372036854775808,-2147483648,0,-2147483648,0,22,-9223372036854776000,-2147483648],[11,32,20,148,10,62,11,42],[11,42,20,148,10,62,11,42],[41,42,14,94,14,72,41,52],[41,52,14,94,14,72,41,52]]},"exceptions":[],"nu [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["LONG","INT","LONG","LONG","DOUBLE","DOUBLE","DOUBLE","DOUBLE"],"columnNames":["longDimSV1","intDimMV1","count(*)","countmv(intDimMV1)","avg(floatMetric1)","avgmv(intDimMV2)","minmaxrange(doubleMetric1)","minmaxrangemv(intDimMV2)"]},"rows":[[-9223372036854775808,-2147483648,1,1,0,57,0,70],[11,32,2,4,22.100000381469727,67,0,10],[11,42,2,4,22.100000381469727,67,0,10],[41,42,1,2,24.100000381469727,77,0,10],[41,52,1,2,24.100000381469727,77,0,1 [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["LONG","INT","DOUBLE","DOUBLE","LONG","LONG","DOUBLE","DOUBLE"],"columnNames":["longDimSV1","intDimMV1","percentile(longDimSV1, 80.0)","percentilemv(intDimMV1, 90.0)","percentileest(longDimSV1, 80.0)","percentileestmv(intDimMV1, 90.0)","percentiletdigest(longDimSV1, 80.0)","percentiletdigestmv(intDimMV1, 90.0)"]},"rows":[[-9223372036854775808,-2147483648,-9223372036854775808,-2147483648,-9223372036854775808,-2147483648,-9223372036854776000 [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["LONG","INT","INT","INT","LONG","LONG"],"columnNames":["longDimSV1","intDimMV1","distinctcount(longDimSV1)","distinctcountmv(intDimMV1)","distinctcounthll(longDimSV1)","distinctcounthllmv(intDimMV1)"]},"rows":[[-9223372036854775808,-2147483648,1,1,1,1],[11,32,1,2,1,2],[11,42,1,2,1,2],[41,42,1,2,1,2],[41,52,1,2,1,2]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMa [...]
+
+# Transformation Functions
+{"resultTable":{"dataSchema":{"columnDataTypes":["DOUBLE","DOUBLE","DOUBLE"],"columnNames":["add(longDimSV1,sub(longDimSV2,'3'))","mod(intMetric1,'10')","div(doubleMetric1,mult(floatMetric1,'5'))"]},"rows":[[15229.0,1.0,0.20076306285631254],[15229.0,7.0,0.20076306285631254],[15229.0,7.0,0.20076306285631254],[13540.0,7.0,0.20076306285631254],[60.0,4.0,0.1999999968342762],[29.0,0.0,0.20904977014723267],[29.0,0.0,0.20904977014723267],[0.0,0.0,0.21652891879345226],[0.0,0.0,0.2165289187934522 [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["DOUBLE","DOUBLE","DOUBLE"],"columnNames":["floor(sqrt(doubleMetric1))","ceil(ln(longDimSV1))","exp(mod(abs(longDimSV2),'3'))"]},"rows":[[3.0,0.0,7.38905609893065],[3.0,0.0,7.38905609893065],[4.0,3.0,1.0],[4.0,3.0,1.0],[4.0,4.0,2.718281828459045],[4.0,"NaN",7.38905609893065],[16.0,9.0,2.718281828459045],[16.0,9.0,2.718281828459045],[16.0,9.0,2.718281828459045],[16.0,9.0,1.0]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1," [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["LONG"],"columnNames":["count(*)"]},"rows":[[6],[1],[3]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":10,"numEntriesScannedInFilter":0,"numEntriesScannedPostFilter":20,"numGroupsLimitReached":false,"totalDocs":10,"timeUsedMs":9,"segmentStatistics":[],"traceInfo":{},"minConsumingFreshnessTimeMs":0}
+{"resultTable":{"dataSchema":{"columnDataTypes":["INT","LONG"],"columnNames":["valuein(intDimMV1,'3','32')","count(*)"]},"rows":[[3,2],[32,2]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":10,"numEntriesScannedInFilter":0,"numEntriesScannedPostFilter":10,"numGroupsLimitReached":false,"totalDocs":10,"timeUsedMs":18,"segmentStatistics":[],"traceInfo":{}," [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","STRING","STRING","STRING","STRING"],"columnNames":["upper(stringDimSV1)","lower(textDim1)","reverse(stringDimSV2)","ltrim(substr(textDim1,'4','9'))","rtrim(substr(textDim1,'4','9'))"]},"rows":[["S1-0","java c++ python","0-2s","C++ "," C++"],["S1-0","java c++ python","0-2s","C++ "," C++"],["S1-2","java c++ golang","2-2s","C++ "," C++"],["S1-2","java c++ golang","2-2s","C++ "," C++"],["S1-4","java c++ golang","4-2s","C++ "," C++"], [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","STRING","INT","STRING","STRING"],"columnNames":["stringDimSV2","replace(stringDimSV2,'foo','bar')","codepoint(stringDimSV2)","rpad(stringDimSV2,'11','abc')","lpad(stringDimSV2,'11','xyz')"]},"rows":[["s2-2","s2-2",115,"s2-2abcabca","xyzxyzxs2-2"],["s2-2","s2-2",115,"s2-2abcabca","xyzxyzxs2-2"]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"nu [...]
+
+# Groovy Scripts
+{"resultTable":{"dataSchema":{"columnDataTypes":["LONG","LONG","LONG"],"columnNames":["longDimSV1","longDimSV2","groovy('{\"returnType\":\"LONG\",\"isSingleValue\":true}','arg0 + arg1',longDimSV1,longDimSV2)"]},"rows":[[-9223372036854775808,32,-9223372036854775776],[1,2,3],[1,2,3],[11,21,32],[11,21,32],[41,22,63],[6766,6777,13543],[7611,7621,15232],[7611,7621,15232],[7611,7621,15232]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProces [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["LONG","STRING"],"columnNames":["count(*)","groovy('{\"returnType\":\"STRING\", \"isSingleValue\":true}','def result; if (arg0 < 0) { result = \"NEGATIVE\"; } else if (arg0 < 10) { result = \"SMALL\";} else if (arg0 < 50) { result = \"MEDIUM\";} else{result = \"LARGE\"}; return result',longDimSV1)"]},"rows":[[4,"LARGE"],[3,"MEDIUM"],[2,"SMALL"],[1,"NEGATIVE"]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueri [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["INT"],"columnNames":["groovy('{\"returnType\":\"INT\",\"isSingleValue\":true}','arg0.toList().max()',intDimMV1)"]},"rows":[[-2147483648],[4],[4],[42],[42],[52],[462],[462],[462],[462]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":10,"numEntriesScannedInFilter":0,"numEntriesScannedPostFilter":10,"numGrou [...]
+
+# Text Search
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","STRING"],"columnNames":["stringDimSV1","textDim1"]},"rows":[["s1-0","Java C++ Python"],["s1-0","Java C++ Python"],["s1-2","Java C++ golang"],["s1-2","Java C++ golang"],["s1-4","Java C++ golang"],["s1-7","golang Java"]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":6,"numEntriesScannedInFilter":0 [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","STRING"],"columnNames":["stringDimSV1","textDim1"]},"rows":[["s1-0","Java C++ Python"],["s1-0","Java C++ Python"],["s1-2","Java C++ golang"],["s1-2","Java C++ golang"],["s1-4","Java C++ golang"]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":5,"numEntriesScannedInFilter":0,"numEntriesScannedPost [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","STRING"],"columnNames":["stringDimSV1","textDim1"]},"rows":[["s1-4","Java C++ golang"],["s1-6","C++ golang python"],["s1-6","C++ golang python"],["s1-6","C++ golang python"],["s1-7","golang Java"]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":5,"numEntriesScannedInFilter":9,"numEntriesScannedPo [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","STRING"],"columnNames":["stringDimSV1","textDim1"]},"rows":[["s1-4","Java C++ golang"],["s1-6","C++ golang python"],["s1-6","C++ golang python"],["s1-6","C++ golang python"],["s1-7","golang Java"]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":5,"numEntriesScannedInFilter":9,"numEntriesScannedPo [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","STRING"],"columnNames":["stringDimSV1","textDim1"]},"rows":[["s1-0","Java C++ Python"],["s1-0","Java C++ Python"],["s1-2","Java C++ golang"],["s1-2","Java C++ golang"],["s1-4","Java C++ golang"]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":5,"numEntriesScannedInFilter":0,"numEntriesScannedPost [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","STRING"],"columnNames":["stringDimSV1","textDim1"]},"rows":[["s1-0","Java C++ Python"],["s1-0","Java C++ Python"],["s1-2","Java C++ golang"],["s1-2","Java C++ golang"],["s1-4","Java C++ golang"],["s1-6","C++ golang python"],["s1-6","C++ golang python"],["s1-6","C++ golang python"]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSeg [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","STRING"],"columnNames":["stringDimSV1","textDim1"]},"rows":[["s1-0","Java C++ Python"],["s1-0","Java C++ Python"],["s1-2","Java C++ golang"],["s1-2","Java C++ golang"],["s1-4","Java C++ golang"]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":5,"numEntriesScannedInFilter":0,"numEntriesScannedPost [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","STRING"],"columnNames":["stringDimSV1","textDim1"]},"rows":[["s1-4","Java C++ golang"],["s1-6","C++ golang python"],["s1-6","C++ golang python"],["s1-6","C++ golang python"],["s1-7","golang Java"]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":5,"numEntriesScannedInFilter":9,"numEntriesScannedPo [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","STRING"],"columnNames":["stringDimSV1","textDim1"]},"rows":[["s1-2","Java C++ golang"],["s1-2","Java C++ golang"],["s1-4","Java C++ golang"],["s1-5","golang shell bash"],["s1-6","C++ golang python"],["s1-6","C++ golang python"],["s1-6","C++ golang python"],["s1-7","golang Java"]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegme [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","STRING"],"columnNames":["stringDimSV1","textDim1"]},"rows":[["s1-2","Java C++ golang"],["s1-2","Java C++ golang"],["s1-4","Java C++ golang"],["s1-5","golang shell bash"],["s1-6","C++ golang python"],["s1-6","C++ golang python"],["s1-6","C++ golang python"],["s1-7","golang Java"]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegme [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","STRING"],"columnNames":["stringDimSV1","textDim1"]},"rows":[["s1-2","Java C++ golang"],["s1-2","Java C++ golang"],["s1-4","Java C++ golang"],["s1-5","golang shell bash"],["s1-6","C++ golang python"],["s1-6","C++ golang python"],["s1-6","C++ golang python"],["s1-7","golang Java"]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegme [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","LONG"],"columnNames":["stringDimSV1","count(*)"]},"rows":[["s1-2",2],["s1-0",2],["s1-7",1],["s1-4",1]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":6,"numEntriesScannedInFilter":0,"numEntriesScannedPostFilter":6,"numGroupsLimitReached":false,"totalDocs":10,"timeUsedMs":6,"segmentStatistics":[], [...]
+
+# Map
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","INT","INT"],"columnNames":["stringDimSV1","mapvalue(mapDim1__KEYS,'k1',mapDim1__VALUES)","mapvalue(mapDim1__KEYS,'k4',mapDim1__VALUES)"]},"rows":[["s1-0",1,2],["s1-0",3,3],["s1-2",4,7],["s1-2",7,7],["s1-4",7,8]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":5,"numEntriesScannedInFilter":0,"numEn [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","INT","INT"],"columnNames":["stringDimSV1","mapvalue(mapDim1__KEYS,'k1',mapDim1__VALUES)","mapvalue(mapDim1__KEYS,'k4',mapDim1__VALUES)"]},"rows":[["s1-0",1,2],["s1-0",3,3],["s1-2",4,7],["s1-4",7,8],["s1-2",7,7]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":10,"numEntriesScannedInFilter":0,"numE [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["DOUBLE","DOUBLE"],"columnNames":["max(mapvalue(mapDim1__KEYS,'k2',mapDim1__VALUES))","min(mapvalue(mapDim1__KEYS,'k3',mapDim1__VALUES))"]},"rows":[[31,2]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":10,"numEntriesScannedInFilter":0,"numEntriesScannedPostFilter":20,"numGroupsLimitReached":false,"totalDo [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["DOUBLE","DOUBLE"],"columnNames":["max(mapvalue(mapDim1__KEYS,'k2',mapDim1__VALUES))","min(mapvalue(mapDim1__KEYS,'k3',mapDim1__VALUES))"]},"rows":[[1,2],[3,3],[5,6],[8,7],[31,32]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":10,"numEntriesScannedInFilter":0,"numEntriesScannedPostFilter":20,"numGroupsLim [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["INT","INT"],"columnNames":["mapvalue(mapDim1__KEYS,'k1',mapDim1__VALUES)","mapvalue(mapDim1__KEYS,'k2',mapDim1__VALUES)"]},"rows":[[1,1],[3,3],[4,5]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":3,"numEntriesScannedInFilter":10,"numEntriesScannedPostFilter":6,"numGroupsLimitReached":false,"totalDocs":10 [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["INT","INT"],"columnNames":["mapvalue(mapDim1__KEYS,'k1',mapDim1__VALUES)","mapvalue(mapDim1__KEYS,'k2',mapDim1__VALUES)"]},"rows":[]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":0,"numConsumingSegmentsQueried":0,"numDocsScanned":0,"numEntriesScannedInFilter":10,"numEntriesScannedPostFilter":0,"numGroupsLimitReached":false,"totalDocs":10,"timeUsedMs":12, [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING"],"columnNames":["mapvalue(mapDim1__KEYS,'non-existing-key',mapDim1__VALUES)"]},"rows":[]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":0,"numSegmentsMatched":0,"numConsumingSegmentsQueried":0,"numDocsScanned":0,"numEntriesScannedInFilter":0,"numEntriesScannedPostFilter":0,"numGroupsLimitReached":false,"totalDocs":10,"timeUsedMs":3,"segmentStatistics":[],"traceInfo":{}, [...]
+
+# Json Map
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","INT","INT"],"columnNames":["stringDimSV1","jsonextractscalar(mapDim2json,'$.k1','INT')","jsonextractscalar(mapDim2json,'$.k4','INT')"]},"rows":[["s1-0",1,2],["s1-0",3,3],["s1-2",4,7],["s1-2",7,7],["s1-4",7,8]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":5,"numEntriesScannedInFilter":0,"numEntr [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","INT","INT"],"columnNames":["stringDimSV1","jsonextractscalar(mapDim2json,'$.k1','INT')","jsonextractscalar(mapDim2json,'$.k4','INT')"]},"rows":[["s1-0",1,2],["s1-0",3,3],["s1-2",4,7],["s1-4",7,8],["s1-2",7,7]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":10,"numEntriesScannedInFilter":0,"numEnt [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["DOUBLE","DOUBLE"],"columnNames":["max(jsonextractscalar(mapDim2json,'$.k2','INT'))","min(jsonextractscalar(mapDim2json,'$.k3','INT'))"]},"rows":[[31,2]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":10,"numEntriesScannedInFilter":0,"numEntriesScannedPostFilter":10,"numGroupsLimitReached":false,"totalDocs [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["DOUBLE","DOUBLE"],"columnNames":["max(jsonextractscalar(mapDim2json,'$.k2','INT'))","min(jsonextractscalar(mapDim2json,'$.k3','INT'))"]},"rows":[[1,2],[3,3],[5,6],[8,7],[31,32]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":10,"numEntriesScannedInFilter":0,"numEntriesScannedPostFilter":10,"numGroupsLimit [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["INT","INT"],"columnNames":["jsonextractscalar(mapDim2json,'$.k1','INT')","jsonextractscalar(mapDim2json,'$.k2','INT')"]},"rows":[[1,1],[3,3],[4,5]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":3,"numEntriesScannedInFilter":10,"numEntriesScannedPostFilter":3,"numGroupsLimitReached":false,"totalDocs":10," [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["INT"],"columnNames":["jsonextractscalar(mapDim2json,'$.non-existing-key','INT','-1')"]},"rows":[[-1],[-1],[-1],[-1],[-1],[-1],[-1],[-1],[-1],[-1]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":10,"numEntriesScannedInFilter":0,"numEntriesScannedPostFilter":10,"numGroupsLimitReached":false,"totalDocs":10," [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["INT"],"columnNames":["jsonextractscalar(mapDim2json,'$.non-existing-key','INT')"]},"rows":[]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":0,"numConsumingSegmentsQueried":0,"numDocsScanned":0,"numEntriesScannedInFilter":50,"numEntriesScannedPostFilter":0,"numGroupsLimitReached":false,"totalDocs":10,"timeUsedMs":7,"segmentStatistics":[],"traceInfo":{},"mi [...]
+
+# Misc
+{"resultTable":{"dataSchema":{"columnDataTypes":["LONG"],"columnNames":["count(*)"]},"rows":[[2],[1],[2]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":5,"numEntriesScannedInFilter":10,"numEntriesScannedPostFilter":5,"numGroupsLimitReached":false,"totalDocs":10,"timeUsedMs":6,"segmentStatistics":[],"traceInfo":{},"minConsumingFreshnessTimeMs":0}
+{"resultTable":{"dataSchema":{"columnDataTypes":["LONG"],"columnNames":["count(*)"]},"rows":[[6],[2],[2]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":10,"numEntriesScannedInFilter":16,"numEntriesScannedPostFilter":10,"numGroupsLimitReached":false,"totalDocs":10,"timeUsedMs":4,"segmentStatistics":[],"traceInfo":{},"minConsumingFreshnessTimeMs":0}
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","LONG","INT_ARRAY"],"columnNames":["stringDimSV1","longDimSV1","intDimMV1"]},"rows":[["s1-7",6766,[392,462]],["s1-6",7611,[392,462]],["s1-6",7611,[392,462]]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":10,"numEntriesScannedInFilter":0,"numEntriesScannedPostFilter":33,"numGroupsLimitReached":fal [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["STRING","LONG","INT_ARRAY"],"columnNames":["stringDimSV1","longDimSV1","intDimMV1"]},"rows":[["s1-7",6766,[392,462]],["s1-6",7611,[392,462]],["s1-6",7611,[392,462]]]},"exceptions":[],"numServersQueried":1,"numServersResponded":1,"numSegmentsQueried":1,"numSegmentsProcessed":1,"numSegmentsMatched":1,"numConsumingSegmentsQueried":0,"numDocsScanned":10,"numEntriesScannedInFilter":0,"numEntriesScannedPostFilter":33,"numGroupsLimitReached":fal [...]
+{"resultTable":{"dataSchema":{"columnDataTypes":["BYTES","DOUBLE","FLOAT","INT_ARRAY","INT_ARRAY","INT","LONG","LONG","LONG","STRING_ARRAY","INT_ARRAY","STRING","STRING_ARRAY","STRING_ARRAY","STRING","STRING","STRING"],"columnNames":["bytesDimSV1","doubleMetric1","floatMetric1","intDimMV1","intDimMV2","intMetric1","longDimSV1","longDimSV2","longMetric1","mapDim1__KEYS","mapDim1__VALUES","mapDim2json","stringDimMV1","stringDimMV2","stringDimSV1","stringDimSV2","textDim1"]},"rows":[["deed0 [...]
\ No newline at end of file
diff --git a/pinot-integration-tests/src/test/resources/compat-tests/table-segment-op.yaml b/pinot-integration-tests/src/test/resources/compat-tests/table-segment-op.yaml
index 9379db7..58f7eae 100644
--- a/pinot-integration-tests/src/test/resources/compat-tests/table-segment-op.yaml
+++ b/pinot-integration-tests/src/test/resources/compat-tests/table-segment-op.yaml
@@ -38,3 +38,8 @@ operations:
       op: DELETE
       tableConfigFileName: pinot-integration-tests/src/test/resources/compat-tests/configs/feature-test-1.json
       segmentName: FeatureTest1_Segment
+    - type: tableOp
+      description: Delete table feature-test-1.json
+      op: DELETE
+      schemaFileName: pinot-integration-tests/src/test/resources/compat-tests/configs/FeatureTest1-schema.json
+      tableConfigFileName: pinot-integration-tests/src/test/resources/compat-tests/configs/feature-test-1.json


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org