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