diff --git a/.github/workflows/test-other-modules.yml b/.github/workflows/test-other-modules.yml
index 3c3f84817a0d1..b2fec9efd4cb0 100644
--- a/.github/workflows/test-other-modules.yml
+++ b/.github/workflows/test-other-modules.yml
@@ -64,6 +64,7 @@ jobs:
run: |
./mvnw test -T 1 ${MAVEN_TEST} -pl '
!presto-tests,
+ !presto-native-tests,
!presto-accumulo,
!presto-cassandra,
!presto-hive,
diff --git a/pom.xml b/pom.xml
index 54bf984a68083..8c4d64638dad3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -195,6 +195,7 @@
presto-test-coverage
presto-hudi
presto-native-execution
+ presto-native-tests
presto-router
presto-open-telemetry
redis-hbo-provider
diff --git a/presto-native-tests/README.md b/presto-native-tests/README.md
new file mode 100644
index 0000000000000..a882b2a33b463
--- /dev/null
+++ b/presto-native-tests/README.md
@@ -0,0 +1,31 @@
+# Presto Native Tests
+
+This module contains end-to-end tests that run queries from test classes in
+the `presto-tests` module with Presto C++ workers. Please build the module
+`presto-native-execution` first.
+
+The following command can be used to run all tests in this module:
+```
+mvn test
+ -pl 'presto-native-tests'
+ -Dtest="com.facebook.presto.nativetests.Test*"
+ -Duser.timezone=America/Bahia_Banderas
+ -DPRESTO_SERVER=${PRESTO_HOME}/presto-native-execution/cmake-build-debug/presto_cpp/main/presto_server
+ -DWORKER_COUNT=${WORKER_COUNT} -T1C
+```
+Please update JVM argument `PRESTO_SERVER` to point to the Presto C++ worker
+binary `presto_server`.
+
+## Adding new tests
+
+Presto C++ currently does not have the same behavior as Presto for certain
+queries. This could be because of missing types, missing function signatures,
+among other reasons. Tests with these unsupported queries are therefore
+expected to fail and the test asserts the error message is as expected.
+
+Issues should also be created for the failing queries, so they are documented
+and fixed. Please add the tag `presto-native-tests` for these issues.
+Once all the failures in a testcase are fixed, the overriden test in this
+module should be removed and the testcase in the corresponding base class in
+`presto-tests` would be the single source of truth for Presto SQL coverage
+tests.
diff --git a/presto-native-tests/pom.xml b/presto-native-tests/pom.xml
new file mode 100644
index 0000000000000..c38fd6ecfb793
--- /dev/null
+++ b/presto-native-tests/pom.xml
@@ -0,0 +1,121 @@
+
+
+ 4.0.0
+
+
+ com.facebook.presto
+ presto-root
+ 0.290-SNAPSHOT
+
+
+ presto-native-tests
+ presto-native-tests
+ Presto Native Tests
+
+
+ ${project.parent.basedir}
+
+
+
+
+ org.testng
+ testng
+
+
+
+ com.facebook.presto
+ presto-native-execution
+ 0.290-SNAPSHOT
+ test-jar
+ test
+
+
+
+ com.facebook.presto
+ presto-common
+
+
+
+
+ com.facebook.presto
+ presto-spi
+
+
+
+ com.facebook.presto
+ presto-main
+
+
+
+ com.facebook.presto
+ presto-tests
+
+
+
+ com.google.guava
+ guava
+
+
+
+ com.facebook.presto
+ presto-tpcds
+ test
+
+
+
+ org.jetbrains
+ annotations
+ test
+
+
+
+
+
+
+
+ pl.project13.maven
+ git-commit-id-plugin
+
+ true
+
+
+
+ org.basepom.maven
+ duplicate-finder-maven-plugin
+
+
+ parquet.thrift
+ about.html
+ mozilla/public-suffix-list.txt
+ iceberg-build.properties
+ org.apache.avro.data/Json.avsc
+
+
+ com.esotericsoftware.kryo.*
+ com.esotericsoftware.minlog.Log
+ com.esotericsoftware.reflectasm.*
+ module-info
+ META-INF.versions.9.module-info
+ org.apache.avro.*
+ com.github.benmanes.caffeine.*
+ org.roaringbitmap.*
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ -Xms4g -Xmx4g
+ 1
+ false
+ remote-function,textfile_reader
+
+ /root/project/build/debug/presto_cpp/main/presto_server
+
+
+
+
+
+
diff --git a/presto-native-tests/src/test/java/com.facebook.presto.nativetests/AbstractTestAggregationsNative.java b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/AbstractTestAggregationsNative.java
new file mode 100644
index 0000000000000..7f0cdaec6f12c
--- /dev/null
+++ b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/AbstractTestAggregationsNative.java
@@ -0,0 +1,223 @@
+/*
+ * Licensed 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 com.facebook.presto.nativetests;
+
+import com.facebook.presto.tests.AbstractTestAggregations;
+import org.testng.annotations.Test;
+
+import static java.lang.String.format;
+
+public abstract class AbstractTestAggregationsNative
+ extends AbstractTestAggregations
+{
+ private static final String approxDistributionTypesUnsupportedError = ".*Failed to parse type.*digest.*";
+
+ @Override
+ @Test
+ public void testApproximateCountDistinct()
+ {
+ String signatureUnsupportedError = ".*Aggregate function signature is not supported: presto.default.approx_distinct*";
+ String timeTypeUnsupportedError = "Failed to parse type.*time";
+ String charTypeUnsupportedError = "Failed to parse type.*char";
+ String tsWithTzTypeUnsupportedError = "Timestamp with Timezone type is not supported in Prestissimo";
+
+ // test NULL
+ assertQueryFails("SELECT approx_distinct(NULL)", signatureUnsupportedError, true);
+ assertQueryFails("SELECT approx_distinct(NULL, 0.023)", signatureUnsupportedError, true);
+
+ // test date
+ assertQuery("SELECT approx_distinct(orderdate) FROM orders", "SELECT 2372");
+ assertQuery("SELECT approx_distinct(orderdate, 0.023) FROM orders", "SELECT 2372");
+
+ // test timestamp
+ assertQuery("SELECT approx_distinct(CAST(orderdate AS TIMESTAMP)) FROM orders", "SELECT 2347");
+ assertQuery("SELECT approx_distinct(CAST(orderdate AS TIMESTAMP), 0.023) FROM orders", "SELECT 2347");
+
+ // test timestamp with time zone
+ assertQueryFails("SELECT approx_distinct(CAST(orderdate AS TIMESTAMP WITH TIME ZONE)) FROM orders",
+ tsWithTzTypeUnsupportedError, true);
+ assertQueryFails("SELECT approx_distinct(CAST(orderdate AS TIMESTAMP WITH TIME ZONE), 0.023) FROM orders",
+ tsWithTzTypeUnsupportedError, true);
+
+ // test time
+ assertQueryFails("SELECT approx_distinct(CAST(from_unixtime(custkey) AS TIME)) FROM orders", timeTypeUnsupportedError, true);
+ assertQueryFails("SELECT approx_distinct(CAST(from_unixtime(custkey) AS TIME), 0.023) FROM orders", timeTypeUnsupportedError, true);
+
+ // test time with time zone
+ assertQueryFails("SELECT approx_distinct(CAST(from_unixtime(custkey) AS TIME WITH TIME ZONE)) FROM orders", timeTypeUnsupportedError, true);
+ assertQueryFails("SELECT approx_distinct(CAST(from_unixtime(custkey) AS TIME WITH TIME ZONE), 0.023) FROM orders", timeTypeUnsupportedError, true);
+
+ // test short decimal
+ assertQuery("SELECT approx_distinct(CAST(custkey AS DECIMAL(18, 0))) FROM orders", "SELECT 990");
+ assertQuery("SELECT approx_distinct(CAST(custkey AS DECIMAL(18, 0)), 0.023) FROM orders", "SELECT 990");
+
+ // test long decimal
+ assertQuery("SELECT approx_distinct(CAST(custkey AS DECIMAL(25, 20))) FROM orders", "SELECT 1013");
+ assertQuery("SELECT approx_distinct(CAST(custkey AS DECIMAL(25, 20)), 0.023) FROM orders", "SELECT 1013");
+
+ // test real
+ assertQuery("SELECT approx_distinct(CAST(custkey AS REAL)) FROM orders", "SELECT 982");
+ assertQuery("SELECT approx_distinct(CAST(custkey AS REAL), 0.023) FROM orders", "SELECT 982");
+
+ // test bigint
+ assertQuery("SELECT approx_distinct(custkey) FROM orders", "SELECT 990");
+ assertQuery("SELECT approx_distinct(custkey, 0.023) FROM orders", "SELECT 990");
+
+ // test integer
+ assertQuery("SELECT approx_distinct(CAST(custkey AS INTEGER)) FROM orders", "SELECT 1028");
+ assertQuery("SELECT approx_distinct(CAST(custkey AS INTEGER), 0.023) FROM orders", "SELECT 1028");
+
+ // test smallint
+ assertQuery("SELECT approx_distinct(CAST(custkey AS SMALLINT)) FROM orders", "SELECT 1023");
+ assertQuery("SELECT approx_distinct(CAST(custkey AS SMALLINT), 0.023) FROM orders", "SELECT 1023");
+
+ // test tinyint
+ assertQuery("SELECT approx_distinct(CAST((custkey % 128) AS TINYINT)) FROM orders", "SELECT 128");
+ assertQuery("SELECT approx_distinct(CAST((custkey % 128) AS TINYINT), 0.023) FROM orders", "SELECT 128");
+
+ // test double
+ assertQuery("SELECT approx_distinct(CAST(custkey AS DOUBLE)) FROM orders", "SELECT 1014");
+ assertQuery("SELECT approx_distinct(CAST(custkey AS DOUBLE), 0.023) FROM orders", "SELECT 1014");
+
+ // test varchar
+ assertQuery("SELECT approx_distinct(CAST(custkey AS VARCHAR)) FROM orders", "SELECT 1036");
+ assertQuery("SELECT approx_distinct(CAST(custkey AS VARCHAR), 0.023) FROM orders", "SELECT 1036");
+
+ // test char
+ assertQueryFails("SELECT approx_distinct(CAST(CAST(custkey AS VARCHAR) AS CHAR(20))) FROM orders", charTypeUnsupportedError, true);
+ assertQueryFails("SELECT approx_distinct(CAST(CAST(custkey AS VARCHAR) AS CHAR(20)), 0.023) FROM orders", charTypeUnsupportedError, true);
+
+ // test varbinary
+ assertQuery("SELECT approx_distinct(to_utf8(CAST(custkey AS VARCHAR))) FROM orders", "SELECT 1036");
+ assertQuery("SELECT approx_distinct(to_utf8(CAST(custkey AS VARCHAR)), 0.023) FROM orders", "SELECT 1036");
+ }
+
+ @Override
+ @Test(dataProvider = "getType")
+ public void testStatisticalDigest(String type)
+ {
+ assertQueryFails(format("SELECT value_at_quantile(%s_agg(CAST(orderkey AS DOUBLE)), 0.5E0) > 0 FROM lineitem", type), approxDistributionTypesUnsupportedError, true);
+ assertQueryFails(format("SELECT value_at_quantile(%s_agg(CAST(quantity AS DOUBLE)), 0.5E0) > 0 FROM lineitem", type), approxDistributionTypesUnsupportedError, true);
+ assertQueryFails(format("SELECT value_at_quantile(%s_agg(CAST(quantity AS DOUBLE)), 0.5E0) > 0 FROM lineitem", type), approxDistributionTypesUnsupportedError, true);
+ assertQueryFails(format("SELECT value_at_quantile(%s_agg(CAST(orderkey AS DOUBLE), 2), 0.5E0) > 0 FROM lineitem", type), approxDistributionTypesUnsupportedError, true);
+ assertQueryFails(format("SELECT value_at_quantile(%s_agg(CAST(quantity AS DOUBLE), 3), 0.5E0) > 0 FROM lineitem", type), approxDistributionTypesUnsupportedError, true);
+ assertQueryFails(format("SELECT value_at_quantile(%s_agg(CAST(quantity AS DOUBLE), 4), 0.5E0) > 0 FROM lineitem", type), approxDistributionTypesUnsupportedError, true);
+ assertQueryFails(format("SELECT value_at_quantile(%s_agg(CAST(orderkey AS DOUBLE), 2, 0.0001E0), 0.5E0) > 0 FROM lineitem", type), approxDistributionTypesUnsupportedError, true);
+ assertQueryFails(format("SELECT value_at_quantile(%s_agg(CAST(quantity AS DOUBLE), 3, 0.0001E0), 0.5E0) > 0 FROM lineitem", type), approxDistributionTypesUnsupportedError, true);
+ assertQueryFails(format("SELECT value_at_quantile(%s_agg(CAST(quantity AS DOUBLE), 4, 0.0001E0), 0.5E0) > 0 FROM lineitem", type), approxDistributionTypesUnsupportedError, true);
+ }
+
+ /**
+ * Comprehensive correctness testing is done in the TestQuantileDigestAggregationFunction and TestTDigestAggregationFunction
+ */
+ @Override
+ @Test(dataProvider = "getType")
+ public void testStatisticalDigestGroupBy(String type)
+ {
+ assertQueryFails(format("SELECT partkey, value_at_quantile(%s_agg(CAST(orderkey AS DOUBLE)), 0.5E0) > 0 FROM lineitem GROUP BY partkey", type),
+ approxDistributionTypesUnsupportedError, true);
+ assertQueryFails(format("SELECT partkey, value_at_quantile(%s_agg(CAST(quantity AS DOUBLE)), 0.5E0) > 0 FROM lineitem GROUP BY partkey", type),
+ approxDistributionTypesUnsupportedError, true);
+ assertQueryFails(format("SELECT partkey, value_at_quantile(%s_agg(CAST(quantity AS DOUBLE)), 0.5E0) > 0 FROM lineitem GROUP BY partkey", type),
+ approxDistributionTypesUnsupportedError, true);
+ assertQueryFails(format("SELECT partkey, value_at_quantile(%s_agg(CAST(orderkey AS DOUBLE), 2), 0.5E0) > 0 FROM lineitem GROUP BY partkey", type),
+ approxDistributionTypesUnsupportedError, true);
+ assertQueryFails(format("SELECT partkey, value_at_quantile(%s_agg(CAST(quantity AS DOUBLE), 3), 0.5E0) > 0 FROM lineitem GROUP BY partkey", type),
+ approxDistributionTypesUnsupportedError, true);
+ assertQueryFails(format("SELECT partkey, value_at_quantile(%s_agg(CAST(quantity AS DOUBLE), 4), 0.5E0) > 0 FROM lineitem GROUP BY partkey", type),
+ approxDistributionTypesUnsupportedError, true);
+ assertQueryFails(format("SELECT partkey, value_at_quantile(%s_agg(CAST(orderkey AS DOUBLE), 2, 0.0001E0), 0.5E0) > 0 FROM lineitem GROUP BY partkey", type),
+ approxDistributionTypesUnsupportedError, true);
+ assertQueryFails(format("SELECT partkey, value_at_quantile(%s_agg(CAST(quantity AS DOUBLE), 3, 0.0001E0), 0.5E0) > 0 FROM lineitem GROUP BY partkey", type),
+ approxDistributionTypesUnsupportedError, true);
+ assertQueryFails(format("SELECT partkey, value_at_quantile(%s_agg(CAST(quantity AS DOUBLE), 4, 0.0001E0), 0.5E0) > 0 FROM lineitem GROUP BY partkey", type),
+ approxDistributionTypesUnsupportedError, true);
+ }
+
+ /**
+ * Comprehensive correctness testing is done in the TestMergeQuantileDigestFunction and TestMergeTDigestFunction
+ */
+ @Override
+ @Test(dataProvider = "getType")
+ public void testStatisticalDigestMerge(String type)
+ {
+ assertQueryFails(format("SELECT value_at_quantile(merge(%s), 0.5E0) > 0 FROM (SELECT partkey, %s_agg(CAST(orderkey AS DOUBLE)) as %s FROM lineitem GROUP BY partkey)",
+ type,
+ type,
+ type),
+ approxDistributionTypesUnsupportedError, true);
+ }
+
+ /**
+ * Comprehensive correctness testing is done in the TestMergeQuantileDigestFunction and TestMergeTDigestFunction
+ */
+ @Override
+ @Test(dataProvider = "getType")
+ public void testStatisticalDigestMergeGroupBy(String type)
+ {
+ assertQueryFails(format("SELECT partkey, value_at_quantile(merge(%s), 0.5E0) > 0 " +
+ "FROM (SELECT partkey, suppkey, %s_agg(CAST(orderkey AS DOUBLE)) as %s FROM lineitem GROUP BY partkey, suppkey)" +
+ "GROUP BY partkey",
+ type,
+ type,
+ type),
+ approxDistributionTypesUnsupportedError, true);
+ }
+
+ @Override
+ @Test
+ public void testSumDataSizeForStats()
+ {
+ // varchar
+ assertQuery("SELECT \"sum_data_size_for_stats\"(comment) FROM orders", "SELECT 787364");
+
+ // char
+ // Presto removes trailing whitespaces when casting to CHAR.
+ // Hard code the expected data size since there is no easy to way to compute it in H2.
+ assertQueryFails("SELECT \"sum_data_size_for_stats\"(CAST(comment AS CHAR(1000))) FROM orders",
+ "Failed to parse type \\[char\\(1000\\)]", true);
+
+ // varbinary
+ assertQuery("SELECT \"sum_data_size_for_stats\"(CAST(comment AS VARBINARY)) FROM orders", "SELECT 787364");
+
+ // array
+ assertQuery("SELECT \"sum_data_size_for_stats\"(ARRAY[comment]) FROM orders", "SELECT 847364");
+ assertQuery("SELECT \"sum_data_size_for_stats\"(ARRAY[comment, comment]) FROM orders", "SELECT 1634728");
+
+ // map
+ assertQuery("SELECT \"sum_data_size_for_stats\"(map(ARRAY[1], ARRAY[comment])) FROM orders", "SELECT 907364");
+ assertQuery("SELECT \"sum_data_size_for_stats\"(map(ARRAY[1, 2], ARRAY[comment, comment])) FROM orders", "SELECT 1754728");
+
+ // row
+ assertQuery("SELECT \"sum_data_size_for_stats\"(ROW(comment)) FROM orders", "SELECT 847364");
+ assertQuery("SELECT \"sum_data_size_for_stats\"(ROW(comment, comment)) FROM orders", "SELECT 1634728");
+ }
+
+ @Override
+ @Test
+ public void testMaxDataSizeForStats()
+ {
+ // varchar
+ assertQuery("SELECT \"max_data_size_for_stats\"(comment) FROM orders", "select 82");
+
+ // char
+ assertQueryFails("SELECT \"max_data_size_for_stats\"(CAST(comment AS CHAR(1000))) FROM orders",
+ "Failed to parse type \\[char\\(1000\\)]", true);
+
+ // varbinary
+ assertQuery("SELECT \"max_data_size_for_stats\"(CAST(comment AS VARBINARY)) FROM orders", "select 82");
+
+ // max_data_size_for_stats is not needed for array, map and row
+ }
+}
diff --git a/presto-native-tests/src/test/java/com.facebook.presto.nativetests/AbstractTestQueriesNative.java b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/AbstractTestQueriesNative.java
new file mode 100644
index 0000000000000..939b79d66f399
--- /dev/null
+++ b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/AbstractTestQueriesNative.java
@@ -0,0 +1,1613 @@
+package com.facebook.presto.nativetests;
+
+/*
+ * Licensed 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.
+ */
+
+import com.facebook.presto.Session;
+import com.facebook.presto.spi.PrestoException;
+import com.facebook.presto.testing.MaterializedResult;
+import com.facebook.presto.testing.MaterializedRow;
+import com.facebook.presto.tests.AbstractTestQueries;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import org.intellij.lang.annotations.Language;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static com.facebook.presto.SystemSessionProperties.FIELD_NAMES_IN_JSON_CAST_ENABLED;
+import static com.facebook.presto.SystemSessionProperties.KEY_BASED_SAMPLING_ENABLED;
+import static com.facebook.presto.SystemSessionProperties.KEY_BASED_SAMPLING_PERCENTAGE;
+import static com.facebook.presto.SystemSessionProperties.LEGACY_UNNEST;
+import static com.facebook.presto.SystemSessionProperties.MERGE_AGGREGATIONS_WITH_AND_WITHOUT_FILTER;
+import static com.facebook.presto.SystemSessionProperties.OPTIMIZE_HASH_GENERATION;
+import static com.facebook.presto.SystemSessionProperties.PREFILTER_FOR_GROUPBY_LIMIT;
+import static com.facebook.presto.SystemSessionProperties.PREFILTER_FOR_GROUPBY_LIMIT_TIMEOUT_MS;
+import static com.facebook.presto.SystemSessionProperties.REMOVE_MAP_CAST;
+import static com.facebook.presto.SystemSessionProperties.REMOVE_REDUNDANT_CAST_TO_VARCHAR_IN_JOIN;
+import static com.facebook.presto.common.type.BigintType.BIGINT;
+import static com.facebook.presto.testing.MaterializedResult.resultBuilder;
+import static com.facebook.presto.testing.assertions.Assert.assertEquals;
+import static com.facebook.presto.tests.QueryAssertions.assertEqualsIgnoreOrder;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+public abstract class AbstractTestQueriesNative
+ extends AbstractTestQueries
+{
+ private static final String UNSUPPORTED_CORRELATED_SUBQUERY_ERROR_MSG = "line .*: Given correlated subquery is not supported";
+ private static final String p4HlltimestampTzTypeUnsupportedError = ".*Failed to parse type \\[P4HyperLogLog]. Type not registered.*";
+ private static final String applyNotRegisteredError = ".*Scalar function name not registered: presto.default.apply.*";
+ private static final String failNotRegisteredError = ".*Scalar function name not registered: presto.default.fail.*";
+ private static final String kp4HlltimestampTzTypeUnsupportedError = ".*inferredType Failed to parse type \\[KHyperLogLog]. Type not registered.*";
+ private static final String chartimestampTzTypeUnsupportedError = ".*Failed to parse type \\[char\\(.*\\)]. syntax error, unexpected LPAREN, expecting WORD.*";
+ private static final String timestampTzTypeUnsupportedError = ".*Timestamp with Timezone type is not supported in Prestissimo.*";
+ private static final String hashGenerationUnsupportedError = ".*Scalar function name not registered: presto.default.\\$operator\\$hash_code.*";
+ private static final String arrayComparisonUnsupportedError = ".*ARRAY comparison not supported for values that contain nulls.*";
+
+ @Override
+ @DataProvider(name = "optimize_hash_generation")
+ public Object[][] optimizeHashGeneration()
+ {
+ return new Object[][] {{"true"}};
+ }
+
+ @DataProvider(name = "use_default_literal_coalesce")
+ public static Object[][] useDefaultLiteralCoalesce()
+ {
+ return new Object[][] {{true}};
+ }
+
+ @Override
+ @Test
+ public void testCustomAdd()
+ {
+ assertQueryFails(
+ "SELECT custom_add(orderkey, custkey) FROM orders",
+ " Scalar function name not registered: presto.default.custom_add, called with arguments: \\(BIGINT, BIGINT\\).");
+ }
+
+ @Override
+ @Test
+ public void testCustomSum()
+ {
+ @Language("SQL") String sql = "SELECT orderstatus, custom_sum(orderkey) FROM orders GROUP BY orderstatus";
+ assertQueryFails(sql, " Aggregate function not registered: presto.default.custom_sum");
+ }
+
+ @Override
+ @Test
+ public void testCustomRank()
+ {
+ @Language("SQL") String sql = "" +
+ "SELECT orderstatus, clerk, sales\n" +
+ ", custom_rank() OVER (PARTITION BY orderstatus ORDER BY sales DESC) rnk\n" +
+ "FROM (\n" +
+ " SELECT orderstatus, clerk, sum(totalprice) sales\n" +
+ " FROM orders\n" +
+ " GROUP BY orderstatus, clerk\n" +
+ ")\n" +
+ "ORDER BY orderstatus, clerk";
+
+ assertQueryFails(sql, " Window function not registered: presto.default.custom_rank");
+ }
+
+ @Override
+ @Test
+ public void testApproxMostFrequentWithLong()
+ {
+ MaterializedResult actual1 = computeActual("SELECT approx_most_frequent(3, cast(x as bigint), 15) FROM (values 1, 2, 1, 3, 1, 2, 3, 4, 5) t(x)");
+ assertEquals(actual1.getRowCount(), 1);
+ assertEquals(actual1.getMaterializedRows().get(0).getFields().get(0), ImmutableMap.of(1L, 3L, 2L, 2L, 3L, 2L));
+
+ MaterializedResult actual2 = computeActual("SELECT approx_most_frequent(2, cast(x as bigint), 15) FROM (values 1, 2, 1, 3, 1, 2, 3, 4, 5) t(x)");
+ assertEquals(actual2.getRowCount(), 1);
+ assertEquals(actual2.getMaterializedRows().get(0).getFields().get(0), ImmutableMap.of(1L, 3L, 3L, 2L));
+ }
+
+ @Override
+ @Test
+ public void testGroupByLimit()
+ {
+ Session prefilter = Session.builder(getSession())
+ .setSystemProperty(PREFILTER_FOR_GROUPBY_LIMIT, "true")
+ .build();
+ MaterializedResult result1 = computeActual(prefilter, "select count(shipdate), orderkey from lineitem group by orderkey limit 100000");
+ MaterializedResult result2 = computeActual("select count(shipdate), orderkey from lineitem group by orderkey limit 100000");
+ assertEqualsIgnoreOrder(result1, result2, "Prefilter and without prefilter don't give matching results");
+
+ assertQueryFails(prefilter, "select count(custkey), orderkey from orders where orderstatus='F' and orderkey < 50 group by orderkey limit 100", hashGenerationUnsupportedError, true);
+ assertQuery(prefilter, "select count(1) from (select count(custkey), orderkey from orders where orderstatus='F' and orderkey < 50 group by orderkey limit 4)", "select 4");
+ assertQuery(prefilter, "select count(comment), orderstatus from (select upper(comment) comment, upper(orderstatus) orderstatus from orders where orderkey < 50) group by orderstatus limit 100", "values (5, 'F'), (10, 'O')");
+
+ assertQuery(prefilter, "select count(comment), orderstatus from (select upper(comment) comment, upper(orderstatus) orderstatus from orders where orderkey < 50) group by orderstatus having count(1) > 1 limit 100", "values (5, 'F'), (10, 'O')");
+
+ prefilter = Session.builder(getSession())
+ .setSystemProperty(PREFILTER_FOR_GROUPBY_LIMIT, "true")
+ .setSystemProperty(PREFILTER_FOR_GROUPBY_LIMIT_TIMEOUT_MS, "1")
+ .build();
+
+ result1 = computeActual(prefilter, "select count(shipdate), orderkey from lineitem group by orderkey limit 100000");
+ result2 = computeActual("select count(shipdate), orderkey from lineitem group by orderkey limit 100000");
+ assertEqualsIgnoreOrder(result1, result2, "Prefilter and without prefilter don't give matching results");
+
+ assertQuery(prefilter, "select count(1) from (select count(custkey), orderkey from orders group by orderkey limit 100000)", "values 15000");
+ assertQuery(prefilter, "select count(1) from (select count(custkey), orderkey from orders group by orderkey limit 4)", "select 4");
+ assertQuery(prefilter, "select count(1) from (select count(comment), orderstatus from (select upper(comment) comment, upper(orderstatus) orderstatus from orders) group by orderstatus limit 100000)", "values 3");
+ }
+
+ @Override
+ @Test
+ public void testValuesWithTimestamp()
+ {
+ assertQueryFails("VALUES (current_timestamp, now())", timestampTzTypeUnsupportedError, true);
+ }
+
+ @Override
+ @Test
+ public void testTryLambdaRepeated()
+ {
+ assertQueryFails("SELECT x + x FROM (SELECT apply(a, i -> i * i) x FROM (VALUES 3) t(a))", applyNotRegisteredError, true);
+ assertQueryFails("SELECT apply(a, i -> i * i) + apply(a, i -> i * i) FROM (VALUES 3) t(a)", applyNotRegisteredError, true);
+ assertQueryFails("SELECT apply(a, i -> i * i), apply(a, i -> i * i) FROM (VALUES 3) t(a)", applyNotRegisteredError, true);
+ assertQuery("SELECT try(10 / a) + try(10 / a) FROM (VALUES 5) t(a)", "SELECT 4");
+ assertQuery("SELECT try(10 / a), try(10 / a) FROM (VALUES 5) t(a)", "SELECT 2, 2");
+ }
+
+ @Override
+ @Test
+ public void testLambdaCapture()
+ {
+ // Test for lambda expression without capture can be found in TestLambdaExpression
+
+ assertQueryFails("SELECT apply(0, x -> x + c1) FROM (VALUES 1) t(c1)", applyNotRegisteredError, true);
+ assertQueryFails("SELECT apply(0, x -> x + t.c1) FROM (VALUES 1) t(c1)", applyNotRegisteredError, true);
+ assertQueryFails("SELECT apply(c1, x -> x + c2) FROM (VALUES (1, 2), (3, 4), (5, 6)) t(c1, c2)", applyNotRegisteredError, true);
+ assertQueryFails("SELECT apply(c1 + 10, x -> apply(x + 100, y -> c1)) FROM (VALUES 1) t(c1)", applyNotRegisteredError, true);
+ assertQueryFails("SELECT apply(c1 + 10, x -> apply(x + 100, y -> t.c1)) FROM (VALUES 1) t(c1)", applyNotRegisteredError, true);
+ assertQueryFails("SELECT apply(CAST(ROW(10) AS ROW(x INTEGER)), r -> r.x)", applyNotRegisteredError, true);
+ assertQueryFails("SELECT apply(CAST(ROW(10) AS ROW(x INTEGER)), r -> r.x) FROM (VALUES 1) u(x)", applyNotRegisteredError, true);
+ assertQueryFails("SELECT apply(CAST(ROW(10) AS ROW(x INTEGER)), r -> r.x) FROM (VALUES 1) r(x)", applyNotRegisteredError, true);
+ assertQueryFails("SELECT apply(CAST(ROW(10) AS ROW(x INTEGER)), r -> apply(3, y -> y + r.x)) FROM (VALUES 1) u(x)", applyNotRegisteredError, true);
+ assertQueryFails("SELECT apply(CAST(ROW(10) AS ROW(x INTEGER)), r -> apply(3, y -> y + r.x)) FROM (VALUES 1) r(x)", applyNotRegisteredError, true);
+ assertQueryFails("SELECT apply(CAST(ROW(10) AS ROW(x INTEGER)), r -> apply(3, y -> y + r.x)) FROM (VALUES 'a') r(x)", applyNotRegisteredError, true);
+ assertQueryFails("SELECT apply(CAST(ROW(10) AS ROW(x INTEGER)), z -> apply(3, y -> y + r.x)) FROM (VALUES 1) r(x)", applyNotRegisteredError, true);
+
+ // reference lambda variable of the not-immediately-enclosing lambda
+ assertQueryFails("SELECT apply(1, x -> apply(10, y -> x)) FROM (VALUES 1000) t(x)", applyNotRegisteredError, true);
+ assertQueryFails("SELECT apply(1, x -> apply(10, y -> x)) FROM (VALUES 'abc') t(x)", applyNotRegisteredError, true);
+ assertQueryFails("SELECT apply(1, x -> apply(10, y -> apply(100, z -> x))) FROM (VALUES 1000) t(x)", applyNotRegisteredError, true);
+ assertQueryFails("SELECT apply(1, x -> apply(10, y -> apply(100, z -> x))) FROM (VALUES 'abc') t(x)", applyNotRegisteredError, true);
+
+ // in join post-filter
+ assertQueryFails("SELECT * FROM (VALUES true) t(x) left JOIN (VALUES 1001) t2(y) ON (apply(false, z -> apply(false, y -> x)))", applyNotRegisteredError, true);
+ }
+
+ @Override
+ @Test(enabled = false)
+ public void testArrayCumSum()
+ {
+ // int
+ String sql = "select array_cum_sum(k) from (values (array[cast(5 as INTEGER), 6, 0]), (ARRAY[]), (CAST(NULL AS array(integer)))) t(k)";
+ assertQuery(sql, "values array[cast(5 as integer), cast(11 as integer), cast(11 as integer)], array[], null");
+
+ sql = "select array_cum_sum(k) from (values (array[cast(5 as INTEGER), 6, 0]), (ARRAY[]), (CAST(NULL AS array(integer))), (ARRAY [cast(2147483647 as INTEGER), 2147483647, 2147483647])) t(k)";
+ assertQueryFails(sql, ".*integer overflow:.*", true);
+
+ sql = "select array_cum_sum(k) from (values (array[cast(5 as INTEGER), 6, null, 2, 3])) t(k)";
+ assertQuery(sql, "values array[cast(5 as integer), cast(11 as integer), cast(null as integer), cast(null as integer), cast(null as integer)]");
+
+ sql = "select array_cum_sum(k) from (values (array[cast(null as INTEGER), 6, null, 2, 3])) t(k)";
+ assertQuery(sql, "values array[cast(null as integer), cast(null as integer), cast(null as integer), cast(null as integer), cast(null as integer)]");
+
+ // bigint
+ sql = "select array_cum_sum(k) from (values (array[cast(5 as bigint), 6, 0]), (ARRAY[]), (CAST(NULL AS array(bigint))), (ARRAY [cast(2147483647 as bigint), 2147483647, 2147483647])) t(k)";
+ assertQuery(sql, "values array[cast(5 as bigint), cast(11 as bigint), cast(11 as bigint)], array[], null, array[cast(2147483647 as bigint), cast(4294967294 as bigint), cast(6442450941 as bigint)]");
+
+ sql = "select array_cum_sum(k) from (values (array[cast(5 as bigint), 6, null, 2, 3])) t(k)";
+ assertQuery(sql, "values array[cast(5 as bigint), cast(11 as bigint), cast(null as bigint), cast(null as bigint), cast(null as bigint)]");
+
+ sql = "select array_cum_sum(k) from (values (array[cast(null as bigint), 6, null, 2, 3])) t(k)";
+ assertQuery(sql, "values array[cast(null as bigint), cast(null as bigint), cast(null as bigint), cast(null as bigint), cast(null as bigint)]");
+
+ // real
+ sql = "select array_cum_sum(k) from (values (array[cast(null as real), 6, null, 2, 3])) t(k)";
+ assertQuery(sql, "values array[cast(null as real), cast(null as real), cast(null as real), cast(null as real), cast(null as real)]");
+
+ MaterializedResult raw = computeActual("SELECT array_cum_sum(k) FROM (values (ARRAY [cast(5.1 as real), 6.1, 0.5]), (ARRAY[]), (CAST(NULL AS array(real))), " +
+ "(ARRAY [cast(null as real), 6.1, 0.5]), (ARRAY [cast(2.5 as real), 6.1, null, 3.2])) t(k)");
+ List rowList = raw.getMaterializedRows();
+ List actualFloat = (List) rowList.get(0).getField(0);
+ List expectedFloat = ImmutableList.of(5.1f, 11.2f, 11.7f);
+ // TODO: Investigate error 'java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Float'
+ for (int i = 0; i < actualFloat.size(); ++i) {
+ assertTrue(actualFloat.get(i) > expectedFloat.get(i) - 1e-5 && actualFloat.get(i) < expectedFloat.get(i) + 1e-5);
+ }
+
+ actualFloat = (List) rowList.get(1).getField(0);
+ assertTrue(actualFloat.isEmpty());
+
+ actualFloat = (List) rowList.get(2).getField(0);
+ assertNull(actualFloat);
+
+ actualFloat = (List) rowList.get(3).getField(0);
+ for (int i = 0; i < actualFloat.size(); ++i) {
+ assertNull(actualFloat.get(i));
+ }
+
+ actualFloat = (List) rowList.get(4).getField(0);
+ expectedFloat = Arrays.asList(2.5f, 8.6f, null, null);
+ for (int i = 0; i < 2; ++i) {
+ assertTrue(actualFloat.get(i) > expectedFloat.get(i) - 1e-5f && actualFloat.get(i) < expectedFloat.get(i) + 1e-5f);
+ }
+ for (int i = 2; i < actualFloat.size(); ++i) {
+ assertNull(actualFloat.get(i));
+ }
+
+ // double
+ raw = computeActual("SELECT array_cum_sum(k) FROM (values (ARRAY [cast(5.1 as double), 6.1, 0.5]), (ARRAY[]), (CAST(NULL AS array(double))), " +
+ "(ARRAY [cast(null as double), 6.1, 0.5]), (ARRAY [cast(5.1 as double), 6.1, null, 3.2])) t(k)");
+ rowList = raw.getMaterializedRows();
+ List actualDouble = (List) rowList.get(0).getField(0);
+ List expectedDouble = ImmutableList.of(5.1, 11.2, 11.7);
+ for (int i = 0; i < actualDouble.size(); ++i) {
+ assertTrue(actualDouble.get(i) > expectedDouble.get(i) - 1e-5f && actualDouble.get(i) < expectedDouble.get(i) + 1e-5f);
+ }
+
+ actualDouble = (List) rowList.get(1).getField(0);
+ assertTrue(actualDouble.isEmpty());
+
+ actualDouble = (List) rowList.get(2).getField(0);
+ assertNull(actualDouble);
+
+ actualDouble = (List) rowList.get(3).getField(0);
+ for (int i = 0; i < actualDouble.size(); ++i) {
+ assertNull(actualDouble.get(i));
+ }
+
+ actualDouble = (List) rowList.get(4).getField(0);
+ expectedDouble = Arrays.asList(5.1, 11.2, null, null);
+ for (int i = 0; i < 2; ++i) {
+ assertTrue(actualDouble.get(i) > expectedDouble.get(i) - 1e-5f && actualDouble.get(i) < expectedDouble.get(i) + 1e-5f);
+ }
+ for (int i = 2; i < actualDouble.size(); ++i) {
+ assertNull(actualDouble.get(i));
+ }
+
+ // decimal
+ sql = "select array_cum_sum(k) from (values (array[cast(5.1 as decimal(38, 1)), 6, 0]), (ARRAY[]), (CAST(NULL AS array(decimal)))) t(k)";
+ assertQuery(sql, "values array[cast(5.1 as decimal), cast(11.1 as decimal), cast(11.1 as decimal)], array[], null");
+
+ sql = "select array_cum_sum(k) from (values (array[cast(5.1 as decimal(38, 1)), 6, null, 3]), (array[cast(null as decimal(38, 1)), 6, null, 3])) t(k)";
+ assertQuery(sql, "values array[cast(5.1 as decimal), cast(11.1 as decimal), cast(null as decimal), cast(null as decimal)], " +
+ "array[cast(null as decimal), cast(null as decimal), cast(null as decimal), cast(null as decimal)]");
+
+ // varchar
+ sql = "select array_cum_sum(k) from (values (array[cast('5.1' as varchar), '6', '0']), (ARRAY[]), (CAST(NULL AS array(varchar)))) t(k)";
+ assertQueryFails(sql, ".*cannot be applied to.*");
+
+ sql = "select array_cum_sum(k) from (values (array[cast(null as varchar), '6', '0'])) t(k)";
+ assertQueryFails(sql, ".*cannot be applied to.*");
+ }
+
+ @Override
+ @Test
+ public void testLambdaInAggregationContext()
+ {
+ assertQueryFails("SELECT apply(sum(x), i -> i * i) FROM (VALUES 1, 2, 3, 4, 5) t(x)", applyNotRegisteredError, true);
+ assertQueryFails("SELECT apply(x, i -> i - 1), sum(y) FROM (VALUES (1, 10), (1, 20), (2, 50)) t(x,y) GROUP BY x", applyNotRegisteredError, true);
+ assertQueryFails("SELECT x, apply(sum(y), i -> i * 10) FROM (VALUES (1, 10), (1, 20), (2, 50)) t(x,y) GROUP BY x", applyNotRegisteredError, true);
+ assertQueryFails("SELECT apply(8, x -> x + 1) FROM (VALUES (1, 2)) t(x,y) GROUP BY y", applyNotRegisteredError, true);
+
+ assertQueryFails("SELECT apply(CAST(ROW(1) AS ROW(someField BIGINT)), x -> x.someField) FROM (VALUES (1,2)) t(x,y) GROUP BY y", applyNotRegisteredError, true);
+ assertQueryFails("SELECT apply(sum(x), x -> x * x) FROM (VALUES 1, 2, 3, 4, 5) t(x)", applyNotRegisteredError, true);
+ // nested lambda expression uses the same variable name
+ assertQueryFails("SELECT apply(sum(x), x -> apply(x, x -> x * x)) FROM (VALUES 1, 2, 3, 4, 5) t(x)", applyNotRegisteredError, true);
+ }
+
+ @Override
+ @Test
+ public void testLambdaInSubqueryContext()
+ {
+ assertQueryFails("SELECT apply(x, i -> i * i) FROM (SELECT 10 x)", applyNotRegisteredError, true);
+ assertQueryFails("SELECT apply((SELECT 10), i -> i * i)", applyNotRegisteredError, true);
+
+ // with capture
+ assertQueryFails("SELECT apply(x, i -> i * x) FROM (SELECT 10 x)", applyNotRegisteredError, true);
+ assertQueryFails("SELECT apply(x, y -> y * x) FROM (SELECT 10 x, 3 y)", applyNotRegisteredError, true);
+ assertQueryFails("SELECT apply(x, z -> y * x) FROM (SELECT 10 x, 3 y)", applyNotRegisteredError, true);
+ }
+
+ @Override
+ @Test
+ public void testNonDeterministic()
+ {
+ MaterializedResult materializedResult = computeActual("SELECT rand() FROM orders LIMIT 10");
+ long distinctCount = materializedResult.getMaterializedRows().stream()
+ .map(row -> row.getField(0))
+ .distinct()
+ .count();
+ assertTrue(distinctCount >= 8, "rand() must produce different rows");
+
+ assertQueryFails("SELECT apply(1, x -> x + rand()) FROM orders LIMIT 10", applyNotRegisteredError, true);
+ }
+
+ @Override
+ @Test
+ public void testMergeHyperLogLog()
+ {
+ assertQueryFails("SELECT cardinality(merge(create_hll(custkey))) FROM orders", "Scalar function name not registered: presto.default.create_hll, called with arguments", true);
+ }
+
+ @Override
+ @Test
+ public void testMergeHyperLogLogGroupBy()
+ {
+ assertQueryFails(
+ "SELECT orderstatus, cardinality(merge(create_hll(custkey))) " +
+ "FROM orders " +
+ "GROUP BY orderstatus", "Scalar function name not registered: presto.default.create_hll, called with arguments", true);
+ }
+
+ @Override
+ @Test
+ public void testMergeHyperLogLogWithNulls()
+ {
+ assertQueryFails("SELECT cardinality(merge(create_hll(IF(orderstatus = 'O', custkey)))) FROM orders",
+ "Scalar function name not registered: presto.default.create_hll, called with arguments", true);
+ }
+
+ @Override
+ @Test
+ public void testMergeHyperLogLogGroupByWithNulls()
+ {
+ assertQueryFails(
+ "SELECT orderstatus, cardinality(merge(create_hll(IF(orderstatus != 'O', custkey)))) " +
+ "FROM orders " +
+ "GROUP BY orderstatus",
+ "Scalar function name not registered: presto.default.create_hll, called with arguments", true);
+ }
+
+ @Override
+ @Test
+ public void testKeyBasedSampling()
+ {
+ String[] queries = new String[]{
+ "select count(1) from orders join lineitem using(orderkey)",
+ "select count(1) from (select custkey, max(orderkey) from orders group by custkey)",
+ "select count_if(m >= 1) from (select max(orderkey) over(partition by custkey) m from orders)",
+ "select cast(m as bigint) from (select sum(totalprice) over(partition by custkey order by comment) m from orders order by 1 desc limit 1)",
+ "select count(1) from lineitem where orderkey in (select orderkey from orders where length(comment) > 7)",
+ "select count(1) from lineitem where orderkey not in (select orderkey from orders where length(comment) > 27)",
+ "select count(1) from (select distinct orderkey, custkey from orders)",
+ };
+ int[] unsampledResults = new int[]{60175, 1000, 15000, 5408941, 60175, 9256, 15000};
+ for (int i = 0; i < queries.length; i++) {
+ assertQuery(queries[i], "select " + unsampledResults[i]);
+ }
+
+ Session sessionWithKeyBasedSampling = Session.builder(getSession())
+ .setSystemProperty(KEY_BASED_SAMPLING_ENABLED, "true")
+ .setSystemProperty(KEY_BASED_SAMPLING_PERCENTAGE, "0.2")
+ .build();
+ for (int i = 0; i < queries.length; i++) {
+ assertQueryFails(sessionWithKeyBasedSampling, queries[i], "Scalar function name not registered: presto.default.key_sampling_percent, called with arguments", true);
+ }
+
+ sessionWithKeyBasedSampling = Session.builder(getSession())
+ .setSystemProperty(KEY_BASED_SAMPLING_ENABLED, "true")
+ .setSystemProperty(KEY_BASED_SAMPLING_PERCENTAGE, "0.1")
+ .build();
+ for (int i = 0; i < queries.length; i++) {
+ assertQueryFails(sessionWithKeyBasedSampling, queries[i], "Scalar function name not registered: presto.default.key_sampling_percent, called with arguments", true);
+ }
+ }
+
+ @Override
+ @Test
+ public void testP4ApproxSetBigint()
+ {
+ assertQueryFails("SELECT cardinality(cast(approx_set(custkey) AS P4HYPERLOGLOG)) FROM orders",
+ p4HlltimestampTzTypeUnsupportedError, true);
+ }
+
+ @Override
+ @Test
+ public void testP4ApproxSetVarchar()
+ {
+ assertQueryFails("SELECT cardinality(cast(approx_set(CAST(custkey AS VARCHAR)) AS P4HYPERLOGLOG)) FROM orders",
+ p4HlltimestampTzTypeUnsupportedError, true);
+ }
+
+ @Override
+ @Test
+ public void testP4ApproxSetBigintGroupBy()
+ {
+ assertQueryFails(
+ "SELECT orderstatus, cardinality(cast(approx_set(custkey) AS P4HYPERLOGLOG)) " +
+ "FROM orders " +
+ "GROUP BY orderstatus", p4HlltimestampTzTypeUnsupportedError, true);
+ }
+
+ @Override
+ @Test
+ public void testP4ApproxSetDouble()
+ {
+ assertQueryFails("SELECT cardinality(cast(approx_set(CAST(custkey AS DOUBLE)) AS P4HYPERLOGLOG)) FROM orders",
+ p4HlltimestampTzTypeUnsupportedError, true);
+ }
+
+ @Override
+ @Test
+ public void testP4ApproxSetDoubleGroupBy()
+ {
+ assertQueryFails(
+ "SELECT orderstatus, cardinality(cast(approx_set(CAST(custkey AS DOUBLE)) AS P4HYPERLOGLOG)) " +
+ "FROM orders " +
+ "GROUP BY orderstatus", p4HlltimestampTzTypeUnsupportedError, true);
+ }
+
+ @Override
+ @Test
+ public void testP4ApproxSetGroupByWithNulls()
+ {
+ assertQueryFails(
+ "SELECT orderstatus, cardinality(cast(approx_set(IF(custkey % 2 <> 0, custkey)) AS P4HYPERLOGLOG)) " +
+ "FROM orders " +
+ "GROUP BY orderstatus", p4HlltimestampTzTypeUnsupportedError, true);
+ }
+
+ @Override
+ @Test
+ public void testP4ApproxSetGroupByWithOnlyNullsInOneGroup()
+ {
+ assertQueryFails(
+ "SELECT orderstatus, cardinality(cast(approx_set(IF(orderstatus != 'O', custkey)) AS P4HYPERLOGLOG)) " +
+ "FROM orders " +
+ "GROUP BY orderstatus", p4HlltimestampTzTypeUnsupportedError, true);
+ }
+
+ @Override
+ @Test
+ public void testP4ApproxSetOnlyNulls()
+ {
+ assertQueryFails("SELECT cardinality(cast(approx_set(null) AS P4HYPERLOGLOG)) FROM orders",
+ p4HlltimestampTzTypeUnsupportedError, true);
+ }
+
+ @Override
+ @Test
+ public void testP4ApproxSetVarcharGroupBy()
+ {
+ assertQueryFails(
+ "SELECT orderstatus, cardinality(cast(approx_set(CAST(custkey AS VARCHAR)) AS P4HYPERLOGLOG)) " +
+ "FROM orders " +
+ "GROUP BY orderstatus", p4HlltimestampTzTypeUnsupportedError, true);
+ }
+
+ @Override
+ @Test
+ public void testP4ApproxSetWithNulls()
+ {
+ assertQueryFails("SELECT cardinality(cast(approx_set(IF(orderstatus = 'O', custkey)) AS P4HYPERLOGLOG)) FROM orders",
+ p4HlltimestampTzTypeUnsupportedError, true);
+ }
+
+ @Override
+ public void testLargeBytecode()
+ {
+ StringBuilder stringBuilder = new StringBuilder("SELECT x FROM (SELECT orderkey x, custkey y from orders limit 10) WHERE CASE true ");
+ // Generate 100 cases.
+ for (int i = 0; i < 100; i++) {
+ stringBuilder.append(" when x in (");
+ for (int j = 0; j < 20; j++) {
+ stringBuilder.append("random(" + (i * 100 + j) + "), ");
+ }
+
+ stringBuilder.append("random(" + i + ")) then x = random()");
+ }
+
+ stringBuilder.append("else x = random() end");
+ assertQueryFails(stringBuilder.toString(),
+ "input > 0 \\(0 vs. 0\\) bound must be positive presto.default.random\\(0:INTEGER\\)", true);
+ }
+
+ @Override
+ @Test
+ public void testArraySplitIntoChunks()
+ {
+ String functionNotRegistered = "Scalar function name not registered: presto.default.array_split_into_chunks";
+
+ String sql = "select array_split_into_chunks(array[1, 2, 3, 4, 5, 6], 2)";
+ assertQueryFails(sql, functionNotRegistered, true);
+
+ sql = "select array_split_into_chunks(array[1, 2, 3, 4, 5], 3)";
+ assertQueryFails(sql, functionNotRegistered, true);
+
+ sql = "select array_split_into_chunks(array[1, 2, 3], 5)";
+ assertQueryFails(sql, functionNotRegistered, true);
+
+ sql = "select array_split_into_chunks(null, 2)";
+ assertQuery(sql, "values null");
+
+ sql = "select array_split_into_chunks(array[1, 2, 3], 0)";
+ assertQueryFails(sql, functionNotRegistered, true);
+
+ sql = "select array_split_into_chunks(array[1, 2, 3], -1)";
+ assertQueryFails(sql, functionNotRegistered, true);
+
+ sql = "select array_split_into_chunks(array[1, null, 3, null, 5], 2)";
+ assertQueryFails(sql, functionNotRegistered, true);
+
+ sql = "select array_split_into_chunks(array['a', 'b', 'c', 'd'], 2)";
+ assertQueryFails(sql, functionNotRegistered, true);
+
+ sql = "select array_split_into_chunks(array[1.1, 2.2, 3.3, 4.4, 5.5], 2)";
+ assertQueryFails(sql, functionNotRegistered, true);
+
+ sql = "select array_split_into_chunks(array[null, null, null], 0)";
+ assertQueryFails(sql, functionNotRegistered, true);
+
+ sql = "select array_split_into_chunks(array[null, null, null], 2)";
+ assertQueryFails(sql, functionNotRegistered, true);
+
+ sql = "select array_split_into_chunks(array[null, 1, 2], 5)";
+ assertQueryFails(sql, functionNotRegistered, true);
+
+ sql = "select array_split_into_chunks(array[], 0)";
+ assertQueryFails(sql, functionNotRegistered, true);
+ }
+
+ @Test
+ public void testAtTimeZone()
+ {
+ assertQueryFails("SELECT TIMESTAMP '2012-10-31 01:00' AT TIME ZONE INTERVAL '07:09' hour to minute", timestampTzTypeUnsupportedError, true);
+ assertQueryFails("SELECT TIMESTAMP '2012-10-31 01:00' AT TIME ZONE 'Asia/Oral'", timestampTzTypeUnsupportedError, true);
+ assertQueryFails("SELECT MIN(x) AT TIME ZONE 'America/Chicago' FROM (VALUES TIMESTAMP '1970-01-01 00:01:00+00:00') t(x)", timestampTzTypeUnsupportedError, true);
+ assertQueryFails("SELECT TIMESTAMP '2012-10-31 01:00' AT TIME ZONE '+07:09'", timestampTzTypeUnsupportedError, true);
+ assertQueryFails("SELECT TIMESTAMP '2012-10-31 01:00 UTC' AT TIME ZONE 'America/Los_Angeles'", timestampTzTypeUnsupportedError, true);
+ assertQueryFails("SELECT TIMESTAMP '2012-10-31 01:00' AT TIME ZONE 'America/Los_Angeles'", timestampTzTypeUnsupportedError, true);
+ assertQueryFails("SELECT x AT TIME ZONE 'America/Los_Angeles' FROM (values TIMESTAMP '1970-01-01 00:01:00+00:00', TIMESTAMP '1970-01-01 08:01:00+08:00', TIMESTAMP '1969-12-31 16:01:00-08:00') t(x)",
+ timestampTzTypeUnsupportedError, true);
+ assertQueryFails("SELECT x AT TIME ZONE 'America/Los_Angeles' FROM (values TIMESTAMP '1970-01-01 00:01:00', TIMESTAMP '1970-01-01 08:01:00', TIMESTAMP '1969-12-31 16:01:00') t(x)", timestampTzTypeUnsupportedError, true);
+ assertQueryFails("SELECT min(x) AT TIME ZONE 'America/Los_Angeles' FROM (values TIMESTAMP '1970-01-01 00:01:00+00:00', TIMESTAMP '1970-01-01 08:01:00+08:00', TIMESTAMP '1969-12-31 16:01:00-08:00') t(x)",
+ timestampTzTypeUnsupportedError, true);
+
+ // with chained AT TIME ZONE
+ assertQueryFails("SELECT TIMESTAMP '2012-10-31 01:00' AT TIME ZONE 'America/Los_Angeles' AT TIME ZONE 'UTC'", timestampTzTypeUnsupportedError, true);
+ assertQueryFails("SELECT TIMESTAMP '2012-10-31 01:00' AT TIME ZONE 'Asia/Tokyo' AT TIME ZONE 'America/Los_Angeles'", timestampTzTypeUnsupportedError, true);
+ assertQueryFails("SELECT TIMESTAMP '2012-10-31 01:00' AT TIME ZONE 'America/Los_Angeles' AT TIME ZONE 'Asia/Shanghai'", timestampTzTypeUnsupportedError, true);
+ assertQueryFails("SELECT min(x) AT TIME ZONE 'America/Los_Angeles' AT TIME ZONE 'UTC' FROM (values TIMESTAMP '1970-01-01 00:01:00+00:00', TIMESTAMP '1970-01-01 08:01:00+08:00', TIMESTAMP '1969-12-31 16:01:00-08:00') t(x)",
+ timestampTzTypeUnsupportedError, true);
+
+ // with AT TIME ZONE in VALUES
+ assertQueryFails("SELECT * FROM (VALUES TIMESTAMP '2012-10-31 01:00' AT TIME ZONE 'Asia/Oral')", timestampTzTypeUnsupportedError, true);
+ }
+
+ @Override
+ @Test
+ public void testApproxMostFrequentWithVarchar()
+ {
+ MaterializedResult actual1 = computeActual("SELECT approx_most_frequent(3, x, 15) FROM (values 'A', 'B', 'A', 'C', 'A', 'B', 'C', 'D', 'E') t(x)");
+ assertEquals(actual1.getRowCount(), 1);
+ // PRESTISSIMO_FIX
+ assertEquals(actual1.getMaterializedRows().get(0).getFields().get(0), ImmutableMap.of("A", 3L, "B", 2L, "C", 2L));
+
+ MaterializedResult actual2 = computeActual("SELECT approx_most_frequent(2, x, 15) FROM (values 'A', 'B', 'A', 'C', 'A', 'B', 'C', 'D', 'E') t(x)");
+ assertEquals(actual2.getRowCount(), 1);
+ // PRESTISSIMO_FIX
+ assertEquals(actual2.getMaterializedRows().get(0).getFields().get(0), ImmutableMap.of("A", 3L, "C", 2L));
+ }
+
+ @Override
+ @Test
+ public void testMapUnionSumOverflow()
+ {
+ assertQueryFails(
+ "select y, map_union_sum(x) from (select 1 y, map(array['x', 'z', 'y'], cast(array[null,30,100] as array)) x " +
+ "union all select 1 y, map(array['x', 'y'], cast(array[1,100] as array))x) group by y", "Value 200 exceeds 127", true);
+ assertQueryFails(
+ "select y, map_union_sum(x) from (select 1 y, map(array['x', 'z', 'y'], cast(array[null,30, 32760] as array)) x " +
+ "union all select 1 y, map(array['x', 'y'], cast(array[1,100] as array))x) group by y", "Value 32860 exceeds 32767", true);
+ }
+
+ @Override
+ @Test
+ public void testRowSubscript()
+ {
+ // Subscript on Row with unnamed fields
+ assertQuery("SELECT ROW (1, 'a', true)[2]", "SELECT 'a'");
+ assertQuery("SELECT r[2] FROM (VALUES (ROW (ROW (1, 'a', true)))) AS v(r)", "SELECT 'a'");
+ assertQuery("SELECT r[1], r[2] FROM (SELECT ROW (name, regionkey) FROM nation ORDER BY name LIMIT 1) t(r)", "VALUES ('ALGERIA', 0)");
+
+ // Subscript on Row with named fields
+ assertQuery("SELECT (CAST (ROW (1, 'a', 2 ) AS ROW (field1 bigint, field2 varchar(1), field3 bigint)))[2]", "SELECT 'a'");
+
+ // Subscript on nested Row
+ assertQuery("SELECT ROW (1, 'a', ROW (false, 2, 'b'))[3][3]", "SELECT 'b'");
+
+ // Row subscript in filter condition
+ assertQuery("SELECT orderstatus FROM orders WHERE ROW (orderkey, custkey)[1] = 100", "SELECT 'O'");
+
+ // Row subscript in join condition
+ assertQuery("SELECT n.name, r.name FROM nation n JOIN region r ON ROW (n.name, n.regionkey)[2] = ROW (r.name, r.regionkey)[2] ORDER BY n.name LIMIT 1", "VALUES ('ALGERIA', 'AFRICA')");
+
+ //Row subscript in a lambda
+ assertQueryFails("SELECT apply(ROW (1, 2), r -> r[2])", "Scalar function name not registered: presto.default.apply, called with arguments", true);
+ }
+
+ @Override
+ @Test
+ public void testDuplicateUnnestItem()
+ {
+ // unnest with cross join
+ assertQuery("SELECT * from (select * FROM (values 1) as t(k)) CROSS JOIN unnest(ARRAY[2, 3], ARRAY[2, 3]) AS r(r1, r2)", "VALUES (1, 2, 2), (1, 3, 3)");
+ assertQuery("SELECT * from (select * FROM (values 1) as t(k)) CROSS JOIN unnest(ARRAY[2, 3], ARRAY[2, 3], ARRAY[2, 3]) AS r(r1, r2, r3)", "VALUES (1, 2, 2, 2), (1, 3, 3, 3)");
+ assertQuery("SELECT * from (select * FROM (values 1) as t(k)) CROSS JOIN unnest(ARRAY[2, 3], ARRAY[10,11,12], ARRAY[2, 3]) AS r(r1, r2, r3)", "VALUES (1, 2, 10, 2), (1, 3, 11, 3), (1, NULL, 12, NULL)");
+ assertQuery("SELECT * from (select * FROM (values 1) as t(k)) CROSS JOIN unnest(ARRAY[2, 3], ARRAY[2, 3], ARRAY[10,11,12]) AS r(r1, r2, r3)", "VALUES (1, 2, 2, 10), (1, 3, 3, 11), (1, NULL, NULL, 12)");
+ assertQuery("SELECT * from (select * FROM (values 1) as t(k)) CROSS JOIN unnest(MAP(ARRAY[2, 3], ARRAY['a', 'b']), MAP(ARRAY[2, 3], ARRAY['a', 'b'])) AS r(r1, r2, r3, r4)", "VALUES (1, 2, 'a', 2, 'a'), (1, 3, 'b', 3, 'b')");
+ assertQuery("SELECT * from (select * FROM (values 1) as t(k)) CROSS JOIN unnest(MAP(ARRAY[2, 3], ARRAY['a', 'b']), MAP(ARRAY[1, 2, 3], ARRAY['a', 'b', 'c']), MAP(ARRAY[2, 3], ARRAY['a', 'b'])) AS r(r1, r2, r3, r4, r5, r6)",
+ "VALUES (1, 2, 'a', 1, 'a', 2, 'a'), (1, 3, 'b', 2, 'b', 3, 'b'), (1, NULL, NULL, 3, 'c', NULL, NULL)");
+ assertQuery("SELECT * from (select * FROM (values 1) as t(k)) CROSS JOIN unnest(MAP(ARRAY[2, 3], ARRAY['a', 'b']), MAP(ARRAY[2, 3], ARRAY['a', 'b']), MAP(ARRAY[1, 2, 3], ARRAY['a', 'b', 'c'])) AS r(r1, r2, r3, r4, r5, r6)",
+ "VALUES (1, 2, 'a', 2, 'a', 1, 'a'), (1, 3, 'b', 3, 'b', 2, 'b'), (1, NULL, NULL, NULL, NULL, 3, 'c')");
+ assertQuery("SELECT * from ( SELECT ARRAY[1] AS kv FROM (select 1)) CROSS JOIN UNNEST( kv, kv )", "VALUES (ARRAY[1], 1, 1)");
+
+ assertQuery("SELECT * from (select * FROM (values 1) as t(k)) CROSS JOIN unnest(ARRAY[2, 3], ARRAY[2, 3]) WITH ORDINALITY AS r(r1, r2, ord)", "VALUES (1, 2, 2, 1), (1, 3, 3, 2)");
+ assertQuery("SELECT * from (select * FROM (values 1) as t(k)) CROSS JOIN unnest(ARRAY[2, 3], ARRAY[2, 3], ARRAY[2, 3]) WITH ORDINALITY AS r(r1, r2, r3, ord)", "VALUES (1, 2, 2, 2, 1), (1, 3, 3, 3, 2)");
+ assertQuery("SELECT * from (select * FROM (values 1) as t(k)) CROSS JOIN unnest(ARRAY[2, 3], ARRAY[10,11,12], ARRAY[2, 3]) WITH ORDINALITY AS r(r1, r2, r3, ord)", "VALUES (1, 2, 10, 2, 1), (1, 3, 11, 3, 2), (1, NULL, 12, NULL, 3)");
+ assertQuery("SELECT * from (select * FROM (values 1) as t(k)) CROSS JOIN unnest(ARRAY[2, 3], ARRAY[2, 3], ARRAY[10,11,12]) WITH ORDINALITY AS r(r1, r2, r3, ord)", "VALUES (1, 2, 2, 10, 1), (1, 3, 3, 11, 2), (1, NULL, NULL, 12, 3)");
+ assertQuery("SELECT * from (select * FROM (values 1) as t(k)) CROSS JOIN unnest(MAP(ARRAY[2, 3], ARRAY['a', 'b']), MAP(ARRAY[2, 3], ARRAY['a', 'b'])) WITH ORDINALITY AS r(r1, r2, r3, r4, ord)", "VALUES (1, 2, 'a', 2, 'a', 1), (1, 3, 'b', 3, 'b', 2)");
+ assertQuery("SELECT * from (select * FROM (values 1) as t(k)) CROSS JOIN unnest(MAP(ARRAY[2, 3], ARRAY['a', 'b']), MAP(ARRAY[1, 2, 3], ARRAY['a', 'b', 'c']), MAP(ARRAY[2, 3], ARRAY['a', 'b'])) WITH ORDINALITY AS r(r1, r2, r3, r4, r5, r6, ord)",
+ "VALUES (1, 2, 'a', 1, 'a', 2, 'a', 1), (1, 3, 'b', 2, 'b', 3, 'b', 2), (1, NULL, NULL, 3, 'c', NULL, NULL, 3)");
+ assertQuery("SELECT * from (select * FROM (values 1) as t(k)) CROSS JOIN unnest(MAP(ARRAY[2, 3], ARRAY['a', 'b']), MAP(ARRAY[2, 3], ARRAY['a', 'b']), MAP(ARRAY[1, 2, 3], ARRAY['a', 'b', 'c'])) WITH ORDINALITY AS r(r1, r2, r3, r4, r5, r6, ord)",
+ "VALUES (1, 2, 'a', 2, 'a', 1, 'a', 1), (1, 3, 'b', 3, 'b', 2, 'b', 2), (1, NULL, NULL, NULL, NULL, 3, 'c', 3)");
+ assertQuery("SELECT * from ( SELECT ARRAY[1] AS kv FROM (select 1)) CROSS JOIN UNNEST( kv, kv ) WITH ORDINALITY AS t(r1, r2, ord)", "VALUES (ARRAY[1], 1, 1, 1)");
+ assertQueryFails("SELECT * from (select * FROM (values 1) as t(k)) CROSS JOIN unnest(ARRAY[row(2, 3), row(3, 5)], ARRAY[row(2, 3), row(3, 5)]) AS r(r1, r2, r3, r4)",
+ "Field not found: field_.*. Available fields are: field, field_.*", true);
+ assertQueryFails("SELECT * from (select * FROM (values 1) as t(k)) CROSS JOIN unnest(ARRAY[row(2, 3), row(3, 5)], ARRAY[row(2, 3), row(3, 5)], ARRAY[row(10, 13, 15), row(23, 25, 20)]) AS r(r1, r2, r3, r4, r5, r6, r7)",
+ "Field not found: field_.*. Available fields are: field, field_.*", true);
+ assertQueryFails("SELECT * from (select * FROM (values 1) as t(k)) CROSS JOIN unnest(ARRAY[row(2, 3), row(3, 5)], ARRAY[row(2, 3), row(3, 5)]) WITH ORDINALITY AS r(r1, r2, r3, r4, ord)",
+ "Field not found: field_.*. Available fields are: field, field_.*", true);
+ assertQueryFails("SELECT * from (select * FROM (values 1) as t(k)) CROSS JOIN unnest(ARRAY[row(2, 3), row(3, 5)], ARRAY[row(2, 3), row(3, 5)], ARRAY[row(10, 13, 15), row(23, 25, 20)]) WITH ORDINALITY AS r(r1, r2, r3, r4, r5, r6, r7, ord)",
+ "Field not found: field_.*. Available fields are: field, field_.*", true);
+
+ Session useLegacyUnnest = Session.builder(getSession())
+ .setSystemProperty(LEGACY_UNNEST, "true")
+ .build();
+ assertQuery(useLegacyUnnest, "SELECT k, cast(r1 as row(x int, y int)), cast(r2 as row(x int, y int)) from (select * FROM (values 1) as t(k)) CROSS JOIN unnest(ARRAY[row(2, 3), row(3, 5)], ARRAY[row(2, 3), row(3, 5)]) AS r(r1, r2)",
+ "VALUES (1, row(2, 3), row(2, 3)), (1, row(3, 5), row(3, 5))");
+ assertQuery(useLegacyUnnest, "SELECT k, cast(r1 as row(x int, y int)), cast(r2 as row(x int, y int)), cast(r3 as row(x int, y int, z int)) from (select * FROM (values 1) as t(k)) CROSS JOIN unnest(ARRAY[row(2, 3), row(3, 5)], ARRAY[row(2, 3), row(3, 5)], ARRAY[row(10, 13, 15), row(23, 25, 20)]) AS r(r1, r2, r3)",
+ "VALUES (1, row(2, 3), row(2, 3), row(10, 13, 15)), (1, row(3, 5), row(3, 5), row(23, 25, 20))");
+ assertQuery(useLegacyUnnest, "SELECT k, cast(r1 as row(x int, y int)), cast(r2 as row(x int, y int)), ord from (select * FROM (values 1) as t(k)) CROSS JOIN unnest(ARRAY[row(2, 3), row(3, 5)], ARRAY[row(2, 3), row(3, 5)]) WITH ORDINALITY AS r(r1, r2, ord)",
+ "VALUES (1, row(2, 3), row(2, 3), 1), (1, row(3, 5), row(3, 5), 2)");
+ assertQuery(useLegacyUnnest, "SELECT k, cast(r1 as row(x int, y int)), cast(r2 as row(x int, y int)), cast(r3 as row(x int, y int, z int)), ord from (select * FROM (values 1) as t(k)) CROSS JOIN unnest(ARRAY[row(2, 3), row(3, 5)], ARRAY[row(2, 3), row(3, 5)], ARRAY[row(10, 13, 15), row(23, 25, 20)]) WITH ORDINALITY AS r(r1, r2, r3, ord)",
+ "VALUES (1, row(2, 3), row(2, 3), row(10, 13, 15), 1), (1, row(3, 5), row(3, 5), row(23, 25, 20), 2)");
+
+ assertQuery("select orderkey, custkey, totalprice, t1, t2 from orders cross join unnest(array[custkey], array[custkey]) as t(t1, t2)",
+ "select orderkey, custkey, totalprice, custkey as t1, custkey as t2 from orders");
+ assertQuery("select orderkey, custkey, totalprice, t1, t2, t3 from orders cross join unnest(array[custkey], array[custkey], array[custkey]) as t(t1, t2, t3)",
+ "select orderkey, custkey, totalprice, custkey as t1, custkey as t2, custkey as t3 from orders");
+ assertQuery("select orderkey, custkey, totalprice, t1, t2, t3 from orders cross join unnest(array[custkey], array[custkey], array[shippriority]) as t(t1, t2, t3)",
+ "select orderkey, custkey, totalprice, custkey as t1, custkey as t2, shippriority as t3 from orders");
+
+ // SIMPLE UNNEST without cross join
+ assertQuery("SELECT * from unnest(ARRAY[2, 3], ARRAY[2, 3])", "VALUES (2, 2), (3, 3)");
+ assertQuery("SELECT * from unnest(ARRAY[2, 3], ARRAY[2, 3], ARRAY[2, 3])", "VALUES (2, 2, 2), (3, 3, 3)");
+ assertQuery("SELECT * from unnest(ARRAY[2, 3], ARRAY[10,11,12], ARRAY[2, 3])", "VALUES (2, 10, 2), (3, 11, 3), (NULL, 12, NULL)");
+ assertQuery("SELECT * from unnest(ARRAY[2, 3], ARRAY[2, 3], ARRAY[10,11,12])", "VALUES (2, 2, 10), (3, 3, 11), (NULL, NULL, 12)");
+ assertQuery("SELECT * from unnest(MAP(ARRAY[2, 3], ARRAY['a', 'b']), MAP(ARRAY[2, 3], ARRAY['a', 'b']))", "VALUES (2, 'a', 2, 'a'), (3, 'b', 3, 'b')");
+ assertQuery("SELECT * from unnest(MAP(ARRAY[2, 3], ARRAY['a', 'b']), MAP(ARRAY[1, 2, 3], ARRAY['a', 'b', 'c']), MAP(ARRAY[2, 3], ARRAY['a', 'b']))",
+ "VALUES (2, 'a', 1, 'a', 2, 'a'), (3, 'b', 2, 'b', 3, 'b'), (NULL, NULL, 3, 'c', NULL, NULL)");
+ assertQuery("SELECT * from unnest(MAP(ARRAY[2, 3], ARRAY['a', 'b']), MAP(ARRAY[2, 3], ARRAY['a', 'b']), MAP(ARRAY[1, 2, 3], ARRAY['a', 'b', 'c']))",
+ "VALUES (2, 'a', 2, 'a', 1, 'a'), (3, 'b', 3, 'b', 2, 'b'), (NULL, NULL, NULL, NULL, 3, 'c')");
+
+ assertQuery("SELECT * from unnest(ARRAY[2, 3], ARRAY[2, 3]) WITH ORDINALITY AS r(r1, r2, ord)", "VALUES (2, 2, 1), (3, 3, 2)");
+ assertQuery("SELECT * from unnest(ARRAY[2, 3], ARRAY[2, 3], ARRAY[2, 3]) WITH ORDINALITY AS r(r1, r2, r3, ord)", "VALUES (2, 2, 2, 1), (3, 3, 3, 2)");
+ assertQuery("SELECT * from unnest(ARRAY[2, 3], ARRAY[10,11,12], ARRAY[2, 3]) WITH ORDINALITY AS r(r1, r2, r3, ord)", "VALUES (2, 10, 2, 1), (3, 11, 3, 2), (NULL, 12, NULL, 3)");
+ assertQuery("SELECT * from unnest(ARRAY[2, 3], ARRAY[2, 3], ARRAY[10,11,12]) WITH ORDINALITY AS r(r1, r2, r3, ord)", "VALUES (2, 2, 10, 1), (3, 3, 11, 2), (NULL, NULL, 12, 3)");
+
+ assertQueryFails("SELECT * from unnest(ARRAY[row(2, 3), row(3, 5)], ARRAY[row(2, 3), row(3, 5)]) AS r(r1, r2, r3, r4)",
+ "Field not found: field_.*. Available fields are: field, field_.*", true);
+ assertQueryFails("SELECT * from unnest(ARRAY[row(2, 3), row(3, 5)], ARRAY[row(2, 3), row(3, 5)]) WITH ORDINALITY AS r(r1, r2, r3, r4, ord)",
+ "Field not found: field_.*. Available fields are: field, field_.*", true);
+
+ assertQuery(useLegacyUnnest, "SELECT cast(r1 as row(x int, y int)), cast(r2 as row(x int, y int)) from unnest(ARRAY[row(2, 3), row(3, 5)], ARRAY[row(2, 3), row(3, 5)]) AS r(r1, r2)",
+ "VALUES (row(2, 3), row(2, 3)), (row(3, 5), row(3, 5))");
+ assertQuery(useLegacyUnnest, "SELECT cast(r1 as row(x int, y int)), cast(r2 as row(x int, y int)), cast(r3 as row(x int, y int, z int)) from unnest(ARRAY[row(2, 3), row(3, 5)], ARRAY[row(2, 3), row(3, 5)], ARRAY[row(10, 13, 15), row(23, 25, 20)]) AS r(r1, r2, r3)",
+ "VALUES (row(2, 3), row(2, 3), row(10, 13, 15)), (row(3, 5), row(3, 5), row(23, 25, 20))");
+ assertQuery(useLegacyUnnest, "SELECT cast(r1 as row(x int, y int)), cast(r2 as row(x int, y int)), ord from unnest(ARRAY[row(2, 3), row(3, 5)], ARRAY[row(2, 3), row(3, 5)]) WITH ORDINALITY AS r(r1, r2, ord)",
+ "VALUES (row(2, 3), row(2, 3), 1), (row(3, 5), row(3, 5), 2)");
+ assertQuery(useLegacyUnnest, "SELECT cast(r1 as row(x int, y int)), cast(r2 as row(x int, y int)), cast(r3 as row(x int, y int, z int)), ord from unnest(ARRAY[row(2, 3), row(3, 5)], ARRAY[row(2, 3), row(3, 5)], ARRAY[row(10, 13, 15), row(23, 25, 20)]) WITH ORDINALITY AS r(r1, r2, r3, ord)",
+ "VALUES (row(2, 3), row(2, 3), row(10, 13, 15), 1), (row(3, 5), row(3, 5), row(23, 25, 20), 2)");
+
+ // mixed
+ assertQuery("select * from (SELECT * from unnest(ARRAY[2, 3], ARRAY[2, 3]) WITH ORDINALITY AS r(r1, r2, ord)) cross join unnest(ARRAY[2, 3], ARRAY[2, 3])",
+ "VALUES (2, 2, 1, 2, 2), (2, 2, 1, 3, 3), (3, 3, 2, 2, 2), (3, 3, 2, 3, 3)");
+ }
+
+ @Override
+ @Test(dataProvider = "optimize_hash_generation")
+ public void testDoubleDistinctPositiveAndNegativeZero(String optimizeHashGeneration)
+ {
+ Session session = Session.builder(getSession())
+ .setSystemProperty(OPTIMIZE_HASH_GENERATION, optimizeHashGeneration)
+ .build();
+ assertQueryFails(session, "SELECT DISTINCT x FROM (VALUES (DOUBLE '0.0'), (DOUBLE '-0.0')) t(x)",
+ hashGenerationUnsupportedError, true);
+ }
+
+ @Override
+ @Test
+ public void testIn()
+ {
+ assertQuery("SELECT orderkey FROM orders WHERE orderkey IN (1, 2, 3)");
+ assertQuery("SELECT orderkey FROM orders WHERE orderkey IN (1.5, 2.3)", "SELECT orderkey FROM orders LIMIT 0"); // H2 incorrectly matches rows
+ assertQuery("SELECT orderkey FROM orders WHERE orderkey IN (1, 2E0, 3)");
+ assertQuery("SELECT orderkey FROM orders WHERE totalprice IN (1, 2, 3)");
+ assertQuery("SELECT x FROM (values 3, 100) t(x) WHERE x IN (2147483649)", "SELECT * WHERE false");
+ assertQuery("SELECT x FROM (values 3, 100, 2147483648, 2147483649, 2147483650) t(x) WHERE x IN (2147483648, 2147483650)", "values 2147483648, 2147483650");
+ assertQuery("SELECT x FROM (values 3, 100, 2147483648, 2147483649, 2147483650) t(x) WHERE x IN (3, 4, 2147483648, 2147483650)", "values 3, 2147483648, 2147483650");
+ assertQuery("SELECT x FROM (values 1, 2, 3) t(x) WHERE x IN (1 + CAST(rand() < 0 AS bigint), 2 + CAST(rand() < 0 AS bigint))", "values 1, 2");
+ assertQuery("SELECT x FROM (values 1, 2, 3, 4) t(x) WHERE x IN (1 + CAST(rand() < 0 AS bigint), 2 + CAST(rand() < 0 AS bigint), 4)", "values 1, 2, 4");
+ assertQuery("SELECT x FROM (values 1, 2, 3, 4) t(x) WHERE x IN (4, 2, 1)", "values 1, 2, 4");
+ assertQuery("SELECT x FROM (values 1, 2, 3, 2147483648) t(x) WHERE x IN (1 + CAST(rand() < 0 AS bigint), 2 + CAST(rand() < 0 AS bigint), 2147483648)", "values 1, 2, 2147483648");
+ assertQuery("SELECT x IN (0) FROM (values 4294967296) t(x)", "values false");
+ assertQuery("SELECT x IN (0, 4294967297 + CAST(rand() < 0 AS bigint)) FROM (values 4294967296, 4294967297) t(x)", "values false, true");
+ assertQuery("SELECT NULL in (1, 2, 3)", "values null");
+ assertQuery("SELECT 1 in (1, NULL, 3)", "values true");
+ assertQuery("SELECT 2 in (1, NULL, 3)", "values null");
+ assertQuery("SELECT x FROM (values DATE '1970-01-01', DATE '1970-01-03') t(x) WHERE x IN (DATE '1970-01-01')", "values DATE '1970-01-01'");
+ assertQueryFails("SELECT x FROM (values TIMESTAMP '1970-01-01 00:01:00+00:00', TIMESTAMP '1970-01-01 08:01:00+08:00', TIMESTAMP '1970-01-01 00:01:00+08:00') t(x) WHERE x IN (TIMESTAMP '1970-01-01 00:01:00+00:00')",
+ timestampTzTypeUnsupportedError, true);
+ assertQuery("SELECT COUNT(*) FROM (values 1) t(x) WHERE x IN (null, 0)", "SELECT 0");
+ assertQuery("SELECT d IN (DECIMAL '2.0', DECIMAL '30.0') FROM (VALUES (2.0E0)) t(d)", "SELECT true"); // coercion with type only coercion inside IN list
+ }
+
+ @Override
+ @Test
+ public void testPreserveAssignmentsInJoin()
+ {
+ // The following two timestamps represent the same point in time but with different time zones
+ String timestampLosAngeles = "2001-08-22 03:04:05.321 America/Los_Angeles";
+ String timestampNewYork = "2001-08-22 06:04:05.321 America/New_York";
+ String sql = "WITH source AS (" +
+ "SELECT * FROM (" +
+ " VALUES" +
+ " (TIMESTAMP '" + timestampLosAngeles + "')," +
+ " (TIMESTAMP '" + timestampNewYork + "')" +
+ ") AS tbl (tstz)" +
+ ")" +
+ "SELECT * FROM source a JOIN source b ON a.tstz = b.tstz";
+ assertQueryFails(sql, timestampTzTypeUnsupportedError, true);
+ }
+
+ @Override
+ @Test(dataProvider = "optimize_hash_generation")
+ public void testRealDistinctPositiveAndNegativeZero(String optimizeHashGeneration)
+ {
+ Session session = Session.builder(getSession())
+ .setSystemProperty(OPTIMIZE_HASH_GENERATION, optimizeHashGeneration)
+ .build();
+ assertQueryFails(session, "SELECT DISTINCT x FROM (VALUES (REAL '0.0'), (REAL '-0.0')) t(x)",
+ hashGenerationUnsupportedError, true);
+ }
+
+ @Override
+ @Test(dataProvider = "optimize_hash_generation")
+ public void testRealJoinPositiveAndNegativeZero(String optimizeHashGeneration)
+ {
+ Session session = Session.builder(getSession())
+ .setSystemProperty(OPTIMIZE_HASH_GENERATION, optimizeHashGeneration)
+ .build();
+ assertQueryFails(session, "WITH t AS ( SELECT * FROM (VALUES(REAL '0.0'), (REAL '-0.0'))_t(x)) SELECT * FROM t t1 JOIN t t2 on t1.x = t2.x",
+ hashGenerationUnsupportedError, true);
+ }
+
+ @Override
+ @Test
+ public void testMergeEmptyNonEmptyApproxSet()
+ {
+ assertQueryFails("SELECT cardinality(merge(c)) FROM (SELECT create_hll(custkey) c FROM orders UNION ALL SELECT empty_approx_set())",
+ "Scalar function name not registered: presto.default.create_hll, called with arguments: \\(BIGINT\\)", true);
+ }
+
+ @Override
+ @Test
+ public void testSetUnion()
+ {
+ // sanity
+ assertQuery(
+ "select set_union(x) from (values array[1, 2], array[3, 4], array[5, 6]) as t(x)",
+ "select array[1, 2, 3, 4, 5, 6]");
+ assertQuery(
+ "select set_union(x) from (values array[1, 2, 3], array[2, 3, 4], array[7, 8]) as t(x)",
+ "select array[1, 2, 3, 4, 7, 8]");
+ assertQuery(
+ "select group_id, set_union(numbers) from (values (1, array[1, 2]), (1, array[2, 3]), (2, array[4, 5]), (2, array[5, 6])) as t(group_id, numbers) group by group_id",
+ "select group_id, numbers from (values (1, array[1, 2, 3]), (2, array[4, 5, 6])) as t(group_id, numbers)");
+ assertQuery(
+ "select group_id, set_union(numbers) from (values (1, array[1, 2]), (2, array[2, 3]), (3, array[4, 5]), (4, array[5, 6])) as t(group_id, numbers) group by group_id",
+ "select group_id, numbers from (values (1, array[1, 2]), (2, array[2, 3]), (3, array[4, 5]), (4, array[5, 6])) as t(group_id, numbers)");
+ // all nulls should return empty array to match behavior of array_distinct(flatten(array_agg(x)))
+ assertQueryFails(
+ "select set_union(x) from (values null, null, null) as t(x)",
+ "Unexpected type UNKNOWN", true);
+ // nulls inside arrays should be captured while pure nulls should be ignored
+ assertQueryFails(
+ "select set_union(x) from (values null, array[null], null) as t(x)",
+ "Unexpected type UNKNOWN", true);
+ // null inside arrays should be captured
+ assertQuery(
+ "select set_union(x) from (values array[1, 2, 3], array[null], null) as t(x)",
+ "select array[1, 2, 3, null]");
+ // return null for empty rows
+ assertQueryFails(
+ "select set_union(x) from (values null, array[null], null) as t(x) where x != null",
+ "Unexpected type UNKNOWN", true);
+ }
+
+ @Override
+ @Test
+ public void testSamplingJoinChain()
+ {
+ Session sessionWithKeyBasedSampling = Session.builder(getSession())
+ .setSystemProperty(KEY_BASED_SAMPLING_ENABLED, "true")
+ .build();
+ String query = "select count(1) FROM lineitem l left JOIN orders o ON l.orderkey = o.orderkey JOIN customer c ON o.custkey = c.custkey";
+
+ assertQuery(query, "select 60175");
+ assertQueryFails(sessionWithKeyBasedSampling, query, "Scalar function name not registered: presto.default.key_sampling_percent, called with arguments", true);
+ }
+
+ @Override
+ @Test
+ public void testApproxSetBigint()
+ {
+ MaterializedResult actual = computeActual("SELECT cardinality(approx_set(custkey)) FROM orders");
+
+ // PRESTISSIMO_FIX
+ MaterializedResult expected = resultBuilder(getSession(), BIGINT)
+ .row(1005L)
+ .build();
+
+ assertEquals(actual.getMaterializedRows(), expected.getMaterializedRows());
+ }
+
+ @Override
+ @Test
+ public void testApproxSetBigintGroupBy()
+ {
+ MaterializedResult actual = computeActual("" +
+ "SELECT orderstatus, cardinality(approx_set(custkey)) " +
+ "FROM orders " +
+ "GROUP BY orderstatus");
+
+ // PRESTISSIMO_FIX
+ MaterializedResult expected = resultBuilder(getSession(), actual.getTypes())
+ .row("O", 1003L)
+ .row("F", 1001L)
+ .row("P", 304L)
+ .build();
+
+ assertEqualsIgnoreOrder(actual.getMaterializedRows(), expected.getMaterializedRows());
+ }
+
+ @Override
+ @Test
+ public void testApproxSetDouble()
+ {
+ MaterializedResult actual = computeActual("SELECT cardinality(approx_set(CAST(custkey AS DOUBLE))) FROM orders");
+
+ MaterializedResult expected = resultBuilder(getSession(), BIGINT)
+ .row(1002L)
+ .build();
+
+ assertEquals(actual.getMaterializedRows(), expected.getMaterializedRows());
+ }
+
+ @Override
+ @Test
+ public void testApproxSetDoubleGroupBy()
+ {
+ MaterializedResult actual = computeActual("" +
+ "SELECT orderstatus, cardinality(approx_set(CAST(custkey AS DOUBLE))) " +
+ "FROM orders " +
+ "GROUP BY orderstatus");
+
+ // PRESTISSIMO_FIX
+ MaterializedResult expected = resultBuilder(getSession(), actual.getTypes())
+ .row("O", 1002L)
+ .row("F", 998L)
+ .row("P", 304L)
+ .build();
+
+ assertEqualsIgnoreOrder(actual.getMaterializedRows(), expected.getMaterializedRows());
+ }
+
+ @Override
+ @Test
+ public void testApproxSetGroupByWithNulls()
+ {
+ MaterializedResult actual = computeActual("" +
+ "SELECT orderstatus, cardinality(approx_set(IF(custkey % 2 <> 0, custkey))) " +
+ "FROM orders " +
+ "GROUP BY orderstatus");
+
+ // PRESTISSIMO_FIX
+ MaterializedResult expected = resultBuilder(getSession(), actual.getTypes())
+ .row("O", 499L)
+ .row("F", 496L)
+ .row("P", 153L)
+ .build();
+
+ assertEqualsIgnoreOrder(actual.getMaterializedRows(), expected.getMaterializedRows());
+ }
+
+ @Override
+ @Test
+ public void testApproxSetVarchar()
+ {
+ MaterializedResult actual = computeActual("SELECT cardinality(approx_set(CAST(custkey AS VARCHAR))) FROM orders");
+
+ // PRESTISSIMO_FIX
+ MaterializedResult expected = resultBuilder(getSession(), BIGINT)
+ .row(1015L)
+ .build();
+
+ assertEquals(actual.getMaterializedRows(), expected.getMaterializedRows());
+ }
+
+ @Override
+ @Test
+ public void testApproxSetVarcharGroupBy()
+ {
+ MaterializedResult actual = computeActual("" +
+ "SELECT orderstatus, cardinality(approx_set(CAST(custkey AS VARCHAR))) " +
+ "FROM orders " +
+ "GROUP BY orderstatus");
+
+ // PRESTISSIMO_FIX
+ MaterializedResult expected = resultBuilder(getSession(), actual.getTypes())
+ .row("O", 1012L)
+ .row("F", 1011L)
+ .row("P", 304L)
+ .build();
+
+ assertEqualsIgnoreOrder(actual.getMaterializedRows(), expected.getMaterializedRows());
+ }
+
+ @Override
+ @Test
+ public void testApproxSetWithNulls()
+ {
+ MaterializedResult actual = computeActual("SELECT cardinality(approx_set(IF(orderstatus = 'O', custkey))) FROM orders");
+
+ // PRESTISSIMO_FIX
+ MaterializedResult expected = resultBuilder(getSession(), actual.getTypes())
+ .row(1003L)
+ .build();
+
+ assertEquals(actual.getMaterializedRows(), expected.getMaterializedRows());
+ }
+
+ @Override
+ @Test
+ public void testApproxSetGroupByWithOnlyNullsInOneGroup()
+ {
+ MaterializedResult actual = computeActual("" +
+ "SELECT orderstatus, cardinality(approx_set(IF(orderstatus != 'O', custkey))) " +
+ "FROM orders " +
+ "GROUP BY orderstatus");
+
+ // PRESTISSIMO_FIX
+ MaterializedResult expected = resultBuilder(getSession(), actual.getTypes())
+ .row("O", null)
+ .row("F", 1001L)
+ .row("P", 304L)
+ .build();
+
+ assertEqualsIgnoreOrder(actual.getMaterializedRows(), expected.getMaterializedRows());
+ }
+
+ @Override
+ @Test
+ public void testReduceAggWithNulls()
+ {
+ assertQueryFails("select reduce_agg(x, null, (x,y)->try(x+y), (x,y)->try(x+y)) from (select 1 union all select 10) T(x)", ".*REDUCE_AGG only supports non-NULL literal as the initial value.*");
+ assertQueryFails("select reduce_agg(x, cast(null as bigint), (x,y)->coalesce(x, 0)+coalesce(y, 0), (x,y)->coalesce(x, 0)+coalesce(y, 0)) from (values cast(10 as bigint),10)T(x)", ".*REDUCE_AGG only supports non-NULL literal as the initial value.*");
+
+ // here some reduce_aggs coalesce overflow/zero-divide errors to null in the input/combine functions
+ assertQuery("select reduce_agg(x, 0, (x,y)->try(1/x+1/y), (x,y)->try(1/x+1/y)) from ((select 0) union all select 10.) T(x)", "select 0.0");
+ assertQueryFails("select reduce_agg(x, 0, (x, y)->try(x+y), (x, y)->try(x+y)) from (values 2817, 9223372036854775807) AS T(x)", "!states->isNullAt\\(i\\) Lambda expressions in reduce_agg should not return null for non-null inputs", true);
+ assertQuery("select reduce_agg(x, array[], (x, y)->array[element_at(x, 2)], (x, y)->array[element_at(x, 2)]) from (select array[array[1]]) T(x)", "select array[null]");
+ }
+
+ @Override
+ @Test(expectedExceptions = {RuntimeException.class, PrestoException.class}, expectedExceptionsMessageRegExp = ".*Scalar function name not registered: presto.default.create_hll, called with arguments.*")
+ public void testMergeEmptyNonEmptyApproxSetWithDifferentMaxError()
+ {
+ computeActual("SELECT cardinality(merge(c)) FROM (SELECT create_hll(custkey, 0.1) c FROM orders UNION ALL SELECT empty_approx_set(0.2))");
+ }
+
+ //@Test @Override
+ @Override
+ @Test(expectedExceptions = {RuntimeException.class, PrestoException.class}, expectedExceptionsMessageRegExp = ".*Scalar function name not registered: presto.default.create_hll, called with arguments.*")
+ public void testMergeEmptyNonEmptyApproxSetWithSameMaxError()
+ {
+ MaterializedResult actual = computeActual("SELECT cardinality(merge(c)) FROM (SELECT create_hll(custkey, 0.1) c FROM orders UNION ALL SELECT empty_approx_set(0.1))");
+ // PRESTISSIMO_FIX
+ MaterializedResult expected = resultBuilder(getSession(), BIGINT)
+ .row(1046L)
+ .build();
+ assertEquals(actual.getMaterializedRows(), expected.getMaterializedRows());
+ }
+
+ @Override
+ @Test
+ public void testRows()
+ {
+ // Using JSON_FORMAT(CAST(_ AS JSON)) because H2 does not support ROW type
+ Session session = Session.builder(getSession()).setSystemProperty(FIELD_NAMES_IN_JSON_CAST_ENABLED, "true").build();
+ assertQuery(session, "SELECT JSON_FORMAT(CAST(ROW(1 + 2, CONCAT('a', 'b')) AS JSON))", "SELECT '{\"\":3,\"\":\"ab\"}'");
+ assertQuery(session, "SELECT JSON_FORMAT(CAST(ROW(a + b) AS JSON)) FROM (VALUES (1, 2)) AS t(a, b)", "SELECT '[3]'");
+ assertQuery(session, "SELECT JSON_FORMAT(CAST(ROW(1, ROW(9, a, ARRAY[], NULL), ROW(1, 2)) AS JSON)) FROM (VALUES ('a')) t(a)",
+ "SELECT '[1,[9,\"a\",[],null],[1,2]]'");
+ assertQuery(session, "SELECT JSON_FORMAT(CAST(ROW(ROW(ROW(ROW(ROW(a, b), c), d), e), f) AS JSON)) FROM (VALUES (ROW(0, 1), 2, '3', NULL, ARRAY[5], ARRAY[])) t(a, b, c, d, e, f)",
+ "SELECT '[[[[[[0,1],2],\"3\"],null],[5]],[]]'");
+ assertQuery(session, "SELECT JSON_FORMAT(CAST(ARRAY_AGG(ROW(a, b)) AS JSON)) FROM (VALUES (1, 2), (3, 4), (5, 6)) t(a, b)",
+ "SELECT '[[1,2],[3,4],[5,6]]'");
+ assertQuery(session, "SELECT CONTAINS(ARRAY_AGG(ROW(a, b)), ROW(1, 2)) FROM (VALUES (1, 2), (3, 4), (5, 6)) t(a, b)", "SELECT TRUE");
+ assertQuery(session, "SELECT JSON_FORMAT(CAST(ARRAY_AGG(ROW(c, d)) AS JSON)) FROM (VALUES (ARRAY[1, 3, 5], ARRAY[2, 4, 6])) AS t(a, b) CROSS JOIN UNNEST(a, b) AS u(c, d)",
+ "SELECT '[[1,2],[3,4],[5,6]]'");
+ assertQuery(session, "SELECT JSON_FORMAT(CAST(ROW(x, y, z) AS JSON)) FROM (VALUES ROW(1, NULL, '3')) t(x,y,z)", "SELECT '[1,null,\"3\"]'");
+ assertQuery(session, "SELECT JSON_FORMAT(CAST(ROW(x, y, z) AS JSON)) FROM (VALUES ROW(1, CAST(NULL AS INTEGER), '3')) t(x,y,z)", "SELECT '[1,null,\"3\"]'");
+ }
+
+ @Override
+ @Test(enabled = false)
+ public void testCorrelatedNonAggregationScalarSubqueries()
+ {
+ String subqueryReturnedTooManyRows = ".*Scalar sub-query has returned multiple rows.*";
+
+ assertQuery("SELECT (SELECT 1 WHERE a = 2) FROM (VALUES 1) t(a)", "SELECT null");
+ assertQuery("SELECT (SELECT 2 WHERE a = 1) FROM (VALUES 1) t(a)", "SELECT 2");
+ assertQueryFails(
+ "SELECT (SELECT 2 FROM (VALUES 3, 4) WHERE a = 1) FROM (VALUES 1) t(a)",
+ subqueryReturnedTooManyRows);
+
+ // multiple subquery output projections
+ // TODO: Check why expected query runner throws an error but native query runner doesn't.
+ assertQueryFails(
+ "SELECT name FROM nation n WHERE 'AFRICA' = (SELECT 'bleh' FROM region WHERE regionkey > n.regionkey)",
+ subqueryReturnedTooManyRows);
+ assertQueryFails(
+ "SELECT name FROM nation n WHERE 'AFRICA' = (SELECT name FROM region WHERE regionkey > n.regionkey)",
+ subqueryReturnedTooManyRows);
+ assertQueryFails(
+ "SELECT name FROM nation n WHERE 1 = (SELECT 1 FROM region WHERE regionkey > n.regionkey)",
+ subqueryReturnedTooManyRows);
+
+ // correlation used in subquery output
+ assertQueryFails(
+ "SELECT name FROM nation n WHERE 'AFRICA' = (SELECT n.name FROM region WHERE regionkey > n.regionkey)",
+ UNSUPPORTED_CORRELATED_SUBQUERY_ERROR_MSG);
+
+ assertQuery(
+ "SELECT (SELECT 2 WHERE o.orderkey = 1) FROM orders o ORDER BY orderkey LIMIT 5",
+ "VALUES 2, null, null, null, null");
+ // outputs plain correlated orderkey symbol which causes ambiguity with outer query orderkey symbol
+ assertQueryFails(
+ "SELECT (SELECT o.orderkey WHERE o.orderkey = 1) FROM orders o ORDER BY orderkey LIMIT 5",
+ UNSUPPORTED_CORRELATED_SUBQUERY_ERROR_MSG);
+ assertQueryFails(
+ "SELECT (SELECT o.orderkey * 2 WHERE o.orderkey = 1) FROM orders o ORDER BY orderkey LIMIT 5",
+ UNSUPPORTED_CORRELATED_SUBQUERY_ERROR_MSG);
+ // correlation used outside the subquery
+ assertQueryFails(
+ "SELECT o.orderkey, (SELECT o.orderkey * 2 WHERE o.orderkey = 1) FROM orders o ORDER BY orderkey LIMIT 5",
+ UNSUPPORTED_CORRELATED_SUBQUERY_ERROR_MSG);
+
+ // aggregation with having
+// TODO: uncomment below test once #8456 is fixed
+// assertQuery("SELECT (SELECT avg(totalprice) FROM orders GROUP BY custkey, orderdate HAVING avg(totalprice) < a) FROM (VALUES 900) t(a)");
+
+ // correlation in predicate
+ assertQueryFails("SELECT name FROM nation n WHERE 'AFRICA' = (SELECT name FROM region WHERE regionkey = n.regionkey)", failNotRegisteredError, true);
+
+ // same correlation in predicate and projection
+ assertQueryFails(
+ "SELECT nationkey FROM nation n WHERE " +
+ "(SELECT n.regionkey * 2 FROM region r WHERE n.regionkey = r.regionkey) > 6",
+ UNSUPPORTED_CORRELATED_SUBQUERY_ERROR_MSG);
+
+ // different correlation in predicate and projection
+ assertQueryFails(
+ "SELECT nationkey FROM nation n WHERE " +
+ "(SELECT n.nationkey * 2 FROM region r WHERE n.regionkey = r.regionkey) > 6",
+ UNSUPPORTED_CORRELATED_SUBQUERY_ERROR_MSG);
+
+ // correlation used in subrelation
+ assertQueryFails(
+ "SELECT nationkey FROM nation n WHERE " +
+ "(SELECT regionkey * 2 FROM (SELECT regionkey FROM region r WHERE n.regionkey = r.regionkey)) > 6 " +
+ "ORDER BY 1 LIMIT 3", failNotRegisteredError, true);
+
+ // with duplicated rows
+ assertQueryFails(
+ "SELECT (SELECT name FROM nation WHERE nationkey = a) FROM (VALUES 1, 1, 2, 3) t(a)", failNotRegisteredError, true);
+
+ // returning null when nothing matched
+ assertQueryFails(
+ "SELECT (SELECT name FROM nation WHERE nationkey = a) FROM (VALUES 31) t(a)", failNotRegisteredError, true);
+
+ assertQueryFails(
+ "SELECT (SELECT r.name FROM nation n, region r WHERE r.regionkey = n.regionkey AND n.nationkey = a) FROM (VALUES 1) t(a)", failNotRegisteredError, true);
+ }
+
+ @Override
+ @Test(enabled = false)
+ public void testScalarSubquery()
+ {
+ // nested
+ assertQuery("SELECT (SELECT (SELECT (SELECT 1)))");
+
+ // aggregation
+ // TODO: Investigate error 'Caused by: java.lang.IllegalArgumentException: expected types count (22) does not
+ // match actual column count (16)'
+ assertQuery("SELECT * FROM lineitem WHERE orderkey = \n" +
+ "(SELECT max(orderkey) FROM orders)");
+
+ // no output
+ assertQuery("SELECT * FROM lineitem WHERE orderkey = \n" +
+ "(SELECT orderkey FROM orders WHERE 0=1)");
+
+ // no output matching with null test
+ assertQuery("SELECT * FROM lineitem WHERE \n" +
+ "(SELECT orderkey FROM orders WHERE 0=1) " +
+ "is null");
+ assertQuery("SELECT * FROM lineitem WHERE \n" +
+ "(SELECT orderkey FROM orders WHERE 0=1) " +
+ "is not null");
+
+ // subquery results and in in-predicate
+ assertQuery("SELECT (SELECT 1) IN (1, 2, 3)");
+ assertQuery("SELECT (SELECT 1) IN ( 2, 3)");
+
+ // multiple subqueries
+ assertQuery("SELECT (SELECT 1) = (SELECT 3)");
+ assertQuery("SELECT (SELECT 1) < (SELECT 3)");
+ assertQuery("SELECT COUNT(*) FROM lineitem WHERE " +
+ "(SELECT min(orderkey) FROM orders)" +
+ "<" +
+ "(SELECT max(orderkey) FROM orders)");
+ assertQuery("SELECT (SELECT 1), (SELECT 2), (SELECT 3)");
+
+ // distinct
+ assertQuery("SELECT DISTINCT orderkey FROM lineitem " +
+ "WHERE orderkey BETWEEN" +
+ " (SELECT avg(orderkey) FROM orders) - 10 " +
+ " AND" +
+ " (SELECT avg(orderkey) FROM orders) + 10");
+
+ // subqueries with joins
+ assertQuery("SELECT o1.orderkey, COUNT(*) " +
+ "FROM orders o1 " +
+ "INNER JOIN (SELECT * FROM orders ORDER BY orderkey LIMIT 10) o2 " +
+ "ON o1.orderkey " +
+ "BETWEEN (SELECT avg(orderkey) FROM orders) - 10 AND (SELECT avg(orderkey) FROM orders) + 10 " +
+ "GROUP BY o1.orderkey");
+ assertQuery("SELECT o1.orderkey, COUNT(*) " +
+ "FROM (SELECT * FROM orders ORDER BY orderkey LIMIT 5) o1 " +
+ "LEFT JOIN (SELECT * FROM orders ORDER BY orderkey LIMIT 10) o2 " +
+ "ON o1.orderkey " +
+ "BETWEEN (SELECT avg(orderkey) FROM orders) - 10 AND (SELECT avg(orderkey) FROM orders) + 10 " +
+ "GROUP BY o1.orderkey");
+ assertQuery("SELECT o1.orderkey, COUNT(*) " +
+ "FROM orders o1 RIGHT JOIN (SELECT * FROM orders ORDER BY orderkey LIMIT 10) o2 " +
+ "ON o1.orderkey " +
+ "BETWEEN (SELECT avg(orderkey) FROM orders) - 10 AND (SELECT avg(orderkey) FROM orders) + 10 " +
+ "GROUP BY o1.orderkey");
+ assertQuery("SELECT DISTINCT COUNT(*) " +
+ "FROM (SELECT * FROM orders ORDER BY orderkey LIMIT 5) o1 " +
+ "FULL JOIN (SELECT * FROM orders ORDER BY orderkey LIMIT 10) o2 " +
+ "ON o1.orderkey " +
+ "BETWEEN (SELECT avg(orderkey) FROM orders) - 10 AND (SELECT avg(orderkey) FROM orders) + 10 " +
+ "GROUP BY o1.orderkey",
+ "VALUES 1, 10");
+
+ // subqueries with ORDER BY
+ assertQuery("SELECT orderkey, totalprice FROM orders ORDER BY (SELECT 2)");
+
+ // subquery returns multiple rows
+ String multipleRowsErrorMsg = "Scalar sub-query has returned multiple rows";
+ assertQueryFails("SELECT * FROM lineitem WHERE orderkey = (\n" +
+ "SELECT orderkey FROM orders ORDER BY totalprice)",
+ multipleRowsErrorMsg);
+ assertQueryFails("SELECT orderkey, totalprice FROM orders ORDER BY (VALUES 1, 2)",
+ multipleRowsErrorMsg);
+
+ // exposes a bug in optimize hash generation because EnforceSingleNode does not
+ // support more than one column from the underlying query
+ assertQuery("SELECT custkey, (SELECT DISTINCT custkey FROM orders ORDER BY custkey LIMIT 1) FROM orders");
+
+ // cast scalar sub-query
+ assertQuery("SELECT 1.0/(SELECT 1), CAST(1.0 AS REAL)/(SELECT 1), 1/(SELECT 1)");
+ assertQuery("SELECT 1.0 = (SELECT 1) AND 1 = (SELECT 1), 2.0 = (SELECT 1) WHERE 1.0 = (SELECT 1) AND 1 = (SELECT 1)");
+ assertQuery("SELECT 1.0 = (SELECT 1), 2.0 = (SELECT 1), CAST(2.0 AS REAL) = (SELECT 1) WHERE 1.0 = (SELECT 1)");
+
+ // coerce correlated symbols
+ assertQuery("SELECT * FROM (VALUES 1) t(a) WHERE 1=(SELECT count(*) WHERE 1.0 = a)", "SELECT 1");
+ assertQuery("SELECT * FROM (VALUES 1.0) t(a) WHERE 1=(SELECT count(*) WHERE 1 = a)", "SELECT 1.0");
+ }
+
+ @Override
+ @Test(dataProvider = "optimize_hash_generation")
+ public void testDoubleJoinPositiveAndNegativeZero(String optimizeHashGeneration)
+ {
+ Session session = Session.builder(getSession())
+ .setSystemProperty(OPTIMIZE_HASH_GENERATION, optimizeHashGeneration)
+ .build();
+ assertQueryFails(session, "WITH t AS ( SELECT * FROM (VALUES(DOUBLE '0.0'), (DOUBLE '-0.0'))_t(x)) SELECT * FROM t t1 JOIN t t2 on t1.x = t2.x",
+ hashGenerationUnsupportedError, true);
+ }
+
+ @Override
+ public void testCorrelatedScalarSubqueries()
+ {
+ assertQuery("SELECT (SELECT n.nationkey + n.NATIONKEY) FROM nation n");
+ assertQuery("SELECT (SELECT 2 * n.nationkey) FROM nation n");
+ assertQuery("SELECT nationkey FROM nation n WHERE 2 = (SELECT 2 * n.nationkey)");
+ assertQuery("SELECT nationkey FROM nation n ORDER BY (SELECT 2 * n.nationkey)");
+
+ // group by
+ assertQuery("SELECT max(n.regionkey), 2 * n.nationkey, (SELECT n.nationkey) FROM nation n GROUP BY n.nationkey");
+ assertQuery(
+ "SELECT max(l.quantity), 2 * l.orderkey FROM lineitem l GROUP BY l.orderkey HAVING max(l.quantity) < (SELECT l.orderkey)");
+ assertQuery("SELECT max(l.quantity), 2 * l.orderkey FROM lineitem l GROUP BY l.orderkey, (SELECT l.orderkey)");
+
+ // join
+ assertQuery("SELECT * FROM nation n1 JOIN nation n2 ON n1.nationkey = (SELECT n2.nationkey)");
+ assertQueryFails(
+ "SELECT (SELECT l3.* FROM lineitem l2 CROSS JOIN (SELECT l1.orderkey) l3 LIMIT 1) FROM lineitem l1",
+ UNSUPPORTED_CORRELATED_SUBQUERY_ERROR_MSG);
+
+ // subrelation
+ assertQuery(
+ "SELECT 1 FROM nation n WHERE 2 * nationkey - 1 = (SELECT * FROM (SELECT n.nationkey))",
+ "SELECT 1"); // h2 fails to parse this query
+
+ // two level of nesting
+ assertQuery("SELECT * FROM nation n WHERE 2 = (SELECT (SELECT 2 * n.nationkey))");
+
+ // explicit LIMIT in subquery
+ assertQueryFails(
+ "SELECT (SELECT count(*) FROM (VALUES (7,1)) t(orderkey, value) WHERE orderkey = corr_key LIMIT 1) FROM (values 7) t(corr_key)",
+ UNSUPPORTED_CORRELATED_SUBQUERY_ERROR_MSG);
+
+ assertQuery(
+ "SELECT (SELECT count(*) FROM (VALUES (7,1)) t(orderkey, value) WHERE orderkey = corr_key GROUP BY value LIMIT 2) FROM (values 7) t(corr_key)");
+
+ // Limit(1) and non-constant output symbol of the subquery (count)
+ assertQueryFails("SELECT (SELECT count(*) FROM (VALUES (7,1), (7,2)) t(orderkey, value) WHERE orderkey = corr_key GROUP BY value LIMIT 1) FROM (values 7) t(corr_key)",
+ UNSUPPORTED_CORRELATED_SUBQUERY_ERROR_MSG);
+ }
+
+ @Override
+ public void testLikePrefixAndSuffixWithChars()
+ {
+ assertQueryFails("select x like 'abc%' from (values CAST ('abc' AS CHAR(3)), CAST ('def' AS CHAR(3)), CAST ('bcd' AS CHAR(3))) T(x)", chartimestampTzTypeUnsupportedError, true);
+ assertQueryFails("select x like '%abc%' from (values CAST ('xabcy' AS CHAR(5)), CAST ('abxabcdef' AS CHAR(9)), CAST ('bcd' AS CHAR(3)), CAST ('xabcyabcz' AS CHAR(9))) T(x)", chartimestampTzTypeUnsupportedError, true);
+ assertQueryFails(
+ "select x like '%abc' from (values CAST('xa bc' AS CHAR(5)), CAST ('xabcy' AS CHAR(5)), CAST ('abcd' AS CHAR(4)), CAST ('xabc' AS CHAR(4)), CAST (' xabc' AS CHAR(5))) T(x)", chartimestampTzTypeUnsupportedError, true);
+ assertQueryFails("select x like '%ab_c' from (values CAST('xa bc' AS CHAR(5)), CAST ('xabcy' AS CHAR(5)), CAST ('abcd' AS CHAR(4))) T(x)", chartimestampTzTypeUnsupportedError, true);
+ assertQueryFails("select x like '%' from (values CAST('xa bc' AS CHAR(5)), CAST ('xabcy' AS CHAR(5)), CAST ('abcd' AS CHAR(4))) T(x)", chartimestampTzTypeUnsupportedError, true);
+ assertQueryFails("select x like '%_%' from (values CAST('xa bc' AS CHAR(5)), CAST ('xabcy' AS CHAR(5)), CAST ('abcd' AS CHAR(4))) T(x)", chartimestampTzTypeUnsupportedError, true);
+ assertQueryFails("select x like '%a%' from (values CAST('xa bc' AS CHAR(5)), CAST ('xabcy' AS CHAR(5)), CAST ('abcd' AS CHAR(4))) T(x)", chartimestampTzTypeUnsupportedError, true);
+ assertQueryFails("select x like '%acd%xy%' from (values CAST('xa bc' AS CHAR(5)), CAST ('xabcy' AS CHAR(5)), CAST ('abcd' AS CHAR(4))) T(x)", chartimestampTzTypeUnsupportedError, true);
+ }
+
+ @Override
+ public void testMapBlockBug()
+ {
+ assertQueryFails(" VALUES(MAP_AGG(12345,123))", "Scalar function name not registered: presto.default.map_agg", true);
+ }
+
+ @Override
+ public void testMergeKHyperLogLog()
+ {
+ assertQueryFails("select k1, cardinality(merge(khll)), uniqueness_distribution(merge(khll)) from (select k1, k2, khyperloglog_agg(v1, v2) khll from (values (1, 1, 2, 3), (1, 1, 4, 0), (1, 2, 90, 20), (1, 2, 87, 1), " +
+ "(2, 1, 11, 30), (2, 1, 11, 11), (2, 2, 9, 1), (2, 2, 87, 2)) t(k1, k2, v1, v2) group by k1, k2) group by k1", kp4HlltimestampTzTypeUnsupportedError, true);
+
+ assertQueryFails("select cardinality(merge(khll)), uniqueness_distribution(merge(khll)) from (select k1, k2, khyperloglog_agg(v1, v2) khll from (values (1, 1, 2, 3), (1, 1, 4, 0), (1, 2, 90, 20), (1, 2, 87, 1), " +
+ "(2, 1, 11, 30), (2, 1, 11, 11), (2, 2, 9, 1), (2, 2, 87, 2)) t(k1, k2, v1, v2) group by k1, k2)", kp4HlltimestampTzTypeUnsupportedError, true);
+ }
+
+ @Override
+ public void testReduceAgg()
+ {
+ assertQuery(
+ "SELECT x, reduce_agg(y, 1, (a, b) -> a * b, (a, b) -> a * b) " +
+ "FROM (VALUES (1, 5), (1, 6), (1, 7), (2, 8), (2, 9), (3, 10)) AS t(x, y) " +
+ "GROUP BY x",
+ "VALUES (1, 5 * 6 * 7), (2, 8 * 9), (3, 10)");
+ assertQuery(
+ "SELECT x, reduce_agg(y, 0, (a, b) -> a + b, (a, b) -> a + b) " +
+ "FROM (VALUES (1, 5), (1, 6), (1, 7), (2, 8), (2, 9), (3, 10)) AS t(x, y) " +
+ "GROUP BY x",
+ "VALUES (1, 5 + 6 + 7), (2, 8 + 9), (3, 10)");
+
+ assertQuery(
+ "SELECT x, reduce_agg(y, 1, (a, b) -> a * b, (a, b) -> a * b) " +
+ "FROM (VALUES (1, CAST(5 AS DOUBLE)), (1, 6), (1, 7), (2, 8), (2, 9), (3, 10)) AS t(x, y) " +
+ "GROUP BY x",
+ "VALUES (1, CAST(5 AS DOUBLE) * 6 * 7), (2, 8 * 9), (3, 10)");
+ assertQuery(
+ "SELECT x, reduce_agg(y, 0, (a, b) -> a + b, (a, b) -> a + b) " +
+ "FROM (VALUES (1, CAST(5 AS DOUBLE)), (1, 6), (1, 7), (2, 8), (2, 9), (3, 10)) AS t(x, y) " +
+ "GROUP BY x",
+ "VALUES (1, CAST(5 AS DOUBLE) + 6 + 7), (2, 8 + 9), (3, 10)");
+
+ assertQuery(
+ "SELECT " +
+ "x, " +
+ "array_join(" +
+ " array_sort(" +
+ " split(reduce_agg(y, '', (a, b) -> a || b, (a, b) -> a || b), '')" +
+ " ), " +
+ " ''" +
+ ") " +
+ "FROM (VALUES (1, 'a'), (1, 'b'), (1, 'c'), (2, 'd'), (2, 'e'), (3, 'f')) AS t(x, y) " +
+ "GROUP BY x",
+ "VALUES (1, 'abc'), (2, 'de'), (3, 'f')");
+
+ assertQuery(
+ "SELECT " +
+ "x, " +
+ "array_join(" +
+ " array_sort(" +
+ " array['x'] || reduce_agg(y, ARRAY[''], (a, b) -> a || b, (a, b) -> a || b)" +
+ " ), " +
+ " ''" +
+ ") " +
+ "FROM (VALUES (1, ARRAY['a']), (1, ARRAY['b']), (1, ARRAY['c']), (2, ARRAY['d']), (2, ARRAY['e']), (3, ARRAY['f'])) AS t(x, y) " +
+ "GROUP BY x",
+ "VALUES (1, 'abcx'), (2, 'dex'), (3, 'fx')");
+
+ assertQuery("SELECT REDUCE_AGG((x,y), (0,0), (x, y)->(x[1],y[1]), (x,y)->(x[1],y[1]))[1] from (select 1 x, 2 y)", "select 0");
+ }
+
+ @Override
+ @Test
+ public void testRemoveMapCast()
+ {
+ Session enableOptimization = Session.builder(getSession())
+ .setSystemProperty(REMOVE_MAP_CAST, "true")
+ .build();
+ assertQuery(enableOptimization, "select feature[key] from (values (map(array[cast(1 as integer), 2, 3, 4], array[0.3, 0.5, 0.9, 0.1]), cast(2 as bigint)), (map(array[cast(1 as integer), 2, 3, 4], array[0.3, 0.5, 0.9, 0.1]), 4)) t(feature, key)",
+ "values 0.5, 0.1");
+ assertQuery(enableOptimization, "select element_at(feature, key) from (values (map(array[cast(1 as integer), 2, 3, 4], array[0.3, 0.5, 0.9, 0.1]), cast(2 as bigint)), (map(array[cast(1 as integer), 2, 3, 4], array[0.3, 0.5, 0.9, 0.1]), 4)) t(feature, key)",
+ "values 0.5, 0.1");
+ assertQuery(enableOptimization, "select element_at(feature, key) from (values (map(array[cast(1 as integer), 2, 3, 4], array[0.3, 0.5, 0.9, 0.1]), cast(2 as bigint)), (map(array[cast(1 as integer), 2, 3, 4], array[0.3, 0.5, 0.9, 0.1]), 400000000000)) t(feature, key)",
+ "values 0.5, null");
+ assertQueryFails(enableOptimization, "select feature[key] from (values (map(array[cast(1 as integer), 2, 3, 4], array[0.3, 0.5, 0.9, 0.1]), cast(2 as bigint)), (map(array[cast(1 as integer), 2, 3, 4], array[0.3, 0.5, 0.9, 0.1]), 400000000000)) t(feature, key)",
+ "Cannot cast BIGINT.*to INTEGER. Overflow during arithmetic conversion", true);
+ assertQuery(enableOptimization, "select feature[key] from (values (map(array[cast(1 as varchar), '2', '3', '4'], array[0.3, 0.5, 0.9, 0.1]), cast('2' as varchar)), (map(array[cast(1 as varchar), '2', '3', '4'], array[0.3, 0.5, 0.9, 0.1]), '4')) t(feature, key)",
+ "values 0.5, 0.1");
+ }
+
+ @Override
+ @Test(enabled = false)
+ public void testRemoveRedundantCastToVarcharInJoinClause()
+ {
+ Session session = Session.builder(getSession())
+ .setSystemProperty(REMOVE_REDUNDANT_CAST_TO_VARCHAR_IN_JOIN, "false")
+ .build();
+ // Trigger optimization
+ // TODO: Results do not match, investigate further.
+ assertQuery(session, "select * from orders o join customer c on cast(o.custkey as varchar) = cast(c.custkey as varchar)");
+ assertQuery(session, "select o.orderkey, c.name from orders o join customer c on cast(o.custkey as varchar) = cast(c.custkey as varchar)");
+ assertQuery(session, "select *, cast(o.custkey as varchar) from orders o join customer c on cast(o.custkey as varchar) = cast(c.custkey as varchar)");
+ assertQuery(session, "select *, cast(o.custkey as varchar), cast(c.custkey as varchar) from orders o join customer c on cast(o.custkey as varchar) = cast(c.custkey as varchar)");
+ assertQuery(session, "select r.custkey, r.orderkey, r.name, n.nationkey from (select o.custkey, o.orderkey, c.name from orders o join customer c on cast(o.custkey as varchar) = cast(c.custkey as varchar)) r, nation n");
+ // Do not trigger optimization
+ assertQuery(session, "select * from customer c join orders o on cast(acctbal as varchar) = cast(totalprice as varchar)");
+ }
+
+ @Override
+ @Test(enabled = false)
+ public void testSameAggregationWithAndWithoutFilter()
+ {
+ Session enableOptimization = Session.builder(getSession())
+ .setSystemProperty(MERGE_AGGREGATIONS_WITH_AND_WITHOUT_FILTER, "true")
+ .build();
+ Session disableOptimization = Session.builder(getSession())
+ .setSystemProperty(MERGE_AGGREGATIONS_WITH_AND_WITHOUT_FILTER, "false")
+ .build();
+
+ assertQuery(enableOptimization, "select regionkey, count(name) filter (where name like '%N%') n_nations, count(name) all_nations from nation group by regionkey", "values (3,-6799976246779207259,5),(2,5,5),(0,-6799976246779207262,5),(4,-6799976246779207261,5),(1,-6799976246779207260,5)");
+ assertQuery(enableOptimization, "select count(name) filter (where name like '%N%') n_nations, count(name) all_nations from nation", "values (15,25)");
+ assertQuery(enableOptimization, "select count(1), count(1) filter (where k > 5) from (values 1, null, 3, 5, null, 8, 10) t(k)", "values (7, 2)");
+
+ String sql = "select regionkey, count(name) filter (where name like '%N%') n_nations, count(name) all_nations from nation group by regionkey";
+ MaterializedResult resultWithOptimization = computeActual(enableOptimization, sql);
+ MaterializedResult resultWithoutOptimization = computeActual(disableOptimization, sql);
+
+ // TODO: Results do not match, investigate further.
+ assertEqualsIgnoreOrder(resultWithOptimization, resultWithoutOptimization);
+ sql = "select count(name) filter (where name like '%N%') n_nations, count(name) all_nations from nation";
+ resultWithOptimization = computeActual(enableOptimization, sql);
+ resultWithoutOptimization = computeActual(disableOptimization, sql);
+ assertEqualsIgnoreOrder(resultWithOptimization, resultWithoutOptimization);
+ sql = "select partkey, sum(quantity), sum(quantity) filter (where discount > 0.1) from lineitem group by grouping sets((), (partkey))";
+ resultWithOptimization = computeActual(enableOptimization, sql);
+ resultWithoutOptimization = computeActual(disableOptimization, sql);
+ assertEqualsIgnoreOrder(resultWithOptimization, resultWithoutOptimization);
+
+ // multiple aggregations in query
+ sql = "select partkey, sum(quantity), sum(quantity) filter (where discount < 0.05), sum(linenumber), sum(linenumber) filter (where discount < 0.05) from lineitem group by partkey";
+ resultWithOptimization = computeActual(enableOptimization, sql);
+ resultWithoutOptimization = computeActual(disableOptimization, sql);
+ assertEqualsIgnoreOrder(resultWithOptimization, resultWithoutOptimization);
+ // aggregations in multiple levels
+ sql = "select partkey, avg(sum), avg(sum) filter (where tax < 0.05), avg(filtersum) from (select partkey, suppkey, sum(quantity) sum, sum(quantity) filter (where discount > 0.05) filtersum, max(tax) tax from lineitem where partkey=1598 group by partkey, suppkey) t group by partkey";
+ resultWithOptimization = computeActual(enableOptimization, sql);
+ resultWithoutOptimization = computeActual(disableOptimization, sql);
+ assertEqualsIgnoreOrder(resultWithOptimization, resultWithoutOptimization);
+ // global aggregation
+ sql = "select sum(quantity), sum(quantity) filter (where discount < 0.05) from lineitem";
+ resultWithOptimization = computeActual(enableOptimization, sql);
+ resultWithoutOptimization = computeActual(disableOptimization, sql);
+ assertEqualsIgnoreOrder(resultWithOptimization, resultWithoutOptimization);
+ // order by
+ sql = "select partkey, array_agg(suppkey order by suppkey), array_agg(suppkey order by suppkey) filter (where discount > 0.05) from lineitem group by partkey";
+ resultWithOptimization = computeActual(enableOptimization, sql);
+ resultWithoutOptimization = computeActual(disableOptimization, sql);
+ assertEqualsIgnoreOrder(resultWithOptimization, resultWithoutOptimization);
+ // grouping sets
+ sql = "SELECT partkey, suppkey, sum(quantity), sum(quantity) filter (where discount > 0.05) from lineitem group by grouping sets((), (partkey), (partkey, suppkey))";
+ resultWithOptimization = computeActual(enableOptimization, sql);
+ resultWithoutOptimization = computeActual(disableOptimization, sql);
+ assertEqualsIgnoreOrder(resultWithOptimization, resultWithoutOptimization);
+ // aggregation over union
+ sql = "SELECT partkey, sum(quantity), sum(quantity) filter (where orderkey > 0) from (select quantity, orderkey, partkey from lineitem union all select totalprice as quantity, orderkey, custkey as partkey from orders) group by partkey";
+ resultWithOptimization = computeActual(enableOptimization, sql);
+ resultWithoutOptimization = computeActual(disableOptimization, sql);
+ assertEqualsIgnoreOrder(resultWithOptimization, resultWithoutOptimization);
+ // aggregation over join
+ sql = "select custkey, sum(quantity), sum(quantity) filter (where tax < 0.05) from lineitem l join orders o on l.orderkey=o.orderkey group by custkey";
+ resultWithOptimization = computeActual(enableOptimization, sql);
+ resultWithoutOptimization = computeActual(disableOptimization, sql);
+ assertEqualsIgnoreOrder(resultWithOptimization, resultWithoutOptimization);
+ }
+
+ @Override
+ @Test
+ public void testSetAggIndeterminateArrays()
+ {
+ // union all is to force usage of the serialized state
+ assertQueryFails("SELECT unnested from (SELECT set_agg(x) as agg_result from (" +
+ "SELECT ARRAY[ARRAY[null, 2]] x " +
+ "UNION ALL " +
+ "SELECT ARRAY[null, ARRAY[1, null]] " +
+ "UNION ALL " +
+ "SELECT ARRAY[ARRAY[null, 2]])) " +
+ "CROSS JOIN unnest(agg_result) as r(unnested)",
+ arrayComparisonUnsupportedError, true);
+ }
+
+ @Override
+ @Test
+ public void testSetAggIndeterminateRows()
+ {
+ // union all is to force usage of the serialized state
+ assertQueryFails("SELECT unnested from (SELECT set_agg(x) as agg_result from (" +
+ "SELECT ARRAY[CAST(row(null, 2) AS ROW(INTEGER, INTEGER))] x " +
+ "UNION ALL " +
+ "SELECT ARRAY[null, CAST(row(1, null) AS ROW(INTEGER, INTEGER))] " +
+ "UNION ALL " +
+ "SELECT ARRAY[CAST(row(null, 2) AS ROW(INTEGER, INTEGER))])) " +
+ "CROSS JOIN unnest(agg_result) as r(unnested)",
+ arrayComparisonUnsupportedError, true);
+ }
+
+ @Override
+ @Test
+ public void testSetUnionIndeterminateRows()
+ {
+ // union all is to force usage of the serialized state
+ assertQueryFails("SELECT c1, c2 from (SELECT set_union(x) as agg_result from (" +
+ "SELECT ARRAY[CAST(row(null, 2) AS ROW(INTEGER, INTEGER))] x " +
+ "UNION ALL " +
+ "SELECT ARRAY[null, CAST(row(1, null) AS ROW(INTEGER, INTEGER))] " +
+ "UNION ALL " +
+ "SELECT ARRAY[CAST(row(null, 2) AS ROW(INTEGER, INTEGER))])) " +
+ "CROSS JOIN unnest(agg_result) as r(c1, c2)",
+ ".*Field not found.*", true);
+ }
+
+ @Override
+ @Test
+ public void testTry()
+ {
+ // divide by zero
+ assertQuery(
+ "SELECT linenumber, sum(TRY(100/(CAST (tax*10 AS BIGINT)))) FROM lineitem GROUP BY linenumber",
+ "SELECT linenumber, sum(100/(CAST (tax*10 AS BIGINT))) FROM lineitem WHERE CAST(tax*10 AS BIGINT) <> 0 GROUP BY linenumber");
+
+ // invalid cast
+ assertQuery(
+ "SELECT TRY(CAST(IF(round(totalprice) % 2 = 0, CAST(totalprice AS VARCHAR), '^&$' || CAST(totalprice AS VARCHAR)) AS DOUBLE)) FROM orders",
+ "SELECT CASE WHEN round(totalprice) % 2 = 0 THEN totalprice ELSE null END FROM orders");
+
+ // invalid function argument
+ assertQuery(
+ "SELECT COUNT(TRY(to_base(100, CAST(round(totalprice/100) AS BIGINT)))) FROM orders",
+ "SELECT SUM(CASE WHEN CAST(round(totalprice/100) AS BIGINT) BETWEEN 2 AND 36 THEN 1 ELSE 0 END) FROM orders");
+
+ // as part of a complex expression
+ assertQuery(
+ "SELECT COUNT(CAST(orderkey AS VARCHAR) || TRY(to_base(100, CAST(round(totalprice/100) AS BIGINT)))) FROM orders",
+ "SELECT SUM(CASE WHEN CAST(round(totalprice/100) AS BIGINT) BETWEEN 2 AND 36 THEN 1 ELSE 0 END) FROM orders");
+
+ // missing function argument
+ assertQueryFails("SELECT TRY()", "line 1:8: The 'try' function must have exactly one argument");
+
+ // check that TRY is not pushed down
+ assertQueryFails("SELECT TRY(x) IS NULL FROM (SELECT 1/y AS x FROM (VALUES 1, 2, 3, 0, 4) t(y))", ".*division by zero Top-level Expression.*presto.default.divide.*");
+ assertQuery("SELECT x IS NULL FROM (SELECT TRY(1/y) AS x FROM (VALUES 3, 0, 4) t(y))", "VALUES false, true, false");
+
+ // test try with lambda function
+ assertQueryFails("SELECT TRY(apply(5, x -> x + 1) / 0)", "Scalar function name not registered: presto.default.apply", true);
+ assertQueryFails("SELECT TRY(apply(5 + RANDOM(1), x -> x + 1) / 0)", "Scalar function name not registered: presto.default.apply", true);
+ assertQueryFails("SELECT apply(5 + RANDOM(1), x -> x + TRY(1 / 0))", applyNotRegisteredError, true);
+
+ // test try with invalid JSON
+ assertQuery("SELECT JSON_FORMAT(TRY(JSON 'INVALID'))", "SELECT NULL");
+ assertQuery("SELECT JSON_FORMAT(TRY (JSON_PARSE('INVALID')))", "SELECT NULL");
+
+ // tests that might be constant folded
+ assertQuery("SELECT TRY(CAST(NULL AS BIGINT))", "SELECT NULL");
+ assertQuery("SELECT TRY(CAST('123' AS BIGINT))", "SELECT 123L");
+ assertQuery("SELECT TRY(CAST('foo' AS BIGINT))", "SELECT NULL");
+ assertQuery("SELECT TRY(CAST('foo' AS BIGINT)) + TRY(CAST('123' AS BIGINT))", "SELECT NULL");
+ assertQuery("SELECT TRY(CAST(CAST(123 AS VARCHAR) AS BIGINT))", "SELECT 123L");
+ assertQuery("SELECT COALESCE(CAST(CONCAT('123', CAST(123 AS VARCHAR)) AS BIGINT), 0)", "SELECT 123123L");
+ assertQuery("SELECT TRY(CAST(CONCAT('hello', CAST(123 AS VARCHAR)) AS BIGINT))", "SELECT NULL");
+ assertQuery("SELECT COALESCE(TRY(CAST(CONCAT('a', CAST(123 AS VARCHAR)) AS INTEGER)), 0)", "SELECT 0");
+ assertQuery("SELECT COALESCE(TRY(CAST(CONCAT('a', CAST(123 AS VARCHAR)) AS BIGINT)), 0)", "SELECT 0L");
+ assertQuery("SELECT 123 + TRY(ABS(-9223372036854775807 - 1))", "SELECT NULL");
+ assertQuery("SELECT JSON_FORMAT(TRY(JSON '[]')) || '123'", "SELECT '[]123'");
+ assertQuery("SELECT JSON_FORMAT(TRY(JSON 'INVALID')) || '123'", "SELECT NULL");
+ assertQuery("SELECT TRY(2/1)", "SELECT 2");
+ assertQuery("SELECT TRY(2/0)", "SELECT null");
+ assertQuery("SELECT COALESCE(TRY(2/0), 0)", "SELECT 0");
+ assertQuery("SELECT TRY(ABS(-2))", "SELECT 2");
+
+ // test try with null
+ assertQuery("SELECT TRY(1 / x) FROM (SELECT NULL as x)", "SELECT NULL");
+ }
+
+ @Override
+ @Test
+ public void testLambdaInAggregation()
+ {
+ assertQuery("SELECT id, reduce_agg(value, 0, (a, b) -> a + b+0, (a, b) -> a + b) FROM ( VALUES (1, 2), (1, 3), (1, 4), (2, 20), (2, 30), (2, 40) ) AS t(id, value) GROUP BY id", "values (1, 9), (2, 90)");
+ assertQuery("SELECT id, 's' || reduce_agg(value, '', (a, b) -> concat(a, b, 's'), (a, b) -> concat(a, b, 's')) FROM ( VALUES (1, '2'), (1, '3'), (1, '4'), (2, '20'), (2, '30'), (2, '40') ) AS t(id, value) GROUP BY id",
+ "values (1, 's2s3ss4ss'), (2, 's20s30ss40ss')");
+ assertQueryFails("SELECT id, reduce_agg(value, array[id, value], (a, b) -> a || b, (a, b) -> a || b) FROM ( VALUES (1, 2), (1, 3), (1, 4), (2, 20), (2, 30), (2, 40) ) AS t(id, value) GROUP BY id",
+ ".*REDUCE_AGG only supports non-NULL literal as the initial value.*");
+ }
+}
diff --git a/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestAggregations.java b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestAggregations.java
new file mode 100644
index 0000000000000..53ee6e496354b
--- /dev/null
+++ b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestAggregations.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed 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 com.facebook.presto.nativetests;
+
+import com.facebook.presto.nativeworker.NativeQueryRunnerUtils;
+import com.facebook.presto.nativeworker.PrestoNativeQueryRunnerUtils;
+import com.facebook.presto.testing.QueryRunner;
+
+public class TestAggregations
+ extends AbstractTestAggregationsNative
+{
+ private static final String storageFormat = "PARQUET";
+
+ @Override
+ protected QueryRunner createQueryRunner() throws Exception
+ {
+ return PrestoNativeQueryRunnerUtils.createNativeQueryRunner(true, storageFormat);
+ }
+
+ @Override
+ protected void createTables()
+ {
+ try {
+ QueryRunner javaQueryRunner = PrestoNativeQueryRunnerUtils.createJavaQueryRunner(storageFormat);
+ NativeQueryRunnerUtils.createAllTables(javaQueryRunner, false);
+ javaQueryRunner.close();
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestDistributedEngineOnlyQueries.java b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestDistributedEngineOnlyQueries.java
new file mode 100644
index 0000000000000..24e714b7cd243
--- /dev/null
+++ b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestDistributedEngineOnlyQueries.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed 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 com.facebook.presto.nativetests;
+
+import com.facebook.presto.Session;
+import com.facebook.presto.common.type.TimeZoneKey;
+import com.facebook.presto.nativeworker.NativeQueryRunnerUtils;
+import com.facebook.presto.nativeworker.PrestoNativeQueryRunnerUtils;
+import com.facebook.presto.testing.QueryRunner;
+import com.facebook.presto.tests.AbstractTestEngineOnlyQueries;
+import org.intellij.lang.annotations.Language;
+import org.testng.annotations.Test;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkState;
+import static org.testng.Assert.assertEquals;
+
+public class TestDistributedEngineOnlyQueries
+ extends AbstractTestEngineOnlyQueries
+{
+ private static final String timeTypeUnsupportedError = ".*Failed to parse type \\[time.*";
+ private static final String timestampTzTypeUnsupportedError = ".*Timestamp with Timezone type is not supported in Prestissimo.*";
+
+ private static final String storageFormat = "PARQUET";
+
+ @Override
+ protected QueryRunner createQueryRunner() throws Exception
+ {
+ return PrestoNativeQueryRunnerUtils.createNativeQueryRunner(true, storageFormat);
+ }
+
+ @Override
+ protected void createTables()
+ {
+ try {
+ QueryRunner javaQueryRunner = PrestoNativeQueryRunnerUtils.createJavaQueryRunner(storageFormat);
+ NativeQueryRunnerUtils.createAllTables(javaQueryRunner, false);
+ javaQueryRunner.close();
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ @Test
+ public void testTimeLiterals()
+ {
+ Session chicago = Session.builder(getSession()).setTimeZoneKey(TimeZoneKey.getTimeZoneKey("America/Chicago")).build();
+ Session kathmandu = Session.builder(getSession()).setTimeZoneKey(TimeZoneKey.getTimeZoneKey("Asia/Kathmandu")).build();
+
+ assertEquals(computeScalar("SELECT DATE '2013-03-22'"), LocalDate.of(2013, 3, 22));
+ assertQuery("SELECT DATE '2013-03-22'");
+ assertQuery(chicago, "SELECT DATE '2013-03-22'");
+ assertQuery(kathmandu, "SELECT DATE '2013-03-22'");
+
+ assertQueryFails("SELECT TIME '3:04:05'", timeTypeUnsupportedError, true);
+ assertQueryFails("SELECT TIME '3:04:05.123'", timeTypeUnsupportedError, true);
+ assertQueryFails("SELECT TIME '3:04:05'", timeTypeUnsupportedError, true);
+ assertQueryFails("SELECT TIME '0:04:05'", timeTypeUnsupportedError, true);
+ assertQueryFails(chicago, "SELECT TIME '3:04:05'", timeTypeUnsupportedError, true);
+ assertQueryFails(kathmandu, "SELECT TIME '3:04:05'", timeTypeUnsupportedError, true);
+
+ assertQueryFails("SELECT TIME '01:02:03.400 Z'", timeTypeUnsupportedError, true);
+ assertQueryFails("SELECT TIME '01:02:03.400 UTC'", timeTypeUnsupportedError, true);
+ assertQueryFails("SELECT TIME '3:04:05 +06:00'", timeTypeUnsupportedError, true);
+ assertQueryFails("SELECT TIME '3:04:05 +0507'", timeTypeUnsupportedError, true);
+ assertQueryFails("SELECT TIME '3:04:05 +03'", timeTypeUnsupportedError, true);
+
+ assertEquals(computeScalar("SELECT TIMESTAMP '1960-01-22 3:04:05'"), LocalDateTime.of(1960, 1, 22, 3, 4, 5));
+ assertEquals(computeScalar("SELECT TIMESTAMP '1960-01-22 3:04:05.123'"), LocalDateTime.of(1960, 1, 22, 3, 4, 5, 123_000_000));
+ assertQuery("SELECT TIMESTAMP '1960-01-22 3:04:05'");
+ assertQuery("SELECT TIMESTAMP '1960-01-22 3:04:05.123'");
+ // TODO #7122 assertQuery(chicago, "SELECT TIMESTAMP '1960-01-22 3:04:05.123'");
+ // TODO #7122 assertQuery(kathmandu, "SELECT TIMESTAMP '1960-01-22 3:04:05.123'");
+
+ assertQueryFails("SELECT TIMESTAMP '1960-01-22 3:04:05 +06:00'", timestampTzTypeUnsupportedError, true);
+ }
+
+ @Override
+ @Test
+ public void testLocallyUnrepresentableTimeLiterals()
+ {
+ LocalDateTime localTimeThatDidNotExist = LocalDateTime.of(2017, 4, 2, 2, 10);
+ checkState(ZoneId.systemDefault().getRules().getValidOffsets(localTimeThatDidNotExist).isEmpty(), "This test assumes certain JVM time zone");
+ // This tests that both Presto runner and H2 can return TIMESTAMP value that never happened in JVM's zone (e.g. is not representable using java.sql.Timestamp)
+ @Language("SQL") String sql = DateTimeFormatter.ofPattern("'SELECT TIMESTAMP '''uuuu-MM-dd HH:mm:ss''").format(localTimeThatDidNotExist);
+ assertEquals(computeScalar(sql), localTimeThatDidNotExist); // this tests Presto and the QueryRunner
+ assertQuery(sql); // this tests H2QueryRunner
+
+ LocalDate localDateThatDidNotHaveMidnight = LocalDate.of(1970, 1, 1);
+ checkState(ZoneId.systemDefault().getRules().getValidOffsets(localDateThatDidNotHaveMidnight.atStartOfDay()).isEmpty(), "This test assumes certain JVM time zone");
+ // This tests that both Presto runner and H2 can return DATE value for a day which midnight never happened in JVM's zone (e.g. is not exactly representable using java.sql.Date)
+ sql = DateTimeFormatter.ofPattern("'SELECT DATE '''uuuu-MM-dd''").format(localDateThatDidNotHaveMidnight);
+ assertEquals(computeScalar(sql), localDateThatDidNotHaveMidnight); // this tests Presto and the QueryRunner
+ assertQuery(sql); // this tests H2QueryRunner
+
+ LocalTime localTimeThatDidNotOccurOn19700101 = LocalTime.of(0, 10);
+ checkState(ZoneId.systemDefault().getRules().getValidOffsets(localTimeThatDidNotOccurOn19700101.atDate(LocalDate.ofEpochDay(0))).isEmpty(), "This test assumes certain JVM time zone");
+ checkState(!Objects.equals(java.sql.Time.valueOf(localTimeThatDidNotOccurOn19700101).toLocalTime(), localTimeThatDidNotOccurOn19700101), "This test assumes certain JVM time zone");
+ sql = DateTimeFormatter.ofPattern("'SELECT TIME '''HH:mm:ss''").format(localTimeThatDidNotOccurOn19700101);
+ assertQueryFails(sql, timeTypeUnsupportedError, true);
+ }
+}
diff --git a/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestDistributedQueriesNoHashGeneration.java b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestDistributedQueriesNoHashGeneration.java
new file mode 100644
index 0000000000000..ee57b560ed60b
--- /dev/null
+++ b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestDistributedQueriesNoHashGeneration.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed 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 com.facebook.presto.nativetests;
+
+import com.facebook.presto.nativeworker.NativeQueryRunnerUtils;
+import com.facebook.presto.nativeworker.PrestoNativeQueryRunnerUtils;
+import com.facebook.presto.testing.QueryRunner;
+import com.google.common.collect.ImmutableMap;
+
+public class TestDistributedQueriesNoHashGeneration
+ extends AbstractTestQueriesNative
+{
+ private static final String storageFormat = "PARQUET";
+
+ @Override
+ protected QueryRunner createQueryRunner()
+ throws Exception
+ {
+ return PrestoNativeQueryRunnerUtils.createNativeQueryRunner(
+ ImmutableMap.of(),
+ ImmutableMap.of("optimizer.optimize-hash-generation", "false"), storageFormat);
+ }
+
+ @Override
+ protected void createTables()
+ {
+ try {
+ QueryRunner javaQueryRunner = PrestoNativeQueryRunnerUtils.createJavaQueryRunner(storageFormat);
+ NativeQueryRunnerUtils.createAllTables(javaQueryRunner, false);
+ javaQueryRunner.close();
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestNonIterativeDistributedQueries.java b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestNonIterativeDistributedQueries.java
new file mode 100644
index 0000000000000..214914e2628e7
--- /dev/null
+++ b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestNonIterativeDistributedQueries.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed 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 com.facebook.presto.nativetests;
+
+import com.facebook.presto.nativeworker.NativeQueryRunnerUtils;
+import com.facebook.presto.nativeworker.PrestoNativeQueryRunnerUtils;
+import com.facebook.presto.testing.QueryRunner;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Test that Presto works with {@link com.facebook.presto.sql.planner.iterative.IterativeOptimizer} disabled.
+ */
+public class TestNonIterativeDistributedQueries
+ extends AbstractTestQueriesNative
+{
+ private static final String storageFormat = "PARQUET";
+
+ @Override
+ protected QueryRunner createQueryRunner() throws Exception
+ {
+ return PrestoNativeQueryRunnerUtils.createNativeQueryRunner(
+ ImmutableMap.of("experimental.iterative-optimizer-enabled", "false"),
+ ImmutableMap.of(), storageFormat);
+ }
+
+ @Override
+ protected void createTables()
+ {
+ try {
+ QueryRunner javaQueryRunner = PrestoNativeQueryRunnerUtils.createJavaQueryRunner(storageFormat);
+ NativeQueryRunnerUtils.createAllTables(javaQueryRunner, false);
+ javaQueryRunner.close();
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestOptimizeMixedDistinctAggregations.java b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestOptimizeMixedDistinctAggregations.java
new file mode 100644
index 0000000000000..8ee9f35f9f601
--- /dev/null
+++ b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestOptimizeMixedDistinctAggregations.java
@@ -0,0 +1,55 @@
+
+/*
+ * Licensed 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 com.facebook.presto.nativetests;
+
+import com.facebook.presto.nativeworker.NativeQueryRunnerUtils;
+import com.facebook.presto.nativeworker.PrestoNativeQueryRunnerUtils;
+import com.facebook.presto.testing.QueryRunner;
+import com.google.common.collect.ImmutableMap;
+
+public class TestOptimizeMixedDistinctAggregations
+ extends AbstractTestAggregationsNative
+{
+ private static final String storageFormat = "PARQUET";
+
+ @Override
+ protected QueryRunner createQueryRunner()
+ throws Exception
+ {
+ return PrestoNativeQueryRunnerUtils.createNativeQueryRunner(
+ ImmutableMap.of(),
+ ImmutableMap.of("optimizer.optimize-mixed-distinct-aggregations", "true"), storageFormat);
+ }
+
+ @Override
+ protected void createTables()
+ {
+ try {
+ QueryRunner javaQueryRunner = PrestoNativeQueryRunnerUtils.createJavaQueryRunner(storageFormat);
+ NativeQueryRunnerUtils.createAllTables(javaQueryRunner, false);
+ javaQueryRunner.close();
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void testCountDistinct()
+ {
+ assertQuery("SELECT COUNT(DISTINCT custkey + 1) FROM orders", "SELECT COUNT(*) FROM (SELECT DISTINCT custkey + 1 FROM orders) t");
+ assertQuery("SELECT COUNT(DISTINCT linenumber), COUNT(*) from lineitem where linenumber < 0");
+ }
+}
diff --git a/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestOrderByQueries.java b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestOrderByQueries.java
new file mode 100644
index 0000000000000..83d58d2970b52
--- /dev/null
+++ b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestOrderByQueries.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed 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 com.facebook.presto.nativetests;
+
+import com.facebook.presto.nativeworker.NativeQueryRunnerUtils;
+import com.facebook.presto.nativeworker.PrestoNativeQueryRunnerUtils;
+import com.facebook.presto.testing.QueryRunner;
+import com.facebook.presto.tests.AbstractTestOrderByQueries;
+import org.testng.annotations.Test;
+
+public class TestOrderByQueries
+ extends AbstractTestOrderByQueries
+{
+ private static final String storageFormat = "PARQUET";
+
+ @Override
+ protected QueryRunner createQueryRunner() throws Exception
+ {
+ return PrestoNativeQueryRunnerUtils.createNativeQueryRunner(true, storageFormat);
+ }
+
+ @Override
+ protected void createTables()
+ {
+ try {
+ QueryRunner javaQueryRunner = PrestoNativeQueryRunnerUtils.createJavaQueryRunner(storageFormat);
+ NativeQueryRunnerUtils.createAllTables(javaQueryRunner, false);
+ javaQueryRunner.close();
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ @Test
+ public void testOrderByWithOutputColumnReference()
+ {
+ assertQueryOrdered("SELECT a*2 AS b FROM (VALUES -1, 0, 2) t(a) ORDER BY b*-1", "VALUES 4, 0, -2");
+ assertQueryOrdered("SELECT a*2 AS b FROM (VALUES -1, 0, 2) t(a) ORDER BY b", "VALUES -2, 0, 4");
+ assertQueryOrdered("SELECT a*-2 AS a FROM (VALUES -1, 0, 2) t(a) ORDER BY a*-1", "VALUES 2, 0, -4");
+ assertQueryOrdered("SELECT a*-2 AS a FROM (VALUES -1, 0, 2) t(a) ORDER BY t.a*-1", "VALUES -4, 0, 2");
+ assertQueryOrdered("SELECT a*-2 FROM (VALUES -1, 0, 2) t(a) ORDER BY a*-1", "VALUES -4, 0, 2");
+ assertQueryOrdered("SELECT a*-2 FROM (VALUES -1, 0, 2) t(a) ORDER BY t.a*-1", "VALUES -4, 0, 2");
+ assertQueryOrdered("SELECT a, a* -1 AS a FROM (VALUES -1, 0, 2) t(a) ORDER BY t.a", "VALUES (-1, 1), (0, 0), (2, -2)");
+ assertQueryOrdered("SELECT a, a* -2 AS b FROM (VALUES -1, 0, 2) t(a) ORDER BY a + b", "VALUES (2, -4), (0, 0), (-1, 2)");
+ assertQueryOrdered("SELECT a AS b, a* -2 AS a FROM (VALUES -1, 0, 2) t(a) ORDER BY a + b", "VALUES (2, -4), (0, 0), (-1, 2)");
+ assertQueryOrdered("SELECT a* -2 AS a FROM (VALUES -1, 0, 2) t(a) ORDER BY a + t.a", "VALUES -4, 0, 2");
+ assertQueryOrdered("SELECT k, SUM(a) a, SUM(b) a FROM (VALUES (1, 2, 3)) t(k, a, b) GROUP BY k ORDER BY k", "VALUES (1, 2, 3)");
+
+ // coercions
+ assertQueryOrdered("SELECT 1 x ORDER BY degrees(x)", "VALUES 1");
+ assertQueryOrdered("SELECT a + 1 AS b FROM (VALUES 1, 2) t(a) ORDER BY -1.0 * b", "VALUES 3, 2");
+ assertQueryOrdered("SELECT a AS b FROM (VALUES 1, 2) t(a) ORDER BY -1.0 * b", "VALUES 2, 1");
+ assertQueryOrdered("SELECT a AS a FROM (VALUES 1, 2) t(a) ORDER BY -1.0 * a", "VALUES 2, 1");
+ assertQueryOrdered("SELECT 1 x ORDER BY degrees(x)", "VALUES 1");
+
+ // groups
+ assertQueryOrdered("SELECT max(a+b), min(a+b) AS a FROM (values (1,2),(3,2),(1,5)) t(a,b) GROUP BY a ORDER BY max(t.a+t.b)", "VALUES (5, 5), (6, 3)");
+ assertQueryOrdered("SELECT max(a+b), min(a+b) AS a FROM (values (1,2),(3,2),(1,5)) t(a,b) GROUP BY a ORDER BY max(t.a+t.b)*-0.1", "VALUES (6, 3), (5, 5)");
+ assertQueryOrdered("SELECT max(a) FROM (values (1,2), (2,1)) t(a,b) GROUP BY b ORDER BY max(b*1.0)", "VALUES 2, 1");
+ assertQueryOrdered("SELECT max(a) AS b FROM (values (1,2), (2,1)) t(a,b) GROUP BY b ORDER BY b", "VALUES 1, 2");
+ assertQueryOrdered("SELECT max(a) FROM (values (1,2), (2,1)) t(a,b) GROUP BY b ORDER BY b*1.0", "VALUES 2, 1");
+ assertQueryOrdered("SELECT max(a)*100 AS c FROM (values (1,2), (2,1)) t(a,b) GROUP BY b ORDER BY max(b) + c", "VALUES 100, 200");
+ assertQueryOrdered("SELECT max(a) FROM (values (1,2), (2,1)) t(a,b) GROUP BY b ORDER BY b", "VALUES 2, 1");
+ assertQueryOrdered("SELECT max(a) FROM (values (1,2), (2,1)) t(a,b) GROUP BY t.b ORDER BY t.b*1.0", "VALUES 2, 1");
+ assertQueryOrdered("SELECT -(a+b) AS a, -(a+b) AS b, a+b FROM (values (41, 42), (-41, -42)) t(a,b) GROUP BY a+b ORDER BY a+b", "VALUES (-83, -83, 83), (83, 83, -83)");
+ assertQueryOrdered("SELECT -a AS a FROM (values (1,2),(3,2)) t(a,b) GROUP BY GROUPING SETS ((a), (a, b)) ORDER BY -a", "VALUES -1, -1, -3, -3");
+ assertQueryOrdered("SELECT a AS foo FROM (values (1,2),(3,2)) t(a,b) GROUP BY GROUPING SETS ((a), (a, b)) HAVING b IS NOT NULL ORDER BY -a", "VALUES 3, 1");
+ assertQueryOrdered("SELECT max(a) FROM (values (1,2),(3,2)) t(a,b) ORDER BY max(-a)", "VALUES 3");
+ assertQueryFails("SELECT max(a) AS a FROM (values (1,2)) t(a,b) GROUP BY b ORDER BY max(a+b)", ".*Invalid reference to output projection attribute from ORDER BY aggregation");
+ assertQueryOrdered("SELECT -a AS a, a AS b FROM (VALUES 1, 2) t(a) GROUP BY t.a ORDER BY a", "VALUES (-2, 2), (-1, 1)");
+ assertQueryOrdered("SELECT -a AS a, a AS b FROM (VALUES 1, 2) t(a) GROUP BY t.a ORDER BY t.a", "VALUES (-1, 1), (-2, 2)");
+ assertQueryOrdered("SELECT -a AS a, a AS b FROM (VALUES 1, 2) t(a) GROUP BY a ORDER BY t.a", "VALUES (-1, 1), (-2, 2)");
+ assertQueryOrdered("SELECT -a AS a, a AS b FROM (VALUES 1, 2) t(a) GROUP BY a ORDER BY t.a+2*a", "VALUES (-2, 2), (-1, 1)");
+ assertQueryOrdered("SELECT -a AS a, a AS b FROM (VALUES 1, 2) t(a) GROUP BY t.a ORDER BY t.a+2*a", "VALUES (-2, 2), (-1, 1)");
+
+ // lambdas
+ assertQueryFails("SELECT x AS y FROM (values (1,2), (2,3)) t(x, y) GROUP BY x ORDER BY apply(x, x -> -x) + 2*x", ".*Scalar function name not registered: presto.default.apply.*");
+ assertQueryFails("SELECT -y AS x FROM (values (1,2), (2,3)) t(x, y) GROUP BY y ORDER BY apply(x, x -> -x)", ".*Scalar function name not registered: presto.default.apply.*");
+ assertQueryFails("SELECT -y AS x FROM (values (1,2), (2,3)) t(x, y) GROUP BY y ORDER BY sum(apply(-y, x -> x * 1.0))", ".*Scalar function name not registered: presto.default.apply.*");
+
+ // distinct
+ assertQueryOrdered("SELECT DISTINCT -a AS b FROM (VALUES 1, 2) t(a) ORDER BY b", "VALUES -2, -1");
+ assertQueryOrdered("SELECT DISTINCT -a AS b FROM (VALUES 1, 2) t(a) ORDER BY 1", "VALUES -2, -1");
+ assertQueryOrdered("SELECT DISTINCT max(a) AS b FROM (values (1,2), (2,1)) t(a,b) GROUP BY b ORDER BY b", "VALUES 1, 2");
+ assertQueryFails("SELECT DISTINCT -a AS b FROM (VALUES (1, 2), (3, 4)) t(a, c) ORDER BY c", ".*For SELECT DISTINCT, ORDER BY expressions must appear in select list");
+ assertQueryFails("SELECT DISTINCT -a AS b FROM (VALUES (1, 2), (3, 4)) t(a, c) ORDER BY 2", ".*ORDER BY position 2 is not in select list");
+
+ // window
+ assertQueryOrdered("SELECT a FROM (VALUES 1, 2) t(a) ORDER BY -row_number() OVER ()", "VALUES 2, 1");
+ assertQueryOrdered("SELECT -a AS a, first_value(-a) OVER (ORDER BY a ROWS 0 PRECEDING) AS b FROM (VALUES 1, 2) t(a) ORDER BY first_value(a) OVER (ORDER BY a ROWS 0 PRECEDING)", "VALUES (-2, -2), (-1, -1)");
+ assertQueryOrdered("SELECT -a AS a FROM (VALUES 1, 2) t(a) ORDER BY first_value(a+t.a*2) OVER (ORDER BY a ROWS 0 PRECEDING)", "VALUES -1, -2");
+
+ assertQueryFails("SELECT a, a* -1 AS a FROM (VALUES -1, 0, 2) t(a) ORDER BY a", ".*'a' is ambiguous");
+ }
+}
diff --git a/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestRepartitionQueries.java b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestRepartitionQueries.java
new file mode 100644
index 0000000000000..3fc0d1e0ac08d
--- /dev/null
+++ b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestRepartitionQueries.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed 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 com.facebook.presto.nativetests;
+
+import com.facebook.presto.nativeworker.NativeQueryRunnerUtils;
+import com.facebook.presto.nativeworker.PrestoNativeQueryRunnerUtils;
+import com.facebook.presto.testing.QueryRunner;
+import com.facebook.presto.tests.AbstractTestRepartitionQueries;
+import org.testng.annotations.Test;
+
+public class TestRepartitionQueries
+ extends AbstractTestRepartitionQueries
+{
+ private static final String storageFormat = "PARQUET";
+
+ @Override
+ protected QueryRunner createQueryRunner() throws Exception
+ {
+ return PrestoNativeQueryRunnerUtils.createNativeQueryRunner(true, storageFormat);
+ }
+
+ @Override
+ protected void createTables()
+ {
+ try {
+ QueryRunner javaQueryRunner = PrestoNativeQueryRunnerUtils.createJavaQueryRunner(storageFormat);
+ NativeQueryRunnerUtils.createAllTables(javaQueryRunner, false);
+ javaQueryRunner.close();
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ @Test
+ public void testIpAddress()
+ {
+ assertQueryFails("WITH lineitem_ex AS \n" +
+ "(\n" +
+ "SELECT\n" +
+ " partkey,\n" +
+ " CAST(\n" +
+ " CONCAT(\n" +
+ " CONCAT(\n" +
+ " CONCAT(\n" +
+ " CONCAT(\n" +
+ " CONCAT(\n" +
+ " CONCAT(CAST((orderkey % 255) AS VARCHAR), '.'),\n" +
+ " CAST((partkey % 255) AS VARCHAR)\n" +
+ " ),\n" +
+ " '.'\n" +
+ " ),\n" +
+ " CAST(suppkey AS VARCHAR)\n" +
+ " ),\n" +
+ " '.'\n" +
+ " ),\n" +
+ " CAST(linenumber AS VARCHAR)\n" +
+ " ) AS ipaddress\n" +
+ " ) AS ip\n" +
+ " FROM lineitem\n" +
+ " )\n" +
+ "SELECT\n" +
+ " CHECKSUM(l.ip) \n" +
+ "FROM lineitem_ex l,\n" +
+ " partsupp p\n" +
+ "WHERE\n" +
+ " l.partkey = p.partkey",
+ "IPAddress type is not supported in Prestissimo", true);
+ }
+}
diff --git a/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestRepartitionQueriesWithSmallPages.java b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestRepartitionQueriesWithSmallPages.java
new file mode 100644
index 0000000000000..00b42088e0915
--- /dev/null
+++ b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestRepartitionQueriesWithSmallPages.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed 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 com.facebook.presto.nativetests;
+
+import com.facebook.presto.nativeworker.NativeQueryRunnerUtils;
+import com.facebook.presto.nativeworker.PrestoNativeQueryRunnerUtils;
+import com.facebook.presto.testing.QueryRunner;
+import com.facebook.presto.tests.AbstractTestRepartitionQueries;
+import org.testng.annotations.Test;
+
+public class TestRepartitionQueriesWithSmallPages
+ extends AbstractTestRepartitionQueries
+{
+ private static final String storageFormat = "PARQUET";
+
+ @Override
+ protected QueryRunner createQueryRunner() throws Exception
+ {
+ return PrestoNativeQueryRunnerUtils.createNativeQueryRunner(true, storageFormat);
+ }
+
+ @Override
+ protected void createTables()
+ {
+ try {
+ QueryRunner javaQueryRunner = PrestoNativeQueryRunnerUtils.createJavaQueryRunner(storageFormat);
+ NativeQueryRunnerUtils.createAllTables(javaQueryRunner, false);
+ javaQueryRunner.close();
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ @Test
+ public void testIpAddress()
+ {
+ assertQueryFails("WITH lineitem_ex AS \n" +
+ "(\n" +
+ "SELECT\n" +
+ " partkey,\n" +
+ " CAST(\n" +
+ " CONCAT(\n" +
+ " CONCAT(\n" +
+ " CONCAT(\n" +
+ " CONCAT(\n" +
+ " CONCAT(\n" +
+ " CONCAT(CAST((orderkey % 255) AS VARCHAR), '.'),\n" +
+ " CAST((partkey % 255) AS VARCHAR)\n" +
+ " ),\n" +
+ " '.'\n" +
+ " ),\n" +
+ " CAST(suppkey AS VARCHAR)\n" +
+ " ),\n" +
+ " '.'\n" +
+ " ),\n" +
+ " CAST(linenumber AS VARCHAR)\n" +
+ " ) AS ipaddress\n" +
+ " ) AS ip\n" +
+ " FROM lineitem\n" +
+ " )\n" +
+ "SELECT\n" +
+ " CHECKSUM(l.ip) \n" +
+ "FROM lineitem_ex l,\n" +
+ " partsupp p\n" +
+ "WHERE\n" +
+ " l.partkey = p.partkey",
+ "IPAddress type is not supported in Prestissimo", true);
+ }
+}
diff --git a/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestTpchDistributedQueries.java b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestTpchDistributedQueries.java
new file mode 100644
index 0000000000000..d6afb3f46c50a
--- /dev/null
+++ b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestTpchDistributedQueries.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed 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 com.facebook.presto.nativetests;
+
+import com.facebook.presto.nativeworker.NativeQueryRunnerUtils;
+import com.facebook.presto.nativeworker.PrestoNativeQueryRunnerUtils;
+import com.facebook.presto.testing.QueryRunner;
+import com.google.common.base.Strings;
+import org.intellij.lang.annotations.Language;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+
+public class TestTpchDistributedQueries
+ extends AbstractTestQueriesNative
+{
+ private static final String storageFormat = "PARQUET";
+
+ @Override
+ protected QueryRunner createQueryRunner() throws Exception
+ {
+ return PrestoNativeQueryRunnerUtils.createNativeQueryRunner(true, storageFormat);
+ }
+
+ @Override
+ protected void createTables()
+ {
+ try {
+ QueryRunner javaQueryRunner = PrestoNativeQueryRunnerUtils.createJavaQueryRunner(storageFormat);
+ NativeQueryRunnerUtils.createAllTables(javaQueryRunner, false);
+ javaQueryRunner.close();
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Test
+ public void testTooLongQuery()
+ {
+ // Generate a super-long query: SELECT x,x,x,x,x,... FROM (VALUES 1,2,3,4,5) t(x)
+ @Language("SQL") String longQuery = "SELECT x" + Strings.repeat(",x", 500_000) + " FROM (VALUES 1,2,3,4,5) t(x)";
+ assertQueryFails(longQuery, "Query text length \\(1000037\\) exceeds the maximum length \\(1000000\\)");
+ }
+
+ @Test
+ public void testAnalyzePropertiesSystemTable()
+ {
+ assertQuery("SELECT COUNT(*) FROM system.metadata.analyze_properties WHERE catalog_name = 'tpch'", "SELECT 0");
+ }
+
+ @Test
+ public void testAnalyze()
+ {
+ assertUpdate("ANALYZE orders", 15000);
+ assertQueryFails("ANALYZE orders WITH (foo = 'bar')", ".* does not support analyze property 'foo'.*");
+ }
+
+ @Test
+ public void testTooManyStages()
+ {
+ @Language("SQL") String query = "WITH\n" +
+ " t1 AS (SELECT nationkey AS x FROM nation where name='UNITED STATES'),\n" +
+ " t2 AS (SELECT a.x+b.x+c.x+d.x AS x FROM t1 a, t1 b, t1 c, t1 d),\n" +
+ " t3 AS (SELECT a.x+b.x+c.x+d.x AS x FROM t2 a, t2 b, t2 c, t2 d),\n" +
+ " t4 AS (SELECT a.x+b.x+c.x+d.x AS x FROM t3 a, t3 b, t3 c, t3 d),\n" +
+ " t5 AS (SELECT a.x+b.x+c.x+d.x AS x FROM t4 a, t4 b, t4 c, t4 d)\n" +
+ "SELECT x FROM t5\n";
+ assertQueryFails(query, "Number of stages in the query \\([0-9]+\\) exceeds the allowed maximum \\([0-9]+\\).*");
+ }
+
+ @Test
+ public void testTableSampleSystem()
+ {
+ int total = computeActual("SELECT orderkey FROM orders").getMaterializedRows().size();
+
+ boolean sampleSizeFound = false;
+ for (int i = 0; i < 100; i++) {
+ int sampleSize = computeActual("SELECT orderkey FROM ORDERS TABLESAMPLE SYSTEM (50)").getMaterializedRows().size();
+ if (sampleSize > 0 && sampleSize < total) {
+ sampleSizeFound = true;
+ break;
+ }
+ }
+ assertTrue(sampleSizeFound, "Table sample returned unexpected number of rows");
+ }
+}
diff --git a/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestWindowQueries.java b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestWindowQueries.java
new file mode 100644
index 0000000000000..45a91b2663ef4
--- /dev/null
+++ b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestWindowQueries.java
@@ -0,0 +1,721 @@
+/*
+ * Licensed 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 com.facebook.presto.nativetests;
+
+import com.facebook.presto.nativeworker.NativeQueryRunnerUtils;
+import com.facebook.presto.nativeworker.PrestoNativeQueryRunnerUtils;
+import com.facebook.presto.testing.QueryRunner;
+import com.facebook.presto.tests.AbstractTestWindowQueries;
+import org.testng.annotations.Test;
+
+public class TestWindowQueries
+ extends AbstractTestWindowQueries
+{
+ private String frameTypeDiffersError = ".*Window frame of type RANGE does not match types of the ORDER BY and frame column.*";
+ private String unsupportedWindowTypeError = ".*Unsupported window type: 2.*";
+ private String invalidOffsetError = ".*Window frame offset value must not be negative or null.*";
+ private String functionNotRegisteredError = ".*Scalar function presto.default.plus not registered with arguments.*";
+
+ private String storageFormat = "PARQUET";
+
+ @Override
+ protected QueryRunner createQueryRunner() throws Exception
+ {
+ return PrestoNativeQueryRunnerUtils.createNativeQueryRunner(true, storageFormat);
+ }
+
+ @Override
+ protected void createTables()
+ {
+ try {
+ QueryRunner javaQueryRunner = PrestoNativeQueryRunnerUtils.createJavaQueryRunner("PARQUET");
+ NativeQueryRunnerUtils.createAllTables(javaQueryRunner, false);
+ javaQueryRunner.close();
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ @Test
+ public void testAllPartitionSameValuesGroup()
+ {
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a GROUPS BETWEEN 1 FOLLOWING AND 2 FOLLOWING) " +
+ "FROM (VALUES 'a', 'a', 'a') T(a)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a GROUPS BETWEEN 2 PRECEDING AND 1 PRECEDING) " +
+ "FROM (VALUES 'a', 'a', 'a') T(a)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a GROUPS BETWEEN 1 PRECEDING AND 1 FOLLOWING) " +
+ "FROM (VALUES 'a', 'a', 'a') T(a)",
+ unsupportedWindowTypeError);
+
+ // test frame bounds at partition bounds
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a GROUPS BETWEEN 10 PRECEDING AND 10 FOLLOWING) " +
+ "FROM (VALUES 'a', 'a', 'a') T(a)",
+ unsupportedWindowTypeError);
+ }
+
+ @Override
+ @Test
+ public void testConstantOffset()
+ {
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS FIRST GROUPS BETWEEN 1 PRECEDING AND 2 FOLLOWING) " +
+ "FROM (VALUES 3, 3, 3, 2, 2, 1, null, null) T(a)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS FIRST GROUPS CURRENT ROW) " +
+ "FROM (VALUES 3, 3, 3, 2, 2, 1, null, null) T(a)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS FIRST GROUPS BETWEEN 0 PRECEDING AND 0 FOLLOWING) " +
+ "FROM (VALUES 3, 3, 3, 2, 2, 1, null, null) T(a)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS FIRST GROUPS BETWEEN 1 FOLLOWING AND 2 FOLLOWING) " +
+ "FROM (VALUES 3, 3, 3, 2, 2, 1, null, null) T(a)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS FIRST GROUPS BETWEEN 2 PRECEDING AND 1 PRECEDING) " +
+ "FROM (VALUES 3, 3, 3, 2, 2, 1, null, null) T(a)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS FIRST GROUPS BETWEEN 2 FOLLOWING AND 1 FOLLOWING) " +
+ "FROM (VALUES 3, 3, 3, 2, 2, 1, null, null) T(a)",
+ unsupportedWindowTypeError);
+ }
+
+ @Override
+ @Test
+ public void testEmptyFrame()
+ {
+ assertQuery("SELECT array_agg(a) OVER(ORDER BY a DESC NULLS LAST RANGE BETWEEN 1 PRECEDING AND 10 PRECEDING) " +
+ "FROM (VALUES 1, 2, 3, null, null, 2, 1, null, null) T(a)",
+ "VALUES " +
+ "CAST(null AS array), " +
+ "null, " +
+ "null, " +
+ "null, " +
+ "null, " +
+ "ARRAY[null, null, null, null], " +
+ "ARRAY[null, null, null, null], " +
+ "ARRAY[null, null, null, null], " +
+ "ARRAY[null, null, null, null]");
+
+ assertQuery("SELECT array_agg(a) OVER(ORDER BY a DESC NULLS LAST RANGE BETWEEN 10 FOLLOWING AND 1 FOLLOWING) " +
+ "FROM (VALUES 1, 2, 3, null, null, 2, 1, null, null) T(a)",
+ "VALUES " +
+ "CAST(null AS array), " +
+ "null, " +
+ "null, " +
+ "null, " +
+ "null, " +
+ "ARRAY[null, null, null, null], " +
+ "ARRAY[null, null, null, null], " +
+ "ARRAY[null, null, null, null], " +
+ "ARRAY[null, null, null, null]");
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a RANGE BETWEEN 0.5 FOLLOWING AND 1.5 FOLLOWING) " +
+ "FROM (VALUES 1, 2, 4) T(a)", frameTypeDiffersError, true);
+
+ assertQuery("SELECT array_agg(a) OVER(ORDER BY a RANGE BETWEEN 1 FOLLOWING AND 2 FOLLOWING) " +
+ "FROM (VALUES 1.0, 1.1) T(a)",
+ "VALUES " +
+ "CAST(null AS array), " +
+ "null");
+
+ assertQuery("SELECT array_agg(a) OVER(ORDER BY a NULLS LAST RANGE BETWEEN 1 FOLLOWING AND 2 FOLLOWING) " +
+ "FROM (VALUES 1.0, 1.1, null) T(a)",
+ "VALUES " +
+ "CAST(null AS array), " +
+ "null, " +
+ "ARRAY[null]");
+
+ assertQuery("SELECT array_agg(a) OVER(ORDER BY a RANGE BETWEEN 2 PRECEDING AND 1 PRECEDING) " +
+ "FROM (VALUES 1.0, 1.1) T(a)",
+ "VALUES " +
+ "CAST(null AS array), " +
+ "null");
+
+ assertQuery("SELECT array_agg(a) OVER(ORDER BY a NULLS FIRST RANGE BETWEEN 2 PRECEDING AND 1 PRECEDING) " +
+ "FROM (VALUES null, 1.0, 1.1) T(a)",
+ "VALUES " +
+ "ARRAY[cast(null as decimal(2,1))], " +
+ "null, " +
+ "null");
+
+ assertQuery("SELECT array_agg(a) OVER(ORDER BY a RANGE BETWEEN 2 PRECEDING AND 1 PRECEDING) " +
+ "FROM (VALUES 1, 2) T(a)",
+ "VALUES " +
+ "null, " +
+ "ARRAY[1]");
+
+ assertQuery("SELECT array_agg(a) OVER(ORDER BY a NULLS FIRST RANGE BETWEEN 2 PRECEDING AND 1 PRECEDING) " +
+ "FROM (VALUES null, 1, 2) T(a)",
+ "VALUES " +
+ "ARRAY[null], " +
+ "null, " +
+ "ARRAY[1]");
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a NULLS FIRST RANGE BETWEEN 2 PRECEDING AND 1.5 PRECEDING) " +
+ "FROM (VALUES null, 1, 2) T(a)",
+ frameTypeDiffersError, true);
+ }
+
+ @Override
+ @Test
+ public void testEmptyFrameGroup()
+ {
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS LAST GROUPS BETWEEN 90 PRECEDING AND 100 PRECEDING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS LAST GROUPS BETWEEN 100 FOLLOWING AND 90 FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ unsupportedWindowTypeError);
+ }
+
+ // TODO: This test is flaky so disabled for now.
+ @Override
+ @Test(enabled = false)
+ public void testInvalidOffset()
+ {
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC RANGE x PRECEDING) " +
+ "FROM (VALUES (1, 0.1), (2, -0.2)) T(a, x)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC RANGE BETWEEN 1 PRECEDING AND x FOLLOWING) " +
+ "FROM (VALUES (1, 0.1), (2, -0.2)) T(a, x)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a DESC RANGE x PRECEDING) " +
+ "FROM (VALUES (1, 0.1), (2, -0.2)) T(a, x)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a DESC RANGE BETWEEN 1 PRECEDING AND x FOLLOWING) " +
+ "FROM (VALUES (1, 0.1), (2, -0.2)) T(a, x)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a DESC RANGE x PRECEDING) " +
+ "FROM (VALUES (1, 0.1), (2, null)) T(a, x)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a DESC RANGE BETWEEN 1 PRECEDING AND x FOLLOWING) " +
+ "FROM (VALUES (1, 0.1), (2, null)) T(a, x)",
+ frameTypeDiffersError);
+
+ // fail if offset is invalid for null sort key
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a DESC RANGE BETWEEN 1 PRECEDING AND x FOLLOWING) " +
+ "FROM (VALUES (1, 0.1), (null, null)) T(a, x)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a DESC RANGE BETWEEN 1 PRECEDING AND x FOLLOWING) " +
+ "FROM (VALUES (1, 0.1), (null, -0.1)) T(a, x)",
+ invalidOffsetError);
+
+ // test invalid offset of different types
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a RANGE x PRECEDING) " +
+ "FROM (VALUES (1, BIGINT '-1')) T(a, x)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a RANGE x PRECEDING) " +
+ "FROM (VALUES (1, INTEGER '-1')) T(a, x)",
+ invalidOffsetError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a RANGE x PRECEDING) " +
+ "FROM (VALUES (SMALLINT '1', SMALLINT '-1')) T(a, x)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a RANGE x PRECEDING) " +
+ "FROM (VALUES (TINYINT '1', TINYINT '-1')) T(a, x)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a RANGE x PRECEDING) " +
+ "FROM (VALUES (1, -1.1e0)) T(a, x)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a RANGE x PRECEDING) " +
+ "FROM (VALUES (1, REAL '-1.1')) T(a, x)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a RANGE x PRECEDING) " +
+ "FROM (VALUES (1, -1.0001)) T(a, x)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a RANGE x PRECEDING) " +
+ "FROM (VALUES (DATE '2001-01-31', INTERVAL '-1' YEAR)) T(a, x)",
+ functionNotRegisteredError, true);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a RANGE x PRECEDING) " +
+ "FROM (VALUES (DATE '2001-01-31', INTERVAL '-1' MONTH)) T(a, x)",
+ functionNotRegisteredError, true);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a RANGE x PRECEDING) " +
+ "FROM (VALUES (DATE '2001-01-31', INTERVAL '-1' DAY)) T(a, x)",
+ functionNotRegisteredError, true);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a RANGE x PRECEDING) " +
+ "FROM (VALUES (DATE '2001-01-31', INTERVAL '-1' HOUR)) T(a, x)",
+ functionNotRegisteredError, true);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a RANGE x PRECEDING) " +
+ "FROM (VALUES (DATE '2001-01-31', INTERVAL '-1' MINUTE)) T(a, x)",
+ functionNotRegisteredError, true);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a RANGE x PRECEDING) " +
+ "FROM (VALUES (DATE '2001-01-31', INTERVAL '-1' SECOND)) T(a, x)",
+ functionNotRegisteredError, true);
+ }
+
+ @Override
+ @Test
+ public void testInvalidOffsetGroup()
+ {
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC GROUPS x PRECEDING) " +
+ "FROM (VALUES (1, 1), (2, -2)) T(a, x)",
+ unsupportedWindowTypeError);
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC GROUPS x PRECEDING) " +
+ "FROM (VALUES (1, 1), (2, -2)) T(a, x)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC GROUPS BETWEEN 1 PRECEDING AND x FOLLOWING) " +
+ "FROM (VALUES (1, 1), (2, -2)) T(a, x)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a DESC GROUPS x PRECEDING) " +
+ "FROM (VALUES (1, 1), (2, -2)) T(a, x)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a DESC GROUPS BETWEEN 1 PRECEDING AND x FOLLOWING) " +
+ "FROM (VALUES (1, 1), (2, -2)) T(a, x)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a DESC GROUPS x PRECEDING) " +
+ "FROM (VALUES (1, 1), (2, null)) T(a, x)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a DESC GROUPS BETWEEN 1 PRECEDING AND x FOLLOWING) " +
+ "FROM (VALUES (1, 1), (2, null)) T(a, x)",
+ unsupportedWindowTypeError);
+
+ // fail if offset is invalid for null sort key
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a DESC GROUPS BETWEEN 1 PRECEDING AND x FOLLOWING) " +
+ "FROM (VALUES (1, 1), (null, null)) T(a, x)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a DESC GROUPS BETWEEN 1 PRECEDING AND x FOLLOWING) " +
+ "FROM (VALUES (1, 1), (null, -1)) T(a, x)",
+ unsupportedWindowTypeError);
+
+ // test invalid offset of different types
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a GROUPS x PRECEDING) " +
+ "FROM (VALUES (1, BIGINT '-1')) T(a, x)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a GROUPS x PRECEDING) " +
+ "FROM (VALUES (1, INTEGER '-1')) T(a, x)",
+ unsupportedWindowTypeError);
+ }
+
+ @Override
+ @Test
+ public void testMixedTypeFrameBounds()
+ {
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS LAST GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS LAST GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS LAST GROUPS BETWEEN CURRENT ROW AND 1 FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS LAST GROUPS BETWEEN 1 PRECEDING AND CURRENT ROW) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS LAST GROUPS BETWEEN 1 PRECEDING AND UNBOUNDED FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS LAST GROUPS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ unsupportedWindowTypeError);
+ }
+
+ @Override
+ @Test
+ public void testMixedTypeFrameBoundsAscendingNullsFirst()
+ {
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS FIRST RANGE BETWEEN UNBOUNDED PRECEDING AND 0.5 PRECEDING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS FIRST RANGE BETWEEN UNBOUNDED PRECEDING AND 1.5 FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS FIRST RANGE BETWEEN CURRENT ROW AND 1.5 FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS FIRST RANGE BETWEEN 1.5 PRECEDING AND CURRENT ROW) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS FIRST RANGE BETWEEN 0.5 PRECEDING AND UNBOUNDED FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS FIRST RANGE BETWEEN 0.5 FOLLOWING AND UNBOUNDED FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ frameTypeDiffersError);
+ }
+
+ @Override
+ @Test
+ public void testMixedTypeFrameBoundsAscendingNullsLast()
+ {
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS LAST RANGE BETWEEN UNBOUNDED PRECEDING AND 0.5 PRECEDING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS LAST RANGE BETWEEN UNBOUNDED PRECEDING AND 1.5 FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS LAST RANGE BETWEEN CURRENT ROW AND 1.5 FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS LAST RANGE BETWEEN 1.5 PRECEDING AND CURRENT ROW) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS LAST RANGE BETWEEN 0.5 PRECEDING AND UNBOUNDED FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS LAST RANGE BETWEEN 0.5 FOLLOWING AND UNBOUNDED FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ frameTypeDiffersError);
+ }
+
+ @Override
+ @Test
+ public void testMixedTypeFrameBoundsDescendingNullsFirst()
+ {
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a DESC NULLS FIRST RANGE BETWEEN UNBOUNDED PRECEDING AND 0.5 PRECEDING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a DESC NULLS FIRST RANGE BETWEEN UNBOUNDED PRECEDING AND 0.5 FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a DESC NULLS FIRST RANGE BETWEEN CURRENT ROW AND 1.5 FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a DESC NULLS FIRST RANGE BETWEEN 1.5 PRECEDING AND CURRENT ROW) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a DESC NULLS FIRST RANGE BETWEEN 1.5 PRECEDING AND UNBOUNDED FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a DESC NULLS FIRST RANGE BETWEEN 1.5 FOLLOWING AND UNBOUNDED FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ frameTypeDiffersError);
+ }
+
+ @Override
+ @Test
+ public void testMixedTypeFrameBoundsDescendingNullsLast()
+ {
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a DESC NULLS LAST RANGE BETWEEN UNBOUNDED PRECEDING AND 0.5 PRECEDING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a DESC NULLS LAST RANGE BETWEEN UNBOUNDED PRECEDING AND 1.5 FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a DESC NULLS LAST RANGE BETWEEN CURRENT ROW AND 1.5 FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a DESC NULLS LAST RANGE BETWEEN 0.5 PRECEDING AND CURRENT ROW) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a DESC NULLS LAST RANGE BETWEEN 0.5 PRECEDING AND UNBOUNDED FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a DESC NULLS LAST RANGE BETWEEN 1.5 FOLLOWING AND UNBOUNDED FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ frameTypeDiffersError);
+ }
+
+ @Override
+ @Test
+ public void testMultipleWindowFunctionsGroup()
+ {
+ // two functions with frame type GROUPS
+ assertQueryFails("SELECT x, array_agg(date) OVER(ORDER BY x GROUPS BETWEEN 1 PRECEDING AND 1 PRECEDING), avg(number) OVER(ORDER BY x GROUPS BETWEEN 1 FOLLOWING AND 1 FOLLOWING) " +
+ "FROM (VALUES " +
+ "(2, DATE '2222-01-01', 4.4), " +
+ "(1, DATE '1111-01-01', 2.2), " +
+ "(3, DATE '3333-01-01', 6.6)) T(x, date, number)",
+ unsupportedWindowTypeError);
+
+ // three functions with different frame types
+ assertQueryFails("SELECT " +
+ "x, " +
+ "array_agg(a) OVER(ORDER BY x RANGE BETWEEN 2 PRECEDING AND CURRENT ROW), " +
+ "array_agg(a) OVER(ORDER BY x GROUPS BETWEEN 1 FOLLOWING AND 2 FOLLOWING), " +
+ "array_agg(a) OVER(ORDER BY x ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) " +
+ "FROM (VALUES " +
+ "(1.0, 1), " +
+ "(2.0, 2), " +
+ "(3.0, 3), " +
+ "(4.0, 4), " +
+ "(5.0, 5), " +
+ "(6.0, 6)) T(x, a)",
+ unsupportedWindowTypeError);
+ }
+
+ @Override
+ public void testNonConstantOffset()
+ {
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a RANGE BETWEEN x * 10 PRECEDING AND y / 10.0 FOLLOWING) " +
+ "FROM (VALUES (1, 0.1, 10), (2, 0.2, 20), (4, 0.4, 40)) T(a, x, y)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a RANGE BETWEEN x * 10 PRECEDING AND y / 10.0 FOLLOWING) " +
+ "FROM (VALUES (1, 0.1, 10), (2, 0.2, 20), (4, 0.4, 40), (null, 0.5, 50)) T(a, x, y)",
+ frameTypeDiffersError);
+ }
+
+ @Override
+ @Test
+ public void testNonConstantOffsetGroup()
+ {
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a GROUPS BETWEEN x PRECEDING AND y FOLLOWING) " +
+ "FROM (VALUES ('a', 1, 1), ('b', 2, 0), ('c', 0, 3)) T(a, x, y)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a GROUPS BETWEEN x FOLLOWING AND y FOLLOWING) " +
+ "FROM (VALUES ('a', 1, 1), ('b', 2, 0), ('c', 3, 3), ('d', 0, 0)) T(a, x, y)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a GROUPS BETWEEN x PRECEDING AND y PRECEDING) " +
+ "FROM (VALUES ('a', 1, 1), ('b', 0, 2), ('c', 2, 1), ('d', 0, 2)) T(a, x, y)",
+ unsupportedWindowTypeError);
+ }
+
+ @Override
+ @Test
+ public void testNoValueFrameBoundsGroup()
+ {
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS FIRST GROUPS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS FIRST GROUPS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS FIRST GROUPS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS FIRST GROUPS BETWEEN CURRENT ROW AND CURRENT ROW) " +
+ "FROM (VALUES 1, null, null, 2, 1) T(a)",
+ unsupportedWindowTypeError);
+ }
+
+ @Override
+ @Test
+ public void testNullsSortKey()
+ {
+ assertQuery("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS FIRST RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING) " +
+ "FROM (VALUES 1, 2, 3, null, null, 2, 1, null, null) T(a)",
+ "VALUES " +
+ "ARRAY[null, null, null, null], " +
+ "ARRAY[null, null, null, null], " +
+ "ARRAY[null, null, null, null], " +
+ "ARRAY[null, null, null, null], " +
+ "ARRAY[1, 1, 2, 2], " +
+ "ARRAY[1, 1, 2, 2], " +
+ "ARRAY[1, 1, 2, 2, 3], " +
+ "ARRAY[1, 1, 2, 2, 3], " +
+ "ARRAY[2, 2, 3]");
+ assertQuery("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS LAST RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING) " +
+ "FROM (VALUES 1, 2, 3, null, null, 2, 1, null, null) T(a)",
+ "VALUES " +
+ "ARRAY[1, 1, 2, 2], " +
+ "ARRAY[1, 1, 2, 2], " +
+ "ARRAY[1, 1, 2, 2, 3], " +
+ "ARRAY[1, 1, 2, 2, 3], " +
+ "ARRAY[2, 2, 3], " +
+ "ARRAY[null, null, null, null], " +
+ "ARRAY[null, null, null, null], " +
+ "ARRAY[null, null, null, null], " +
+ "ARRAY[null, null, null, null]");
+ assertQuery("SELECT array_agg(a) OVER(ORDER BY a DESC NULLS FIRST RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING) " +
+ "FROM (VALUES 1, 2, 3, null, null, 2, 1, null, null) T(a)",
+ "VALUES " +
+ "ARRAY[null, null, null, null], " +
+ "ARRAY[null, null, null, null], " +
+ "ARRAY[null, null, null, null], " +
+ "ARRAY[null, null, null, null], " +
+ "ARRAY[3, 2, 2], " +
+ "ARRAY[3, 2, 2, 1, 1], " +
+ "ARRAY[3, 2, 2, 1, 1], " +
+ "ARRAY[2, 2, 1, 1], " +
+ "ARRAY[2, 2, 1, 1]");
+ assertQuery("SELECT array_agg(a) OVER(ORDER BY a DESC NULLS LAST RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING) " +
+ "FROM (VALUES 1, 2, 3, null, null, 2, 1, null, null) T(a)",
+ "VALUES " +
+ "ARRAY[3, 2, 2], " +
+ "ARRAY[3, 2, 2, 1, 1], " +
+ "ARRAY[3, 2, 2, 1, 1], " +
+ "ARRAY[2, 2, 1, 1], " +
+ "ARRAY[2, 2, 1, 1], " +
+ "ARRAY[null, null, null, null], " +
+ "ARRAY[null, null, null, null], " +
+ "ARRAY[null, null, null, null], " +
+ "ARRAY[null, null, null, null]");
+
+ assertQuery("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS LAST RANGE BETWEEN 1 PRECEDING AND UNBOUNDED FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2) T(a)",
+ "VALUES " +
+ "ARRAY[1, 2, null, null], " +
+ "ARRAY[1, 2, null, null], " +
+ "ARRAY[null, null], " +
+ "ARRAY[null, null]");
+ assertQuery("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS LAST RANGE BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2) T(a)",
+ "VALUES " +
+ "ARRAY[1, 2], " +
+ "ARRAY[1, 2], " +
+ "ARRAY[1, 2, null, null], " +
+ "ARRAY[1, 2, null, null]");
+
+ assertQuery("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS FIRST RANGE BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2) T(a)",
+ "VALUES " +
+ "ARRAY[null, null], " +
+ "ARRAY[null, null], " +
+ "ARRAY[null, null, 1, 2], " +
+ "ARRAY[null, null, 1, 2]");
+
+ assertQuery("SELECT array_agg(a) OVER(ORDER BY a ASC NULLS FIRST RANGE BETWEEN 1 PRECEDING AND UNBOUNDED FOLLOWING) " +
+ "FROM (VALUES 1, null, null, 2) T(a)",
+ "VALUES " +
+ "ARRAY[null, null, 1, 2], " +
+ "ARRAY[null, null, 1, 2], " +
+ "ARRAY[1, 2], " +
+ "ARRAY[1, 2]");
+ }
+
+ @Override
+ @Test
+ public void testOnlyNullsGroup()
+ {
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a GROUPS BETWEEN 1 PRECEDING AND 2 FOLLOWING) " +
+ "FROM (VALUES CAST(null AS integer), null, null) T(a)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a GROUPS BETWEEN 1 FOLLOWING AND 2 FOLLOWING) " +
+ "FROM (VALUES CAST(null AS integer), null, null) T(a)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a GROUPS BETWEEN 2 PRECEDING AND 1 PRECEDING) " +
+ "FROM (VALUES CAST(null AS integer), null, null) T(a)",
+ unsupportedWindowTypeError);
+ }
+
+ @Override
+ @Test
+ public void testWindowPartitioning()
+ {
+ assertQueryFails("SELECT a, p, array_agg(a) OVER(PARTITION BY p ORDER BY a ASC NULLS FIRST RANGE BETWEEN 0.5 PRECEDING AND 1 FOLLOWING) " +
+ "FROM (VALUES (1, 'x'), (2, 'x'), (null, 'x'), (null, 'y'), (2, 'y')) T(a, p)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT a, p, array_agg(a) OVER(PARTITION BY p ORDER BY a ASC NULLS FIRST RANGE BETWEEN 0.5 PRECEDING AND 1 FOLLOWING) " +
+ "FROM (VALUES (1, 'x'), (2, 'x'), (null, 'x'), (null, 'y'), (2, 'y'), (null, null), (null, null), (1, null)) T(a, p)",
+ frameTypeDiffersError);
+ }
+
+ @Override
+ @Test
+ public void testWindowPartitioningGroup()
+ {
+ assertQueryFails("SELECT a, p, array_agg(a) OVER(PARTITION BY p ORDER BY a ASC NULLS FIRST GROUPS BETWEEN 1 PRECEDING AND 1 FOLLOWING) " +
+ "FROM (VALUES (1, 'x'), (2, 'x'), (null, 'x'), (null, 'y'), (2, 'y')) T(a, p)",
+ unsupportedWindowTypeError);
+
+ assertQueryFails("SELECT a, p, array_agg(a) OVER(PARTITION BY p ORDER BY a ASC NULLS FIRST GROUPS BETWEEN 0 PRECEDING AND 1 FOLLOWING) " +
+ "FROM (VALUES (1, 'x'), (2, 'x'), (null, 'x'), (null, 'y'), (2, 'y'), (null, null), (null, null), (1, null)) T(a, p)",
+ unsupportedWindowTypeError);
+ }
+
+ @Override
+ @Test
+ public void testTypes()
+ {
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a RANGE BETWEEN DOUBLE '0.5' PRECEDING AND TINYINT '1' FOLLOWING) " +
+ "FROM (VALUES 1, null, 2) T(a)",
+ frameTypeDiffersError);
+
+ assertQueryFails("SELECT array_agg(a) OVER(ORDER BY a RANGE BETWEEN 0.5 PRECEDING AND 1.000 FOLLOWING) " +
+ "FROM (VALUES REAL '1', null, 2) T(a)",
+ frameTypeDiffersError);
+
+ assertQuery("SELECT x, array_agg(x) OVER(ORDER BY x DESC RANGE BETWEEN interval '1' month PRECEDING AND interval '1' month FOLLOWING) " +
+ "FROM (VALUES DATE '2001-01-31', DATE '2001-08-25', DATE '2001-09-25', DATE '2001-09-26') T(x)",
+ "VALUES " +
+ "(DATE '2001-09-26', ARRAY[DATE '2001-09-26', DATE '2001-09-25']), " +
+ "(DATE '2001-09-25', ARRAY[DATE '2001-09-26', DATE '2001-09-25', DATE '2001-08-25']), " +
+ "(DATE '2001-08-25', ARRAY[DATE '2001-09-25', DATE '2001-08-25']), " +
+ "(DATE '2001-01-31', ARRAY[DATE '2001-01-31'])");
+
+ // January 31 + 1 month sets the frame bound to the last day of February. March 1 is out of range.
+ assertQuery("SELECT x, array_agg(x) OVER(ORDER BY x RANGE BETWEEN CURRENT ROW AND interval '1' month FOLLOWING) " +
+ "FROM (VALUES DATE '2001-01-31', DATE '2001-02-28', DATE '2001-03-01') T(x)",
+ "VALUES " +
+ "(DATE '2001-01-31', ARRAY[DATE '2001-01-31', DATE '2001-02-28']), " +
+ "(DATE '2001-02-28', ARRAY[DATE '2001-02-28', DATE '2001-03-01']), " +
+ "(DATE '2001-03-01', ARRAY[DATE '2001-03-01'])");
+
+ // H2 and Presto has some type conversion problem for Interval type, hence use the same query runner for this query
+ assertQueryFails("SELECT x, array_agg(x) OVER(ORDER BY x RANGE BETWEEN interval '1' year PRECEDING AND interval '1' month FOLLOWING) " +
+ "FROM (VALUES " +
+ "INTERVAL '1' month, " +
+ "INTERVAL '2' month, " +
+ "INTERVAL '5' year) T(x)",
+ functionNotRegisteredError, true);
+ }
+}
diff --git a/presto-tests/src/test/java/com/facebook/presto/tests/AbstractTestEngineOnlyQueries.java b/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestEngineOnlyQueries.java
similarity index 100%
rename from presto-tests/src/test/java/com/facebook/presto/tests/AbstractTestEngineOnlyQueries.java
rename to presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestEngineOnlyQueries.java
diff --git a/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestQueryFramework.java b/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestQueryFramework.java
index 96c5b62d616cf..7d59c94725389 100644
--- a/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestQueryFramework.java
+++ b/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestQueryFramework.java
@@ -310,6 +310,11 @@ protected void assertQueryFails(QueryRunner queryRunner, @Language("SQL") String
QueryAssertions.assertQueryFails(queryRunner, getSession(), sql, expectedMessageRegExp);
}
+ protected void assertQueryFails(@Language("SQL") String sql, @Language("RegExp") String expectedMessageRegExp, Boolean usePatternMatcher)
+ {
+ QueryAssertions.assertQueryFails(queryRunner, getSession(), sql, expectedMessageRegExp, usePatternMatcher);
+ }
+
protected void assertQueryFails(Session session, @Language("SQL") String sql, @Language("RegExp") String expectedMessageRegExp)
{
QueryAssertions.assertQueryFails(queryRunner, session, sql, expectedMessageRegExp);
@@ -330,6 +335,11 @@ protected void assertQueryError(@Language("SQL") String sql, @Language("RegExp")
assertQueryError(queryRunner, getSession(), sql, expectedMessageRegExp);
}
+ protected void assertQueryFails(Session session, @Language("SQL") String sql, @Language("RegExp") String expectedMessageRegExp, Boolean usePatternMatcher)
+ {
+ QueryAssertions.assertQueryFails(queryRunner, session, sql, expectedMessageRegExp, usePatternMatcher);
+ }
+
protected void assertQueryReturnsEmptyResult(@Language("SQL") String sql)
{
QueryAssertions.assertQueryReturnsEmptyResult(queryRunner, getSession(), sql);
diff --git a/presto-tests/src/main/java/com/facebook/presto/tests/QueryAssertions.java b/presto-tests/src/main/java/com/facebook/presto/tests/QueryAssertions.java
index 035051acf2866..94e6ee37aa970 100644
--- a/presto-tests/src/main/java/com/facebook/presto/tests/QueryAssertions.java
+++ b/presto-tests/src/main/java/com/facebook/presto/tests/QueryAssertions.java
@@ -37,6 +37,7 @@
import java.util.OptionalLong;
import java.util.function.Consumer;
import java.util.function.Supplier;
+import java.util.regex.Pattern;
import static com.google.common.base.Strings.nullToEmpty;
import static com.google.common.util.concurrent.Uninterruptibles.sleepUninterruptibly;
@@ -350,6 +351,22 @@ protected static void assertQueryFails(QueryRunner queryRunner, Session session,
}
}
+ protected static void assertQueryFails(QueryRunner queryRunner, Session session, @Language("SQL") String sql, @Language("RegExp") String expectedMessageRegExp, Boolean usePatternMatcher)
+ {
+ try {
+ queryRunner.execute(session, sql);
+ fail(format("Expected query to fail: %s", sql));
+ }
+ catch (RuntimeException ex) {
+ if (usePatternMatcher) {
+ assertExceptionWithPatternMatch(sql, ex, expectedMessageRegExp);
+ }
+ else {
+ assertExceptionMessage(sql, ex, expectedMessageRegExp);
+ }
+ }
+ }
+
protected static void assertQueryReturnsEmptyResult(QueryRunner queryRunner, Session session, @Language("SQL") String sql)
{
try {
@@ -369,6 +386,14 @@ private static void assertExceptionMessage(String sql, Exception exception, @Lan
}
}
+ private static void assertExceptionWithPatternMatch(String sql, Exception exception, @Language("RegExp") String regex)
+ {
+ Pattern p = Pattern.compile(regex, Pattern.MULTILINE);
+ if (!(p.matcher(exception.getMessage()).find())) {
+ fail(format("Expected exception message '%s' to match '%s' for query: %s", exception.getMessage(), regex, sql), exception);
+ }
+ }
+
public static void copyTpchTables(
QueryRunner queryRunner,
String sourceCatalog,