diff --git a/.github/workflows/prestocpp-linux-build-and-unit-test.yml b/.github/workflows/prestocpp-linux-build-and-unit-test.yml
index dee1b269d0a0e..262e89d2d6e9e 100644
--- a/.github/workflows/prestocpp-linux-build-and-unit-test.yml
+++ b/.github/workflows/prestocpp-linux-build-and-unit-test.yml
@@ -165,6 +165,77 @@ jobs:
-Duser.timezone=America/Bahia_Banderas \
-T1C
+ prestocpp-linux-presto-native-tests:
+ needs: prestocpp-linux-build-for-test
+ runs-on: ubuntu-22.04
+ container:
+ image: prestodb/presto-native-dependency:0.292-20250204112033-cf8ba84
+ env:
+ MAVEN_OPTS: "-Xmx4G -XX:+ExitOnOutOfMemoryError"
+ MAVEN_FAST_INSTALL: "-B -V --quiet -T 1C -DskipTests -Dair.check.skip-all -Dmaven.javadoc.skip=true"
+ MAVEN_TEST: "-B -Dair.check.skip-all -Dmaven.javadoc.skip=true -DLogTestDurationListener.enabled=true --fail-at-end"
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Fix git permissions
+ # Usually actions/checkout does this but as we run in a container
+ # it doesn't work
+ run: git config --global --add safe.directory ${GITHUB_WORKSPACE}
+
+ - name: Download artifacts
+ uses: actions/download-artifact@v4
+ with:
+ name: presto-native-build
+ path: presto-native-execution/_build/release
+
+ # Permissions are lost when uploading. Details here: https://github.com/actions/upload-artifact/issues/38
+ - name: Restore execute permissions and library path
+ run: |
+ chmod +x ${GITHUB_WORKSPACE}/presto-native-execution/_build/release/presto_cpp/main/presto_server
+ chmod +x ${GITHUB_WORKSPACE}/presto-native-execution/_build/release/velox/velox/functions/remote/server/velox_functions_remote_server_main
+ # Ensure transitive dependency libboost-iostreams is found.
+ ldconfig /usr/local/lib
+
+ - name: Install OpenJDK8
+ uses: actions/setup-java@v4
+ with:
+ distribution: 'temurin'
+ java-version: '8'
+ cache: 'maven'
+ - name: Download nodejs to maven cache
+ run: .github/bin/download_nodejs
+
+ - name: Maven install
+ env:
+ # Use different Maven options to install.
+ MAVEN_OPTS: "-Xmx2G -XX:+ExitOnOutOfMemoryError"
+ run: |
+ for i in $(seq 1 3); do ./mvnw clean install $MAVEN_FAST_INSTALL -pl 'presto-native-tests' -am && s=0 && break || s=$? && sleep 10; done; (exit $s)
+
+ - name: Run presto-native tests
+ run: |
+ export PRESTO_SERVER_PATH="${GITHUB_WORKSPACE}/presto-native-execution/_build/release/presto_cpp/main/presto_server"
+ export TESTFILES=`find ./presto-native-tests/src/test -type f -name 'Test*.java'`
+ # Convert file paths to comma separated class names
+ export TESTCLASSES=
+ for test_file in $TESTFILES
+ do
+ tmp=${test_file##*/}
+ test_class=${tmp%%\.*}
+ export TESTCLASSES="${TESTCLASSES},$test_class"
+ done
+ export TESTCLASSES=${TESTCLASSES#,}
+ echo "TESTCLASSES = $TESTCLASSES"
+
+ mvn test \
+ ${MAVEN_TEST} \
+ -pl 'presto-native-tests' \
+ -Dtest="${TESTCLASSES}" \
+ -DPRESTO_SERVER=${PRESTO_SERVER_PATH} \
+ -DDATA_DIR=${RUNNER_TEMP} \
+ -Duser.timezone=America/Bahia_Banderas \
+ -T1C
+
prestocpp-linux-presto-sidecar-tests:
needs: prestocpp-linux-build-for-test
runs-on: ubuntu-22.04
diff --git a/.github/workflows/test-other-modules.yml b/.github/workflows/test-other-modules.yml
index afb84cfd7bf5d..fd6496390499c 100644
--- a/.github/workflows/test-other-modules.yml
+++ b/.github/workflows/test-other-modules.yml
@@ -68,6 +68,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 babee5c56cb0a..a7ac6a1613f94 100644
--- a/pom.xml
+++ b/pom.xml
@@ -203,6 +203,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-execution/src/test/java/com/facebook/presto/nativeworker/PrestoNativeQueryRunnerUtils.java b/presto-native-execution/src/test/java/com/facebook/presto/nativeworker/PrestoNativeQueryRunnerUtils.java
index 9d6569ad8bcb3..8e72dc28e4f3c 100644
--- a/presto-native-execution/src/test/java/com/facebook/presto/nativeworker/PrestoNativeQueryRunnerUtils.java
+++ b/presto-native-execution/src/test/java/com/facebook/presto/nativeworker/PrestoNativeQueryRunnerUtils.java
@@ -44,7 +44,9 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.UUID;
@@ -128,7 +130,7 @@ public static QueryRunner createQueryRunner(
defaultQueryRunner.close();
return createNativeQueryRunner(dataDirectory.get().toString(), prestoServerPath.get(), workerCount, cacheMaxSize, true, Optional.empty(),
- storageFormat, addStorageFormatToPath, false, isCoordinatorSidecarEnabled, false, enableRuntimeMetricsCollection, enableSsdCache);
+ storageFormat, addStorageFormatToPath, false, isCoordinatorSidecarEnabled, false, enableRuntimeMetricsCollection, enableSsdCache, Collections.emptyMap());
}
public static QueryRunner createJavaQueryRunner()
@@ -335,7 +337,8 @@ public static QueryRunner createNativeQueryRunner(
boolean isCoordinatorSidecarEnabled,
boolean singleNodeExecutionEnabled,
boolean enableRuntimeMetricsCollection,
- boolean enableSsdCache)
+ boolean enableSsdCache,
+ Map extraProperties)
throws Exception
{
// The property "hive.allow-drop-table" needs to be set to true because security is always "legacy" in NativeQueryRunner.
@@ -359,6 +362,7 @@ public static QueryRunner createNativeQueryRunner(
.put("experimental.internal-communication.thrift-transport-enabled", String.valueOf(useThrift))
.putAll(getNativeWorkerSystemProperties())
.putAll(isCoordinatorSidecarEnabled ? getNativeSidecarProperties() : ImmutableMap.of())
+ .putAll(extraProperties)
.build(),
coordinatorProperties.build(),
"legacy",
@@ -420,6 +424,28 @@ public static QueryRunner createNativeQueryRunner(String remoteFunctionServerUds
return createNativeQueryRunner(false, DEFAULT_STORAGE_FORMAT, Optional.ofNullable(remoteFunctionServerUds), false, false, false, false, false);
}
+ public static QueryRunner createNativeQueryRunner(Map extraProperties, String storageFormat)
+ throws Exception
+ {
+ int cacheMaxSize = 0;
+ NativeQueryRunnerParameters nativeQueryRunnerParameters = getNativeQueryRunnerParameters();
+ return createNativeQueryRunner(
+ nativeQueryRunnerParameters.dataDirectory.toString(),
+ nativeQueryRunnerParameters.serverBinary.toString(),
+ nativeQueryRunnerParameters.workerCount,
+ cacheMaxSize,
+ true,
+ Optional.empty(),
+ storageFormat,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ extraProperties);
+ }
+
public static QueryRunner createNativeQueryRunner(boolean useThrift)
throws Exception
{
@@ -464,7 +490,8 @@ public static QueryRunner createNativeQueryRunner(
isCoordinatorSidecarEnabled,
singleNodeExecutionEnabled,
enableRuntimeMetricsCollection,
- enableSSDCache);
+ enableSSDCache,
+ Collections.emptyMap());
}
// Start the remote function server. Return the UDS path used to communicate with it.
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..d412e684a162c
--- /dev/null
+++ b/presto-native-tests/pom.xml
@@ -0,0 +1,109 @@
+
+
+ 4.0.0
+
+
+ com.facebook.presto
+ presto-root
+ 0.292-SNAPSHOT
+
+
+ presto-native-tests
+ presto-native-tests
+ Presto Native Tests
+
+
+ ${project.parent.basedir}
+
+
+
+
+ org.testng
+ testng
+
+
+
+ com.facebook.presto
+ presto-main
+ ${project.version}
+ test
+
+
+
+ com.facebook.presto
+ presto-native-execution
+ ${project.version}
+ test-jar
+ test
+
+
+
+ com.facebook.presto
+ presto-tests
+ ${project.version}
+ test
+
+
+
+ com.facebook.presto
+ presto-tpcds
+ ${project.version}
+ test
+
+
+
+ com.google.guava
+ guava
+
+
+
+
+
+
+
+ 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/TestDistributedEngineOnlyQueries.java b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestDistributedEngineOnlyQueries.java
new file mode 100644
index 0000000000000..e83e4a2a6e589
--- /dev/null
+++ b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestDistributedEngineOnlyQueries.java
@@ -0,0 +1,88 @@
+/*
+ * 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.AbstractTestEngineOnlyQueries;
+import com.google.common.collect.ImmutableMap;
+import org.intellij.lang.annotations.Language;
+import org.testng.annotations.Test;
+
+import java.time.LocalDate;
+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;
+
+public class TestDistributedEngineOnlyQueries
+ extends AbstractTestEngineOnlyQueries
+{
+ private static final String timeTypeUnsupportedError = ".*Failed to parse type \\[time.*";
+
+ private static final String storageFormat = "PARQUET";
+
+ @Override
+ protected QueryRunner createQueryRunner() throws Exception
+ {
+ return PrestoNativeQueryRunnerUtils.createNativeQueryRunner(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);
+ }
+ }
+
+ /// TIME datatype is not supported in Prestissimo. See issue: https://github.com/prestodb/presto/issues/18844.
+ @Override
+ @Test
+ public void testTimeLiterals()
+ {
+ assertQueryFails("SELECT TIME '3:04:05'", timeTypeUnsupportedError);
+ assertQueryFails("SELECT TIME '3:04:05.123'", timeTypeUnsupportedError);
+ assertQueryFails("SELECT TIME '3:04:05'", timeTypeUnsupportedError);
+ assertQueryFails("SELECT TIME '0:04:05'", timeTypeUnsupportedError);
+ // TODO #7122 assertQueryFails(chicago, "SELECT TIME '3:04:05'", timeTypeUnsupportedError);
+ // TODO #7122 assertQueryFails(kathmandu, "SELECT TIME '3:04:05'", timeTypeUnsupportedError);
+
+ assertQueryFails("SELECT TIME '01:02:03.400 Z'", timeTypeUnsupportedError);
+ assertQueryFails("SELECT TIME '01:02:03.400 UTC'", timeTypeUnsupportedError);
+ assertQueryFails("SELECT TIME '3:04:05 +06:00'", timeTypeUnsupportedError);
+ assertQueryFails("SELECT TIME '3:04:05 +0507'", timeTypeUnsupportedError);
+ assertQueryFails("SELECT TIME '3:04:05 +03'", timeTypeUnsupportedError);
+ }
+
+ /// TIME datatype is not supported in Prestissimo. See issue: https://github.com/prestodb/presto/issues/18844.
+ @Override
+ @Test
+ public void testLocallyUnrepresentableTimeLiterals()
+ {
+ 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");
+ @Language("SQL") String sql = DateTimeFormatter.ofPattern("'SELECT TIME '''HH:mm:ss''").format(localTimeThatDidNotOccurOn19700101);
+ assertQueryFails(sql, timeTypeUnsupportedError);
+ }
+}
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..1f8f378e2bdcf
--- /dev/null
+++ b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestOrderByQueries.java
@@ -0,0 +1,52 @@
+/*
+ * 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 com.google.common.collect.ImmutableMap;
+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(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);
+ }
+ }
+
+ /// Queries in this testcase use the apply function, which is used to test lambda expressions, and is currently
+ /// unsupported in Presto C++. See issue: https://github.com/prestodb/presto/issues/20741.
+ @Override
+ @Test(enabled = false)
+ public void testOrderByWithOutputColumnReferenceInLambdas() {}
+}
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..2bb1125f63ca5
--- /dev/null
+++ b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestRepartitionQueries.java
@@ -0,0 +1,45 @@
+/*
+ * 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 com.google.common.collect.ImmutableMap;
+
+public class TestRepartitionQueries
+ extends AbstractTestRepartitionQueries
+{
+ private static final String storageFormat = "PARQUET";
+
+ @Override
+ protected QueryRunner createQueryRunner() throws Exception
+ {
+ return PrestoNativeQueryRunnerUtils.createNativeQueryRunner(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/TestRepartitionQueriesWithSmallPages.java b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestRepartitionQueriesWithSmallPages.java
new file mode 100644
index 0000000000000..ba48b071c58b2
--- /dev/null
+++ b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestRepartitionQueriesWithSmallPages.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.facebook.presto.tests.AbstractTestRepartitionQueries;
+import com.google.common.collect.ImmutableMap;
+
+public class TestRepartitionQueriesWithSmallPages
+ extends AbstractTestRepartitionQueries
+{
+ private static final String storageFormat = "PARQUET";
+
+ @Override
+ protected QueryRunner createQueryRunner() throws Exception
+ {
+ return PrestoNativeQueryRunnerUtils.createNativeQueryRunner(
+ // Use small SerializedPages to force flushing
+ ImmutableMap.of("driver.max-page-partitioning-buffer-size", "200B"), 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/TestWindowQueries.java b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestWindowQueries.java
new file mode 100644
index 0000000000000..634c3b5de1e89
--- /dev/null
+++ b/presto-native-tests/src/test/java/com.facebook.presto.nativetests/TestWindowQueries.java
@@ -0,0 +1,225 @@
+/*
+ * 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 com.google.common.collect.ImmutableMap;
+import org.testng.annotations.Test;
+
+public class TestWindowQueries
+ extends AbstractTestWindowQueries
+{
+ private static final String frameTypeDiffersError = ".*Window frame of type RANGE does not match types of the ORDER BY and frame column.*";
+
+ private String storageFormat = "PARQUET";
+
+ @Override
+ protected QueryRunner createQueryRunner() throws Exception
+ {
+ return PrestoNativeQueryRunnerUtils.createNativeQueryRunner(ImmutableMap.of(), storageFormat);
+ }
+
+ @Override
+ protected void createTables()
+ {
+ try {
+ QueryRunner javaQueryRunner = PrestoNativeQueryRunnerUtils.createJavaQueryRunner("PARQUET");
+ NativeQueryRunnerUtils.createAllTables(javaQueryRunner, false);
+ javaQueryRunner.close();
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /// Queries in this test fail because GROUPS mode in Window frame is not supported in Prestissimo. See issue:
+ /// https://github.com/prestodb/presto/issues/24413.
+ @Override
+ @Test(enabled = false)
+ public void testAllPartitionSameValuesGroup() {}
+
+ /// Queries in this test fail because GROUPS mode in Window frame is not supported in Prestissimo. See issue:
+ /// https://github.com/prestodb/presto/issues/24413.
+ @Override
+ @Test(enabled = false)
+ public void testConstantOffset() {}
+
+ /// Queries in this test fail because GROUPS mode in Window frame is not supported in Prestissimo. See issue:
+ /// https://github.com/prestodb/presto/issues/24413.
+ @Override
+ @Test(enabled = false)
+ public void testEmptyFrameGroup() {}
+
+ /// Queries in this test fail because GROUPS mode in Window frame is not supported in Prestissimo. See issue:
+ /// https://github.com/prestodb/presto/issues/24413.
+ @Override
+ @Test(enabled = false)
+ public void testInvalidOffsetGroup() {}
+
+ /// Queries in this test fail because GROUPS mode in Window frame is not supported in Prestissimo. See issue:
+ /// https://github.com/prestodb/presto/issues/24413.
+ @Override
+ @Test(enabled = false)
+ public void testMixedTypeFrameBounds() {}
+
+ /// Queries in this test fail because GROUPS mode in Window frame is not supported in Prestissimo. See issue:
+ /// https://github.com/prestodb/presto/issues/24413.
+ @Override
+ @Test(enabled = false)
+ public void testMultipleWindowFunctionsGroup() {}
+
+ /// Queries in this test fail because GROUPS mode in Window frame is not supported in Prestissimo. See issue:
+ /// https://github.com/prestodb/presto/issues/24413.
+ @Override
+ @Test(enabled = false)
+ public void testNonConstantOffsetGroup() {}
+
+ /// Queries in this test fail because GROUPS mode in Window frame is not supported in Prestissimo. See issue:
+ /// https://github.com/prestodb/presto/issues/24413.
+ @Override
+ @Test(enabled = false)
+ public void testNoValueFrameBoundsGroup() {}
+
+ /// Queries in this test fail because GROUPS mode in Window frame is not supported in Prestissimo. See issue:
+ /// https://github.com/prestodb/presto/issues/24413.
+ @Override
+ @Test(enabled = false)
+ public void testOnlyNullsGroup() {}
+
+ /// Queries in this test fail because GROUPS mode in Window frame is not supported in Prestissimo. See issue:
+ /// https://github.com/prestodb/presto/issues/24413.
+ @Override
+ @Test(enabled = false)
+ public void testWindowPartitioningGroup() {}
+
+ /// This test is flaky so disabled for now, see issue: https://github.com/prestodb/presto/issues/21888.
+ @Override
+ @Test
+ public void testInvalidOffset() {}
+
+ /// Queries in this test fail because the Window's ORDER BY column type differs from the frame bound type. See
+ /// issue: https://github.com/prestodb/presto/issues/23269.
+ @Override
+ @Test(enabled = false)
+ public void testEmptyFrameMixedBounds() {}
+
+ /// Queries in this test fail because the Window's ORDER BY column type differs from the frame bound type. See
+ /// issue: https://github.com/prestodb/presto/issues/23269.
+ @Override
+ @Test(enabled = false)
+ public void testMixedTypeFrameBoundsAscendingNullsFirst() {}
+
+ /// Queries in this test fail because the Window's ORDER BY column type differs from the frame bound type. See
+ /// issue: https://github.com/prestodb/presto/issues/23269.
+ @Override
+ @Test(enabled = false)
+ public void testMixedTypeFrameBoundsAscendingNullsLast() {}
+
+ /// Queries in this test fail because the Window's ORDER BY column type differs from the frame bound type. See
+ /// issue: https://github.com/prestodb/presto/issues/23269.
+ @Override
+ @Test(enabled = false)
+ public void testMixedTypeFrameBoundsDescendingNullsFirst() {}
+
+ /// Queries in this test fail because the Window's ORDER BY column type differs from the frame bound type. See
+ /// issue: https://github.com/prestodb/presto/issues/23269.
+ @Override
+ @Test(enabled = false)
+ public void testMixedTypeFrameBoundsDescendingNullsLast() {}
+
+ /// Queries in this test fail because the Window's ORDER BY column type differs from the frame bound type. See
+ /// issue: https://github.com/prestodb/presto/issues/23269.
+ @Override
+ @Test(enabled = false)
+ public void testNonConstantOffset() {}
+
+ /// Queries in this test fail because the Window's ORDER BY column type differs from the frame bound type. See
+ /// issue: https://github.com/prestodb/presto/issues/23269.
+ @Override
+ @Test(enabled = false)
+ public void testWindowPartitioning() {}
+
+ /// The last query in this test fails because the Window's ORDER BY column type differs from the frame bound type.
+ /// See issue: https://github.com/prestodb/presto/issues/23269.
+ @Override
+ @Test
+ public void testMultipleWindowFunctions()
+ {
+ assertQuery("SELECT x, array_agg(date) OVER(ORDER BY x RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING), avg(number) OVER(ORDER BY x RANGE BETWEEN 1 PRECEDING 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)",
+ "VALUES " +
+ "(1, ARRAY[DATE '1111-01-01', DATE '2222-01-01'], 3.3), " +
+ "(2, ARRAY[DATE '1111-01-01', DATE '2222-01-01', DATE '3333-01-01'], 4.4), " +
+ "(3, ARRAY[DATE '2222-01-01', DATE '3333-01-01'], 5.5)");
+
+ assertQueryFails("SELECT x, array_agg(a) OVER(ORDER BY x RANGE BETWEEN 2 PRECEDING AND CURRENT ROW), array_agg(a) OVER(ORDER BY x RANGE BETWEEN CURRENT ROW AND 2 FOLLOWING) " +
+ "FROM (VALUES " +
+ "(1.0, 1), " +
+ "(2.0, 2), " +
+ "(3.0, 3), " +
+ "(4.0, 4), " +
+ "(5.0, 5), " +
+ "(6.0, 6)) T(x, a)", frameTypeDiffersError);
+ }
+
+ /// The first query in this test fails because the Window's ORDER BY column type differs from the frame bound type.
+ /// See issue: https://github.com/prestodb/presto/issues/23269.
+ /// The last query in this test fails because `plus` arithmetic function is currently unsupported for INTERVAL YEAR
+ /// MONTH type in Velox. See PR: https://github.com/facebookincubator/velox/pull/11612.
+ @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);
+
+ assertQuery("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)",
+ "VALUES " +
+ "ARRAY[CAST('1' AS REAL), CAST('2' AS REAL)], " +
+ "ARRAY[CAST('2' AS REAL)], " +
+ "ARRAY[null]");
+
+ 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)",
+ ".*Scalar function presto.default.plus not registered with arguments.*", 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 90%
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
index c2020d8bac6a2..997afe8cabf79 100644
--- a/presto-tests/src/test/java/com/facebook/presto/tests/AbstractTestEngineOnlyQueries.java
+++ b/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestEngineOnlyQueries.java
@@ -35,7 +35,7 @@ public abstract class AbstractTestEngineOnlyQueries
extends AbstractTestQueryFramework
{
@Test
- public void testTimeLiterals()
+ public void testDateLiterals()
{
Session chicago = Session.builder(getSession()).setTimeZoneKey(TimeZoneKey.getTimeZoneKey("America/Chicago")).build();
Session kathmandu = Session.builder(getSession()).setTimeZoneKey(TimeZoneKey.getTimeZoneKey("Asia/Kathmandu")).build();
@@ -44,7 +44,11 @@ public void testTimeLiterals()
assertQuery("SELECT DATE '2013-03-22'");
assertQuery(chicago, "SELECT DATE '2013-03-22'");
assertQuery(kathmandu, "SELECT DATE '2013-03-22'");
+ }
+ @Test
+ public void testTimeLiterals()
+ {
assertEquals(computeScalar("SELECT TIME '3:04:05'"), LocalTime.of(3, 4, 5, 0));
assertEquals(computeScalar("SELECT TIME '3:04:05.123'"), LocalTime.of(3, 4, 5, 123_000_000));
assertQuery("SELECT TIME '3:04:05'");
@@ -57,7 +61,11 @@ public void testTimeLiterals()
assertEquals(computeScalar("SELECT TIME '3:04:05 +06:00'"), OffsetTime.of(3, 4, 5, 0, ZoneOffset.ofHoursMinutes(6, 0)));
assertEquals(computeScalar("SELECT TIME '3:04:05 +0507'"), OffsetTime.of(3, 4, 5, 0, ZoneOffset.ofHoursMinutes(5, 7)));
assertEquals(computeScalar("SELECT TIME '3:04:05 +03'"), OffsetTime.of(3, 4, 5, 0, ZoneOffset.ofHoursMinutes(3, 0)));
+ }
+ @Test
+ public void testTimestampLiterals()
+ {
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'");
@@ -69,27 +77,35 @@ public void testTimeLiterals()
}
@Test
- public void testLocallyUnrepresentableTimeLiterals()
+ public void testLocallyUnrepresentableDateLiterals()
{
- 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);
+ @Language("SQL") String 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
+ }
+ @Test
+ public void testLocallyUnrepresentableTimeLiterals()
+ {
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);
+ @Language("SQL") String sql = DateTimeFormatter.ofPattern("'SELECT TIME '''HH:mm:ss''").format(localTimeThatDidNotOccurOn19700101);
assertEquals(computeScalar(sql), localTimeThatDidNotOccurOn19700101); // this tests Presto and the QueryRunner
assertQuery(sql); // this tests H2QueryRunner
}
+
+ @Test
+ public void testLocallyUnrepresentableTimestampLiterals()
+ {
+ 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
+ }
}
diff --git a/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestOrderByQueries.java b/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestOrderByQueries.java
index 9e633ff52e9ee..62a086c951bfe 100644
--- a/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestOrderByQueries.java
+++ b/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestOrderByQueries.java
@@ -86,11 +86,6 @@ public void testOrderByWithOutputColumnReference()
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
- assertQueryOrdered("SELECT x AS y FROM (values (1,2), (2,3)) t(x, y) GROUP BY x ORDER BY apply(x, x -> -x) + 2*x", "VALUES 1, 2");
- assertQueryOrdered("SELECT -y AS x FROM (values (1,2), (2,3)) t(x, y) GROUP BY y ORDER BY apply(x, x -> -x)", "VALUES -2, -3");
- assertQueryOrdered("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))", "VALUES -3, -2");
-
// 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");
@@ -106,6 +101,14 @@ public void testOrderByWithOutputColumnReference()
assertQueryFails("SELECT a, a* -1 AS a FROM (VALUES -1, 0, 2) t(a) ORDER BY a", ".*'a' is ambiguous");
}
+ @Test
+ public void testOrderByWithOutputColumnReferenceInLambdas()
+ {
+ assertQueryOrdered("SELECT x AS y FROM (values (1,2), (2,3)) t(x, y) GROUP BY x ORDER BY apply(x, x -> -x) + 2*x", "VALUES 1, 2");
+ assertQueryOrdered("SELECT -y AS x FROM (values (1,2), (2,3)) t(x, y) GROUP BY y ORDER BY apply(x, x -> -x)", "VALUES -2, -3");
+ assertQueryOrdered("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))", "VALUES -3, -2");
+ }
+
@Test
public void testOrderByWithAggregation()
{
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 cdc974260c6f3..c134b2fd56027 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
@@ -316,6 +316,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);
@@ -336,6 +341,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/AbstractTestWindowQueries.java b/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestWindowQueries.java
index 14fa5afa8ebf3..1fc7d25953853 100644
--- a/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestWindowQueries.java
+++ b/presto-tests/src/main/java/com/facebook/presto/tests/AbstractTestWindowQueries.java
@@ -1016,7 +1016,7 @@ public void testEmptyInput()
}
@Test
- public void testEmptyFrame()
+ public void testEmptyFrameIntegralBounds()
{
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)",
@@ -1044,6 +1044,23 @@ public void testEmptyFrame()
"ARRAY[null, null, null, null], " +
"ARRAY[null, null, 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]");
+ }
+
+ @Test
+ public void testEmptyFrameMixedBounds()
+ {
assertQuery("SELECT array_agg(a) OVER(ORDER BY a RANGE BETWEEN 0.5 FOLLOWING AND 1.5 FOLLOWING) " +
"FROM (VALUES 1, 2, 4) T(a)",
"VALUES " +
@@ -1077,19 +1094,6 @@ public void testEmptyFrame()
"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]");
-
assertQuery("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)",
"VALUES " +
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..9a1cdbe8b7755 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;
@@ -346,7 +347,18 @@ protected static void assertQueryFails(QueryRunner queryRunner, Session session,
fail(format("Expected query to fail: %s", sql));
}
catch (RuntimeException ex) {
- assertExceptionMessage(sql, ex, expectedMessageRegExp);
+ assertExceptionMessage(sql, ex, expectedMessageRegExp, false);
+ }
+ }
+
+ 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) {
+ assertExceptionMessage(sql, ex, expectedMessageRegExp, usePatternMatcher);
}
}
@@ -362,10 +374,18 @@ protected static void assertQueryReturnsEmptyResult(QueryRunner queryRunner, Ses
}
}
- private static void assertExceptionMessage(String sql, Exception exception, @Language("RegExp") String regex)
+ private static void assertExceptionMessage(String sql, Exception exception, @Language("RegExp") String regex, boolean usePatternMatcher)
{
- if (!nullToEmpty(exception.getMessage()).matches(regex)) {
- fail(format("Expected exception message '%s' to match '%s' for query: %s", exception.getMessage(), regex, sql), exception);
+ if (usePatternMatcher) {
+ 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);
+ }
+ }
+ else {
+ if (!nullToEmpty(exception.getMessage()).matches(regex)) {
+ fail(format("Expected exception message '%s' to match '%s' for query: %s", exception.getMessage(), regex, sql), exception);
+ }
}
}