| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.drill; |
| |
| import org.apache.drill.common.exceptions.UserException; |
| import org.apache.drill.common.types.TypeProtos.MinorType; |
| import org.apache.drill.exec.physical.rowSet.RowSet; |
| import org.apache.drill.exec.physical.rowSet.RowSetBuilder; |
| import org.apache.drill.exec.planner.physical.PlannerSettings; |
| import org.apache.drill.exec.record.BatchSchema; |
| import org.apache.drill.exec.record.BatchSchemaBuilder; |
| import org.apache.drill.exec.record.metadata.SchemaBuilder; |
| import org.apache.drill.exec.record.metadata.TupleMetadata; |
| import org.apache.drill.exec.util.StoragePluginTestUtils; |
| import org.apache.drill.shaded.guava.com.google.common.collect.Lists; |
| import org.apache.commons.lang3.tuple.Pair; |
| import org.apache.drill.categories.OperatorTest; |
| import org.apache.drill.categories.SqlTest; |
| import org.apache.drill.categories.UnlikelyTest; |
| import org.apache.drill.common.expression.SchemaPath; |
| import org.apache.drill.common.types.TypeProtos; |
| import org.apache.drill.exec.ExecConstants; |
| import org.apache.drill.test.ClusterFixture; |
| import org.apache.drill.test.ClusterTest; |
| import org.apache.drill.test.rowSet.RowSetComparison; |
| import org.hamcrest.CoreMatchers; |
| import org.junit.Assert; |
| import org.junit.BeforeClass; |
| import org.junit.Test; |
| import org.junit.experimental.categories.Category; |
| |
| import java.io.BufferedWriter; |
| import java.io.File; |
| import java.io.FileWriter; |
| import java.nio.file.Paths; |
| import java.util.List; |
| |
| import static org.junit.jupiter.api.Assertions.assertEquals; |
| import static org.junit.jupiter.api.Assertions.assertTrue; |
| import static org.junit.jupiter.api.Assertions.fail; |
| |
| @Category({SqlTest.class, OperatorTest.class}) |
| public class TestSetOp extends ClusterTest { |
| private static final String EMPTY_DIR_NAME = "empty_directory"; |
| private static final String SLICE_TARGET_DEFAULT = "alter session reset `planner.slice_target`"; |
| |
| @BeforeClass |
| public static void setupTestFiles() throws Exception { |
| startCluster(ClusterFixture.builder(dirTestWatcher)); |
| dirTestWatcher.copyResourceToRoot(Paths.get("multilevel", "parquet")); |
| dirTestWatcher.makeTestTmpSubDir(Paths.get(EMPTY_DIR_NAME)); |
| |
| // A tmp workspace with a default format defined for tests that need to |
| // query empty directories without encountering an error. |
| cluster.defineWorkspace( |
| StoragePluginTestUtils.DFS_PLUGIN_NAME, |
| "tmp_default_format", |
| dirTestWatcher.getDfsTestTmpDir().getAbsolutePath(), |
| "csvh" |
| ); |
| } |
| |
| @Test |
| public void TestExceptionWithSchemaLessDataSource() { |
| String root = "/multilevel/csv/1994/Q1/orders_94_q1.csv"; |
| try { |
| testBuilder() |
| .sqlQuery("select * from cp.`%s` intersect select * from cp.`%s`", root, root) |
| .unOrdered() |
| .baselineColumns("a", "b") |
| .baselineValues(1, 1) |
| .go(); |
| Assert.fail("Missing expected exception on schema less data source"); |
| } catch (Exception ex) { |
| Assert.assertThat(ex.getMessage(), ex.getMessage(), |
| CoreMatchers.containsString("schema-less tables must specify the columns explicitly")); |
| } |
| |
| try { |
| testBuilder() |
| .sqlQuery("select * from cp.`%s` except select * from cp.`%s`", root, root) |
| .unOrdered() |
| .baselineColumns("a", "b") |
| .baselineValues(1, 1) |
| .go(); |
| Assert.fail("Missing expected exception on schema less data source"); |
| } catch (Exception ex) { |
| Assert.assertThat(ex.getMessage(), ex.getMessage(), |
| CoreMatchers.containsString("schema-less tables must specify the columns explicitly")); |
| } |
| } |
| |
| @Test |
| public void testIntersect() throws Exception { |
| String query = "select * from (values(4,4), (2,2), (4,4), (1,1), (3,4), (2,2), (1,1)) t(a,b) intersect select * from (values(1,1), (1,1), (2,2), (3,3)) t(a,b)"; |
| testBuilder() |
| .sqlQuery(query) |
| .unOrdered() |
| .baselineColumns("a", "b") |
| .baselineValues(2, 2) |
| .baselineValues(1, 1) |
| .build().run(); |
| |
| query = "select * from (values(4,4), (2,2), (4,4), (1,1), (3,4), (2,2), (1,1)) t(a,b) intersect all select * from (values(1,1), (1,1), (2,2), (3,3)) t(a,b)"; |
| testBuilder() |
| .sqlQuery(query) |
| .unOrdered() |
| .baselineColumns("a", "b") |
| .baselineValues(2, 2) |
| .baselineValues(1, 1) |
| .baselineValues(1, 1) |
| .build().run(); |
| } |
| |
| @Test |
| public void testExcept() throws Exception { |
| String query = "select * from (values(4,4), (2,2), (4,4), (1,1), (3,4), (2,2), (1,1)) t(a,b) except select * from (values(1,1), (1,1), (2,2), (3,3)) t(a,b)"; |
| String aggAbovePattern = ".*Screen.*Agg.*SetOp.*"; |
| String aggBelowPattern = ".*SetOp.*Agg.*Values.*"; |
| |
| queryBuilder() |
| .sql(query) |
| .planMatcher() |
| .include(aggAbovePattern) |
| .exclude(aggBelowPattern) |
| .match(true); |
| |
| testBuilder() |
| .sqlQuery(query) |
| .unOrdered() |
| .baselineColumns("a", "b") |
| .baselineValues(4, 4) |
| .baselineValues(3, 4) |
| .build().run(); |
| |
| try { |
| client.alterSession(ExecConstants.EXCEPT_ADD_AGG_BELOW_KEY, true); |
| query = "select * from (values(4,4), (2,2), (4,4), (1,1), (3,4), (2,2), (1,1)) t(a,b) except select a, b from (values(1,1), (1,1), (2,2), (3,3)) t(a,b)"; |
| queryBuilder() |
| .sql(query) |
| .planMatcher() |
| .include(aggBelowPattern) |
| .exclude(aggAbovePattern) |
| .match(true); |
| |
| testBuilder() |
| .sqlQuery(query) |
| .unOrdered() |
| .baselineColumns("a", "b") |
| .baselineValues(4, 4) |
| .baselineValues(3, 4) |
| .build().run(); |
| } finally { |
| client.resetSession(ExecConstants.EXCEPT_ADD_AGG_BELOW_KEY); |
| } |
| |
| query = "select * from (values(4,4), (2,2), (4,4), (1,1), (3,4), (2,2), (1,1)) t(a,b) except all select * from (values(1,1), (1,1), (2,2), (3,3)) t(a,b)"; |
| testBuilder() |
| .sqlQuery(query) |
| .unOrdered() |
| .baselineColumns("a", "b") |
| .baselineValues(4, 4) |
| .baselineValues(4, 4) |
| .baselineValues(3, 4) |
| .baselineValues(2, 2) |
| .build().run(); |
| } |
| |
| |
| @Test |
| public void testOverJoin() throws Exception { |
| String query = |
| "select n1.n_nationkey from cp.`tpch/nation.parquet` n1 inner join cp.`tpch/region.parquet` r1 on n1.n_regionkey = r1.r_regionkey where n1.n_nationkey in (1, 2, 3, 4) " + |
| "except " + |
| "select n2.n_nationkey from cp.`tpch/nation.parquet` n2 inner join cp.`tpch/region.parquet` r2 on n2.n_regionkey = r2.r_regionkey where n2.n_nationkey in (3, 4)"; |
| |
| testBuilder() |
| .sqlQuery(query) |
| .unOrdered() |
| .baselineColumns("n_nationkey") |
| .baselineValues(1) |
| .baselineValues(2) |
| .build().run(); |
| } |
| |
| @Test |
| public void testExceptOverAgg() throws Exception { |
| String query = "select n1.n_regionkey from cp.`tpch/nation.parquet` n1 group by n1.n_regionkey except " + |
| "select r1.r_regionkey from cp.`tpch/region.parquet` r1 where r1.r_regionkey in (0, 1) group by r1.r_regionkey"; |
| |
| String excludePattern = "Screen.*Agg.*SetOp"; |
| queryBuilder() |
| .sql(query) |
| .planMatcher() |
| .exclude(excludePattern) |
| .match(true); |
| |
| testBuilder() |
| .sqlQuery(query) |
| .unOrdered() |
| .baselineColumns("n_regionkey") |
| .baselineValues(2) |
| .baselineValues(3) |
| .baselineValues(4) |
| .build().run(); |
| } |
| |
| @Test |
| public void testChain() throws Exception { |
| String query = "select n_regionkey from cp.`tpch/nation.parquet` intersect " + |
| "select r_regionkey from cp.`tpch/region.parquet` intersect " + |
| "select n_nationkey from cp.`tpch/nation.parquet` where n_nationkey in (1,2) intersect " + |
| "select c_custkey from cp.`tpch/customer.parquet` where c_custkey < 5"; |
| |
| testBuilder() |
| .sqlQuery(query) |
| .unOrdered() |
| .baselineColumns("n_regionkey") |
| .baselineValues(1) |
| .baselineValues(2) |
| .build().run(); |
| } |
| |
| @Test |
| public void testSameColumn() throws Exception { |
| String query = "select n_nationkey, n_regionkey from cp.`tpch/nation.parquet` where n_regionkey = 1 intersect all select r_regionkey, r_regionkey from cp.`tpch/region.parquet` where r_regionkey = 1"; |
| testBuilder() |
| .sqlQuery(query) |
| .unOrdered() |
| .baselineColumns("n_nationkey", "n_regionkey") |
| .baselineValues(1, 1) |
| .build().run(); |
| |
| query = "select n_regionkey, n_regionkey from cp.`tpch/nation.parquet` where n_regionkey = 1 except all select r_regionkey, r_regionkey from cp.`tpch/region.parquet` where r_regionkey = 1"; |
| testBuilder() |
| .sqlQuery(query) |
| .unOrdered() |
| .baselineColumns("n_regionkey", "n_regionkey0") |
| .baselineValues(1, 1) |
| .baselineValues(1, 1) |
| .baselineValues(1, 1) |
| .baselineValues(1, 1) |
| .build().run(); |
| } |
| |
| @Test |
| public void testTwoStringColumns() throws Exception { |
| String query = "select r_comment, r_regionkey from cp.`tpch/region.parquet` except select n_name, n_nationkey from cp.`tpch/nation.parquet`"; |
| |
| testBuilder() |
| .sqlQuery(query) |
| .unOrdered() |
| .baselineColumns("r_comment", "r_regionkey") |
| .baselineValues("lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to ", 0) |
| .baselineValues("hs use ironic, even requests. s", 1) |
| .baselineValues("ges. thinly even pinto beans ca", 2) |
| .baselineValues("ly final courts cajole furiously final excuse", 3) |
| .baselineValues("uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl", 4) |
| .build().run(); |
| } |
| |
| |
| @Test |
| public void testConstantLiterals() throws Exception { |
| String query = "(select 'CONST' as LiteralConstant, 1 as NumberConstant, n_nationkey from cp.`tpch/nation.parquet`) " + |
| "intersect " + |
| "(select 'CONST', 1, r_regionkey from cp.`tpch/region.parquet`)"; |
| |
| testBuilder() |
| .sqlQuery(query) |
| .unOrdered() |
| .baselineColumns("LiteralConstant", "NumberConstant", "n_nationkey") |
| .baselineValues("CONST", 1, 0) |
| .baselineValues("CONST", 1, 1) |
| .baselineValues("CONST", 1, 2) |
| .baselineValues("CONST", 1, 3) |
| .baselineValues("CONST", 1, 4) |
| .build().run(); |
| } |
| |
| @Test |
| @Category(UnlikelyTest.class) |
| public void testViewExpandableStar() throws Exception { |
| try { |
| run("use dfs.tmp"); |
| run("create view nation_view as select n_nationkey, n_name from (values(4,'4'), (2,'2'), (4,'4'), (1,'1'), (3,'4'), (2,'2'), (1,'1')) t(n_nationkey, n_name)"); |
| run("create view region_view as select r_regionkey, r_name from (values(1,'1'), (1,'1'), (2,'2'), (3,'3')) t(r_regionkey, r_name)"); |
| |
| String query1 = "(select * from dfs.tmp.`nation_view`) " + |
| "except " + |
| "(select * from dfs.tmp.`region_view`) "; |
| |
| String query2 = "(select r_regionkey, r_name from (values(1,'1'), (1,'1'), (2,'2'), (3,'3')) t(r_regionkey, r_name)) " + |
| "intersect " + |
| "(select * from dfs.tmp.`nation_view`)"; |
| |
| testBuilder() |
| .sqlQuery(query1) |
| .unOrdered() |
| .baselineColumns("n_nationkey", "n_name") |
| .baselineValues(4, "4") |
| .baselineValues(3, "4") |
| .build().run(); |
| |
| testBuilder() |
| .sqlQuery(query2) |
| .unOrdered() |
| .baselineColumns("r_regionkey", "r_name") |
| .baselineValues(1, "1") |
| .baselineValues(2, "2") |
| .build().run(); |
| } finally { |
| run("drop view if exists nation_view"); |
| run("drop view if exists region_view"); |
| } |
| } |
| |
| @Test |
| public void testDiffDataTypesAndModes() throws Exception { |
| try { |
| run("use dfs.tmp"); |
| run("create view nation_view as select n_nationkey, n_name from (values(4,'4'), (2,'2'), (4,'4'), (1,'1'), (3,'4'), (2,'2'), (1,'1')) t(n_nationkey, n_name)"); |
| run("create view region_view as select r_regionkey, r_name from (values(1,'1'), (1,'1'), (2,'2'), (3,'3')) t(r_regionkey, r_name)"); |
| |
| |
| String t1 = "(select r_regionkey, r_name from (values(1,'1'), (1,'1'), (2,'2'), (3,'3')) t(r_regionkey, r_name))"; |
| String t2 = "(select * from nation_view)"; |
| String t3 = "(select * from region_view)"; |
| String t4 = "(select store_id, full_name from cp.`employee.json` limit 5)"; |
| |
| String query1 = t1 + " intersect all " + t2 + " intersect all " + t3 + " except all " + t4; |
| |
| testBuilder() |
| .sqlQuery(query1) |
| .unOrdered() |
| .baselineColumns("r_regionkey", "r_name") |
| .baselineValues(1, "1") |
| .baselineValues(1, "1") |
| .baselineValues(2, "2") |
| .build().run(); |
| } finally { |
| run("drop view if exists nation_view"); |
| run("drop view if exists region_view"); |
| } |
| } |
| |
| @Test |
| @Category(UnlikelyTest.class) |
| public void testDistinctOverIntersectAllWithFullyQualifiedColumnNames() throws Exception { |
| String query = "select distinct sq.x1 " + |
| "from " + |
| "((select n_regionkey as a1 from cp.`tpch/nation.parquet`) " + |
| "intersect all " + |
| "(select r_regionkey as a2 from cp.`tpch/region.parquet`)) as sq(x1)"; |
| |
| testBuilder() |
| .sqlQuery(query) |
| .unOrdered() |
| .baselineColumns("x1") |
| .baselineValues(0) |
| .baselineValues(1) |
| .baselineValues(2) |
| .baselineValues(3) |
| .baselineValues(4) |
| .build().run(); |
| } |
| |
| @Test |
| @Category(UnlikelyTest.class) |
| public void testContainsColumnAndNumericConstant() throws Exception { |
| String query = "(select n_nationkey, n_regionkey, n_name from cp.`tpch/nation.parquet`) " + |
| "intersect " + |
| "(select 1, n_regionkey, 'ARGENTINA' from cp.`tpch/nation.parquet`)"; |
| |
| testBuilder() |
| .sqlQuery(query) |
| .unOrdered() |
| .baselineColumns("n_nationkey", "n_regionkey", "n_name") |
| .baselineValues(1, 1, "ARGENTINA") |
| .build().run(); |
| } |
| |
| @Test |
| @Category(UnlikelyTest.class) |
| public void testEmptySides() throws Exception { |
| String query1 = "(select n_nationkey, n_regionkey, n_name from cp.`tpch/nation.parquet` limit 0) " + |
| "intersect " + |
| "(select 1, n_regionkey, 'ARGENTINA' from cp.`tpch/nation.parquet`)"; |
| |
| String query2 = "(select n_nationkey, n_regionkey, n_name from cp.`tpch/nation.parquet` where n_nationkey = 1) " + |
| "except " + |
| "(select 1, n_regionkey, 'ARGENTINA' from cp.`tpch/nation.parquet` limit 0)"; |
| |
| testBuilder() |
| .sqlQuery(query1) |
| .unOrdered() |
| .baselineColumns("n_nationkey", "n_regionkey", "n_name") |
| .expectsEmptyResultSet() |
| .build().run(); |
| |
| testBuilder() |
| .sqlQuery(query2) |
| .unOrdered() |
| .baselineColumns("n_nationkey", "n_regionkey", "n_name") |
| .baselineValues(1, 1, "ARGENTINA") |
| .build().run(); |
| } |
| |
| @Test |
| @Category(UnlikelyTest.class) |
| public void testAggregationOnIntersectOperator() throws Exception { |
| String root = "/store/text/data/t.json"; |
| |
| testBuilder() |
| .sqlQuery("(select calc1, max(b1) as `max`, min(b1) as `min`, count(c1) as `count` " + |
| "from (select a1 + 10 as calc1, b1, c1 from cp.`%s` " + |
| "intersect all select a1 + 10 as diff1, b1 as diff2, c1 as diff3 from cp.`%s`) " + |
| "group by calc1 order by calc1)", root, root) |
| .ordered() |
| .baselineColumns("calc1", "max", "min", "count") |
| .baselineValues(10L, 2L, 1L, 5L) |
| .baselineValues(20L, 5L, 3L, 5L) |
| .build().run(); |
| |
| testBuilder() |
| .sqlQuery("(select calc1, min(b1) as `min`, max(b1) as `max`, count(c1) as `count` " + |
| "from (select a1 + 10 as calc1, b1, c1 from cp.`%s` " + |
| "intersect all select a1 + 10 as diff1, b1 as diff2, c1 as diff3 from cp.`%s`) " + |
| "group by calc1 order by calc1)", root, root) |
| .ordered() |
| .baselineColumns("calc1", "min", "max", "count") |
| .baselineValues(10L, 1L, 2L, 5L) |
| .baselineValues(20L, 3L, 5L, 5L) |
| .build().run(); |
| } |
| @Test |
| public void testImplicitCastingOnJoin() throws Exception { |
| client.alterSession(ExecConstants.IMPLICIT_CAST_FOR_JOINS_ENABLED, true); |
| String rootInt = "/store/json/intData.json"; |
| String rootBoolean = "/store/json/booleanData.json"; |
| String stringsAsInts = "/store/json/intDataAsString.json"; |
| |
| RowSet result = client.queryBuilder() |
| .sql("(select key from cp.`%s` " + |
| "intersect all " + |
| "select key from cp.`%s` )", rootInt, rootBoolean) |
| .rowSet(); |
| |
| assertEquals(0, result.rowCount()); |
| result.clear(); |
| |
| result = client.queryBuilder() |
| .sql("(select key from cp.`%s` " + |
| "intersect all " + |
| "select key from cp.`%s` )", rootInt, stringsAsInts) |
| .rowSet(); |
| TupleMetadata expectedSchema = new SchemaBuilder() |
| .addNullable("key", MinorType.BIGINT) |
| .buildSchema(); |
| |
| RowSet expected = new RowSetBuilder(client.allocator(), expectedSchema) |
| .addRow(52459253098448904L) |
| .addRow(1116675951L) |
| .build(); |
| |
| new RowSetComparison(expected).verifyAndClearAll(result); |
| } |
| |
| @Test |
| public void testImplicitCastingOnJoinDisabled() throws Exception { |
| String rootInt = "/store/json/intData.json"; |
| String stringsAsInts = "/store/json/intDataAsString.json"; |
| |
| try { |
| client.queryBuilder() |
| .sql("(select key from cp.`%s` " + |
| "intersect all " + |
| "select key from cp.`%s` )", rootInt, stringsAsInts) |
| .run(); |
| fail(); |
| } catch (UserException e) { |
| assertTrue(e.getMessage().contains("Join only supports implicit casts")); |
| } |
| } |
| |
| @Test |
| @Category(UnlikelyTest.class) |
| public void testDateAndTimestampJson() throws Exception { |
| String rootDate = "/store/json/dateData.json"; |
| String rootTimpStmp = "/store/json/timeStmpData.json"; |
| |
| testBuilder() |
| .sqlQuery("(select max(key) as key from cp.`%s` " + |
| "except all select key from cp.`%s`)", rootDate, rootTimpStmp) |
| .unOrdered() |
| .baselineColumns("key") |
| .baselineValues("2011-07-26") |
| .build().run(); |
| |
| testBuilder() |
| .sqlQuery("select key from cp.`%s` " + |
| "except select max(key) as key from cp.`%s`", rootTimpStmp, rootDate) |
| .unOrdered() |
| .baselineColumns("key") |
| .baselineValues("2015-03-26 19:04:55.542") |
| .baselineValues("2015-03-26 19:04:55.543") |
| .baselineValues("2015-03-26 19:04:55.544") |
| .build().run(); |
| } |
| |
| @Test |
| @Category(UnlikelyTest.class) |
| public void testOneInputContainsAggFunction() throws Exception { |
| String root = "/multilevel/csv/1994/Q1/orders_94_q1.csv"; |
| |
| testBuilder() |
| .sqlQuery("select * from ((select max(c1) as ct from (select columns[0] c1 from cp.`%s`)) \n" + |
| "intersect all (select columns[0] c2 from cp.`%s`)) order by ct limit 3", root, root) |
| .ordered() |
| .baselineColumns("ct") |
| .baselineValues("99") |
| .build().run(); |
| |
| testBuilder() |
| .sqlQuery("select * from ((select columns[0] ct from cp.`%s`)\n" + |
| "intersect all (select max(c1) as c2 from (select columns[0] c1 from cp.`%s`))) order by ct limit 3", root, root) |
| .ordered() |
| .baselineColumns("ct") |
| .baselineValues("99") |
| .build().run(); |
| |
| testBuilder() |
| .sqlQuery("select * from ((select max(c1) as ct from (select columns[0] c1 from cp.`%s`))\n" + |
| "intersect all (select max(c1) as c2 from (select columns[0] c1 from cp.`%s`))) order by ct", root, root) |
| .ordered() |
| .baselineColumns("ct") |
| .baselineValues("99") |
| .build().run(); |
| } |
| |
| @Test |
| @Category(UnlikelyTest.class) |
| public void testInputsGroupByOnCSV() throws Exception { |
| String root = "/multilevel/csv/1994/Q1/orders_94_q1.csv"; |
| |
| testBuilder() |
| .sqlQuery("select * from \n" + |
| "((select columns[0] as col0 from cp.`%s` t1 \n" + |
| "where t1.columns[0] = 66) \n" + |
| "intersect all \n" + |
| "(select columns[0] c2 from cp.`%s` t2 \n" + |
| "where t2.columns[0] is not null \n" + |
| "group by columns[0])) \n" + |
| "group by col0", |
| root, root) |
| .unOrdered() |
| .baselineColumns("col0") |
| .baselineValues("66") |
| .build().run(); |
| } |
| |
| @Test |
| @Category(UnlikelyTest.class) |
| public void testDiffTypesAtPlanning() throws Exception { |
| testBuilder() |
| .sqlQuery("select count(c1) as ct from (select cast(r_regionkey as int) c1 from cp.`tpch/region.parquet`) " + |
| "intersect (select cast(r_regionkey as int) + 1 c2 from cp.`tpch/region.parquet`)") |
| .ordered() |
| .baselineColumns("ct") |
| .baselineValues((long) 5) |
| .build().run(); |
| } |
| |
| @Test |
| @Category(UnlikelyTest.class) |
| public void testRightEmptyJson() throws Exception { |
| String rootEmpty = "/project/pushdown/empty.json"; |
| String rootSimple = "/store/json/booleanData.json"; |
| |
| testBuilder() |
| .sqlQuery("select key from cp.`%s` " + |
| "intersect all " + |
| "select key from cp.`%s`", |
| rootSimple, |
| rootEmpty) |
| .unOrdered() |
| .baselineColumns("key") |
| .expectsEmptyResultSet() |
| .build().run(); |
| |
| testBuilder() |
| .sqlQuery("select key from cp.`%s` " + |
| "except all " + |
| "select key from cp.`%s`", |
| rootSimple, |
| rootEmpty) |
| .unOrdered() |
| .baselineColumns("key") |
| .baselineValues(true) |
| .baselineValues(false) |
| .build().run(); |
| } |
| |
| @Test |
| public void testLeftEmptyJson() throws Exception { |
| final String rootEmpty = "/project/pushdown/empty.json"; |
| final String rootSimple = "/store/json/booleanData.json"; |
| |
| testBuilder() |
| .sqlQuery("select key from cp.`%s` " + |
| "intersect all " + |
| "select key from cp.`%s`", |
| rootEmpty, |
| rootSimple) |
| .unOrdered() |
| .baselineColumns("key") |
| .expectsEmptyResultSet() |
| .build().run(); |
| |
| testBuilder() |
| .sqlQuery("select key from cp.`%s` " + |
| "except all " + |
| "select key from cp.`%s`", |
| rootEmpty, |
| rootSimple) |
| .unOrdered() |
| .baselineColumns("key") |
| .expectsEmptyResultSet() |
| .build().run(); |
| } |
| |
| @Test |
| public void testBothEmptyJson() throws Exception { |
| final String rootEmpty = "/project/pushdown/empty.json"; |
| |
| final List<Pair<SchemaPath, TypeProtos.MajorType>> expectedSchema = Lists.newArrayList(); |
| final TypeProtos.MajorType majorType = TypeProtos.MajorType.newBuilder() |
| .setMinorType(TypeProtos.MinorType.INT) |
| .setMode(TypeProtos.DataMode.OPTIONAL) |
| .build(); |
| expectedSchema.add(Pair.of(SchemaPath.getSimplePath("key"), majorType)); |
| |
| testBuilder() |
| .sqlQuery("select key from cp.`%s` " + |
| "intersect all " + |
| "select key from cp.`%s`", |
| rootEmpty, |
| rootEmpty) |
| .schemaBaseLine(expectedSchema) |
| .build() |
| .run(); |
| } |
| |
| @Test |
| public void testRightEmptyDataBatch() throws Exception { |
| String rootSimple = "/store/json/booleanData.json"; |
| |
| testBuilder() |
| .sqlQuery("select key from cp.`%s` " + |
| "except all " + |
| "select key from cp.`%s` where 1 = 0", |
| rootSimple, |
| rootSimple) |
| .unOrdered() |
| .baselineColumns("key") |
| .baselineValues(true) |
| .baselineValues(false) |
| .build().run(); |
| } |
| |
| @Test |
| public void testLeftEmptyDataBatch() throws Exception { |
| String rootSimple = "/store/json/booleanData.json"; |
| |
| testBuilder() |
| .sqlQuery("select key from cp.`%s` where 1 = 0 " + |
| "except all " + |
| "select key from cp.`%s`", |
| rootSimple, |
| rootSimple) |
| .unOrdered() |
| .baselineColumns("key") |
| .expectsEmptyResultSet() |
| .build() |
| .run(); |
| } |
| |
| @Test |
| public void testBothEmptyDataBatch() throws Exception { |
| String rootSimple = "/store/json/booleanData.json"; |
| |
| final List<Pair<SchemaPath, TypeProtos.MajorType>> expectedSchema = Lists.newArrayList(); |
| final TypeProtos.MajorType majorType = TypeProtos.MajorType.newBuilder() |
| .setMinorType(TypeProtos.MinorType.BIT) // field "key" is boolean type |
| .setMode(TypeProtos.DataMode.OPTIONAL) |
| .build(); |
| expectedSchema.add(Pair.of(SchemaPath.getSimplePath("key"), majorType)); |
| |
| testBuilder() |
| .sqlQuery("select key from cp.`%s` where 1 = 0 " + |
| "intersect all " + |
| "select key from cp.`%s` where 1 = 0", |
| rootSimple, |
| rootSimple) |
| .schemaBaseLine(expectedSchema) |
| .build() |
| .run(); |
| } |
| |
| @Test |
| @Category(UnlikelyTest.class) |
| public void testInListOnIntersect() throws Exception { |
| String query = "select n_nationkey \n" + |
| "from (select n1.n_nationkey from cp.`tpch/nation.parquet` n1 inner join cp.`tpch/region.parquet` r1 on n1.n_regionkey = r1.r_regionkey \n" + |
| "intersect \n" + |
| "select n2.n_nationkey from cp.`tpch/nation.parquet` n2 inner join cp.`tpch/region.parquet` r2 on n2.n_regionkey = r2.r_regionkey) \n" + |
| "where n_nationkey in (1, 2)"; |
| |
| // Validate the plan |
| final String[] expectedPlan = {"Project.*\n" + |
| ".*SetOp\\(all=\\[false\\], kind=\\[INTERSECT\\]\\).*\n" + |
| ".*Project.*\n" + |
| ".*HashJoin.*\n" + |
| ".*SelectionVectorRemover.*\n" + |
| ".*Filter.*\n" + |
| ".*Scan.*columns=\\[`n_regionkey`, `n_nationkey`\\].*\n" + |
| ".*Scan.*columns=\\[`r_regionkey`\\].*\n" + |
| ".*Project.*\n" + |
| ".*HashJoin.*\n" + |
| ".*SelectionVectorRemover.*\n" + |
| ".*Filter.*\n" + |
| ".*Scan.*columns=\\[`n_regionkey`, `n_nationkey`\\].*\n" + |
| ".*Scan.*columns=\\[`r_regionkey`\\].*"}; |
| queryBuilder() |
| .sql(query) |
| .planMatcher() |
| .include(expectedPlan) |
| .match(); |
| |
| // Validate the result |
| testBuilder() |
| .sqlQuery(query) |
| .ordered() |
| .baselineColumns("n_nationkey") |
| .baselineValues(1) |
| .baselineValues(2) |
| .build() |
| .run(); |
| } |
| |
| @Test |
| @Category(UnlikelyTest.class) |
| public void testIntersectWith() throws Exception { |
| final String query1 = "WITH year_total \n" + |
| " AS (SELECT c.r_regionkey customer_id,\n" + |
| " 1 year_total\n" + |
| " FROM cp.`tpch/region.parquet` c\n" + |
| " Intersect ALL \n" + |
| " SELECT c.r_regionkey customer_id, \n" + |
| " 1 year_total\n" + |
| " FROM cp.`tpch/region.parquet` c) \n" + |
| "SELECT count(t_s_secyear.customer_id) as ct \n" + |
| "FROM year_total t_s_firstyear, \n" + |
| " year_total t_s_secyear, \n" + |
| " year_total t_w_firstyear, \n" + |
| " year_total t_w_secyear \n" + |
| "WHERE t_s_secyear.customer_id = t_s_firstyear.customer_id \n" + |
| " AND t_s_firstyear.customer_id = t_w_secyear.customer_id \n" + |
| " AND t_s_firstyear.customer_id = t_w_firstyear.customer_id \n" + |
| " AND CASE \n" + |
| " WHEN t_w_firstyear.year_total > 0 THEN t_w_secyear.year_total \n" + |
| " ELSE NULL \n" + |
| " END > -1"; |
| |
| final String query2 = "WITH year_total \n" + |
| " AS (SELECT c.r_regionkey customer_id,\n" + |
| " 1 year_total\n" + |
| " FROM cp.`tpch/region.parquet` c\n" + |
| " Intersect ALL \n" + |
| " SELECT c.r_regionkey customer_id, \n" + |
| " 1 year_total\n" + |
| " FROM cp.`tpch/region.parquet` c) \n" + |
| "SELECT count(t_w_firstyear.customer_id) as ct \n" + |
| "FROM year_total t_w_firstyear, \n" + |
| " year_total t_w_secyear \n" + |
| "WHERE t_w_firstyear.year_total = t_w_secyear.year_total \n" + |
| " AND t_w_firstyear.year_total > 0 and t_w_secyear.year_total > 0"; |
| |
| final String query3 = "WITH year_total_1\n" + |
| " AS (SELECT c.r_regionkey customer_id,\n" + |
| " 1 year_total\n" + |
| " FROM cp.`tpch/region.parquet` c\n" + |
| " Intersect ALL \n" + |
| " SELECT c.r_regionkey customer_id, \n" + |
| " 1 year_total\n" + |
| " FROM cp.`tpch/region.parquet` c) \n" + |
| " , year_total_2\n" + |
| " AS (SELECT c.n_nationkey customer_id,\n" + |
| " 1 year_total\n" + |
| " FROM cp.`tpch/nation.parquet` c\n" + |
| " Intersect ALL \n" + |
| " SELECT c.n_nationkey customer_id, \n" + |
| " 1 year_total\n" + |
| " FROM cp.`tpch/nation.parquet` c) \n" + |
| " SELECT count(t_w_firstyear.customer_id) as ct\n" + |
| " FROM year_total_1 t_w_firstyear,\n" + |
| " year_total_2 t_w_secyear\n" + |
| " WHERE t_w_firstyear.year_total = t_w_secyear.year_total\n" + |
| " AND t_w_firstyear.year_total > 0 and t_w_secyear.year_total > 0"; |
| |
| final String query4 = "WITH year_total_1\n" + |
| " AS (SELECT c.n_regionkey customer_id,\n" + |
| " 1 year_total\n" + |
| " FROM cp.`tpch/nation.parquet` c\n" + |
| " Intersect ALL \n" + |
| " SELECT c.r_regionkey customer_id, \n" + |
| " 1 year_total\n" + |
| " FROM cp.`tpch/region.parquet` c), \n" + |
| " year_total_2\n" + |
| " AS (SELECT c.n_regionkey customer_id,\n" + |
| " 1 year_total\n" + |
| " FROM cp.`tpch/nation.parquet` c\n" + |
| " Intersect ALL \n" + |
| " SELECT c.r_regionkey customer_id, \n" + |
| " 1 year_total\n" + |
| " FROM cp.`tpch/region.parquet` c) \n" + |
| " SELECT count(t_w_firstyear.customer_id) as ct \n" + |
| " FROM year_total_1 t_w_firstyear,\n" + |
| " year_total_2 t_w_secyear\n" + |
| " WHERE t_w_firstyear.year_total = t_w_secyear.year_total\n" + |
| " AND t_w_firstyear.year_total > 0 and t_w_secyear.year_total > 0"; |
| |
| testBuilder() |
| .sqlQuery(query1) |
| .ordered() |
| .baselineColumns("ct") |
| .baselineValues((long) 5) |
| .build() |
| .run(); |
| |
| testBuilder() |
| .sqlQuery(query2) |
| .ordered() |
| .baselineColumns("ct") |
| .baselineValues((long) 25) |
| .build() |
| .run(); |
| |
| testBuilder() |
| .sqlQuery(query3) |
| .ordered() |
| .baselineColumns("ct") |
| .baselineValues((long) 125) |
| .build() |
| .run(); |
| |
| testBuilder() |
| .sqlQuery(query4) |
| .ordered() |
| .baselineColumns("ct") |
| .baselineValues((long) 25) |
| .build() |
| .run(); |
| } |
| |
| @Test |
| @Category(UnlikelyTest.class) |
| public void testFragmentNum() throws Exception { |
| final String l = "/multilevel/parquet/1994"; |
| final String r = "/multilevel/parquet/1995"; |
| |
| final String query = String.format("SELECT o_custkey FROM dfs.`%s` \n" + |
| "Except All SELECT o_custkey FROM dfs.`%s`", l, r); |
| |
| // Validate the plan |
| final String[] expectedPlan = {"UnionExchange.*\n", |
| ".*SetOp"}; |
| |
| try { |
| client.alterSession(ExecConstants.SLICE_TARGET, 1); |
| queryBuilder() |
| .sql(query) |
| .planMatcher() |
| .include(expectedPlan) |
| .match(); |
| |
| testBuilder() |
| .optionSettingQueriesForBaseline(SLICE_TARGET_DEFAULT) |
| .unOrdered() |
| .sqlQuery(query) |
| .sqlBaselineQuery(query) |
| .build() |
| .run(); |
| } finally { |
| client.resetSession(ExecConstants.SLICE_TARGET); |
| } |
| } |
| |
| @Test |
| public void testGroupByOnSetOp() throws Exception { |
| final String l = "/multilevel/parquet/1994"; |
| final String r = "/multilevel/parquet/1995"; |
| |
| final String query = String.format("Select o_custkey, count(*) as cnt from \n" + |
| " (SELECT o_custkey FROM dfs.`%s` \n" + |
| "Intersect All SELECT o_custkey FROM dfs.`%s`) \n" + |
| "group by o_custkey", l, r); |
| |
| // Validate the plan |
| final String[] expectedPlan = {"(?s)UnionExchange.*StreamAgg.*Sort.*SetOp.*"}; |
| |
| try { |
| client.alterSession(ExecConstants.SLICE_TARGET, 1); |
| queryBuilder() |
| .sql(query) |
| .planMatcher() |
| .include(expectedPlan) |
| .match(); |
| |
| testBuilder() |
| .optionSettingQueriesForBaseline(SLICE_TARGET_DEFAULT) |
| .unOrdered() |
| .sqlQuery(query) |
| .sqlBaselineQuery(query) |
| .build() |
| .run(); |
| } finally { |
| client.resetSession(ExecConstants.SLICE_TARGET); |
| } |
| } |
| |
| @Test |
| public void testSetOpOnHashJoin() throws Exception { |
| final String l = "/multilevel/parquet/1994"; |
| final String r = "/multilevel/parquet/1995"; |
| |
| final String query = String.format("SELECT o_custkey FROM \n" + |
| " (select o1.o_custkey from dfs.`%s` o1 inner join dfs.`%s` o2 on o1.o_orderkey = o2.o_custkey) \n" + |
| " Intersect All SELECT o_custkey FROM dfs.`%s` where o_custkey > 10", l, r, l); |
| |
| // Validate the plan |
| final String[] expectedPlan = {"(?s)UnionExchange.*SetOp.*HashJoin.*"}; |
| |
| try { |
| client.alterSession(ExecConstants.SLICE_TARGET, 1); |
| queryBuilder() |
| .sql(query) |
| .planMatcher() |
| .include(expectedPlan) |
| .match(); |
| |
| testBuilder() |
| .optionSettingQueriesForBaseline(SLICE_TARGET_DEFAULT) |
| .unOrdered() |
| .sqlQuery(query) |
| .sqlBaselineQuery(query) |
| .build() |
| .run(); |
| } finally { |
| client.resetSession(ExecConstants.SLICE_TARGET); |
| } |
| } |
| |
| @Test |
| @Category(UnlikelyTest.class) |
| public void testLimitOneOnRightSide() throws Exception { |
| final String l = "/multilevel/parquet/1994"; |
| final String r = "/multilevel/parquet/1995"; |
| |
| final String query = String.format("SELECT o_custkey FROM \n" + |
| " ((select o1.o_custkey from dfs.`%s` o1 inner join dfs.`%s` o2 on o1.o_orderkey = o2.o_custkey) \n" + |
| " Intersect All (SELECT o_custkey FROM dfs.`%s` limit 1))", l, r, l); |
| |
| // Validate the plan |
| final String[] expectedPlan = {"(?s)UnionExchange.*SetOp.*HashJoin.*"}; |
| |
| try { |
| client.alterSession(ExecConstants.SLICE_TARGET, 1); |
| client.alterSession(PlannerSettings.UNIONALL_DISTRIBUTE_KEY, true); |
| queryBuilder() |
| .sql(query) |
| .planMatcher() |
| .include(expectedPlan) |
| .match(); |
| |
| testBuilder() |
| .optionSettingQueriesForBaseline(SLICE_TARGET_DEFAULT) |
| .unOrdered() |
| .sqlQuery(query) |
| .sqlBaselineQuery(query) |
| .build() |
| .run(); |
| } finally { |
| client.resetSession(ExecConstants.SLICE_TARGET); |
| client.resetSession(PlannerSettings.UNIONALL_DISTRIBUTE_KEY); |
| } |
| } |
| |
| @Test |
| @Category(UnlikelyTest.class) |
| public void testLimitOneOnLeftSide() throws Exception { |
| final String l = "/multilevel/parquet/1994"; |
| final String r = "/multilevel/parquet/1995"; |
| |
| final String query = String.format("SELECT o_custkey FROM \n" + |
| " ((SELECT o_custkey FROM dfs.`%s` limit 1) \n" + |
| " intersect all \n" + |
| " (select o1.o_custkey from dfs.`%s` o1 inner join dfs.`%s` o2 on o1.o_orderkey = o2.o_custkey))", l, r, l); |
| |
| // Validate the plan |
| final String[] expectedPlan = {"(?s)SetOp.*BroadcastExchange.*HashJoin.*"}; |
| |
| try { |
| client.alterSession(ExecConstants.SLICE_TARGET, 1); |
| client.alterSession(PlannerSettings.UNIONALL_DISTRIBUTE_KEY, true); |
| queryBuilder() |
| .sql(query) |
| .planMatcher() |
| .include(expectedPlan) |
| .match(); |
| |
| testBuilder() |
| .optionSettingQueriesForBaseline(SLICE_TARGET_DEFAULT) |
| .unOrdered() |
| .sqlQuery(query) |
| .sqlBaselineQuery(query) |
| .build() |
| .run(); |
| } finally { |
| client.resetSession(ExecConstants.SLICE_TARGET); |
| client.resetSession(PlannerSettings.UNIONALL_DISTRIBUTE_KEY); |
| } |
| } |
| |
| @Test |
| public void testIntersectAllWithValues() throws Exception { |
| testBuilder() |
| .sqlQuery("values('A') intersect all values('A')") |
| .unOrdered() |
| .baselineColumns("EXPR$0") |
| .baselineValues("A") |
| .go(); |
| } |
| |
| @Test |
| @Category(UnlikelyTest.class) |
| public void testFieldWithDots() throws Exception { |
| String fileName = "table.json"; |
| try (BufferedWriter writer = new BufferedWriter(new FileWriter(new File(dirTestWatcher.getRootDir(), fileName)))) { |
| writer.write("{\"rk.q\": \"a\", \"m\": {\"a.b\":\"1\", \"a\":{\"b\":\"2\"}, \"c\":\"3\"}}"); |
| } |
| |
| testBuilder() |
| .sqlQuery("select * from (" + |
| "(select t.m.`a.b` as a,\n" + |
| "t.m.a.b as b,\n" + |
| "t.m['a.b'] as c,\n" + |
| "t.`rk.q` as e\n" + |
| "from dfs.`%1$s` t)\n" + |
| "intersect all\n" + |
| "(select t.m.`a.b` as a,\n" + |
| "t.m.a.b as b,\n" + |
| "t.m['a.b'] as c,\n" + |
| "t.`rk.q` as e\n" + |
| "from dfs.`%1$s` t))", fileName) |
| .unOrdered() |
| .baselineColumns("a", "b", "c", "e") |
| .baselineValues("1", "2", "1", "a") |
| .go(); |
| } |
| |
| @Test |
| public void testExceptAllRightEmptyDir() throws Exception { |
| String rootSimple = "/store/json/booleanData.json"; |
| |
| testBuilder() |
| .sqlQuery("SELECT key FROM cp.`%s` EXCEPT ALL SELECT key FROM dfs.tmp_default_format.`%s`", |
| rootSimple, EMPTY_DIR_NAME) |
| .unOrdered() |
| .baselineColumns("key") |
| .baselineValues(true) |
| .baselineValues(false) |
| .build() |
| .run(); |
| } |
| |
| @Test |
| public void testExceptAllLeftEmptyDir() throws Exception { |
| final String rootSimple = "/store/json/booleanData.json"; |
| |
| testBuilder() |
| .sqlQuery("SELECT key FROM dfs.tmp_default_format.`%s` EXCEPT ALL SELECT key FROM cp.`%s`", |
| EMPTY_DIR_NAME, rootSimple) |
| .unOrdered() |
| .baselineColumns("key") |
| .expectsEmptyResultSet() |
| .build() |
| .run(); |
| } |
| |
| @Test |
| public void testIntersectBothEmptyDirs() throws Exception { |
| SchemaBuilder schemaBuilder = new SchemaBuilder() |
| .addNullable("key", TypeProtos.MinorType.INT); |
| BatchSchema expectedSchema = new BatchSchemaBuilder() |
| .withSchemaBuilder(schemaBuilder) |
| .build(); |
| |
| testBuilder() |
| .sqlQuery("SELECT key FROM dfs.tmp_default_format.`%1$s` INTERSECT ALL SELECT key FROM dfs.tmp_default_format.`%1$s`", EMPTY_DIR_NAME) |
| .schemaBaseLine(expectedSchema) |
| .build() |
| .run(); |
| } |
| |
| @Test |
| public void testSetOpMiddleEmptyDir() throws Exception { |
| final String query = "(SELECT n_regionkey FROM cp.`tpch/nation.parquet` EXCEPT ALL " + |
| "SELECT missing_key FROM dfs.tmp_default_format.`%s`) intersect all SELECT r_regionkey FROM cp.`tpch/region.parquet`"; |
| |
| testBuilder() |
| .sqlQuery(query, EMPTY_DIR_NAME) |
| .unOrdered() |
| .baselineColumns("n_regionkey") |
| .baselineValues(0) |
| .baselineValues(1) |
| .baselineValues(2) |
| .baselineValues(3) |
| .baselineValues(4) |
| .build() |
| .run(); |
| } |
| |
| @Test |
| public void testComplexQueryWithSetOpAndEmptyDir() throws Exception { |
| final String rootSimple = "/store/json/booleanData.json"; |
| |
| testBuilder() |
| .sqlQuery("SELECT key FROM cp.`%2$s` INTERSECT ALL SELECT key FROM " + |
| "(SELECT key FROM cp.`%2$s` EXCEPT ALL SELECT key FROM dfs.tmp_default_format.`%1$s`)", |
| EMPTY_DIR_NAME, rootSimple) |
| .unOrdered() |
| .baselineColumns("key") |
| .baselineValues(true) |
| .baselineValues(false) |
| .build() |
| .run(); |
| } |
| |
| @Test |
| public void testIntersectCancellation() throws Exception { |
| String query = "WITH foo AS\n" + |
| " (SELECT 1 AS a FROM cp.`/tpch/nation.parquet`\n" + |
| " Intersect ALL\n" + |
| " SELECT 1 AS a FROM cp.`/tpch/nation.parquet`\n" + |
| " WHERE n_nationkey > (SELECT 1) )\n" + |
| "SELECT * FROM foo\n" + |
| "LIMIT 1"; |
| |
| testBuilder() |
| .sqlQuery(query) |
| .unOrdered() |
| .baselineColumns("a") |
| .baselineValues(1) |
| .build() |
| .run(); |
| } |
| |
| @Test |
| public void testMultiBatch() throws Exception { |
| String query = "(select * from (values(1,1)) t(a,b) union all select * from (values(3,3)) t(a,b) union all select * from (values(5,5)) t(a,b)) intersect all " + |
| "(select * from (values(1,1)) t(a,b) union all select * from (values(3,3), (2,2)) t(a,b) union all select * from (values(6,6), (4,4), (5,5)) t(a,b)) "; |
| testBuilder() |
| .sqlQuery(query) |
| .unOrdered() |
| .baselineColumns("a", "b") |
| .baselineValues(5, 5) |
| .baselineValues(3, 3) |
| .baselineValues(1, 1) |
| .build().run(); |
| } |
| |
| @Test |
| public void testFirstEmptyBatch() throws Exception { |
| String query = "(select n_nationkey from cp.`tpch/nation.parquet` where n_nationkey < 0 union all select n_nationkey from cp.`tpch/nation.parquet` where n_nationkey < 5) intersect all " + |
| "(select n_nationkey from cp.`tpch/nation.parquet` where n_nationkey < 0 union all select n_nationkey from cp.`tpch/nation.parquet` where n_nationkey < 3)"; |
| testBuilder() |
| .sqlQuery(query) |
| .unOrdered() |
| .baselineColumns("n_nationkey") |
| .baselineValues(0) |
| .baselineValues(2) |
| .baselineValues(1) |
| .build().run(); |
| } |
| |
| @Test |
| public void testUnsupportedComplexType() { |
| try { |
| String query = "select sia from cp.`complex/json/complex.json` intersect all select sia from cp.`complex/json/complex.json`"; |
| testBuilder() |
| .sqlQuery(query) |
| .unOrdered() |
| .baselineColumns("sia") |
| .baselineValues("[1,11,101,1001]") |
| .baselineValues("[2,12,102,1002]") |
| .baselineValues("[3,13,103,1003]") |
| .build().run(); |
| Assert.fail("Missing expected exception on complex type"); |
| } catch (Exception ex) { |
| Assert.assertThat(ex.getMessage(), ex.getMessage(), |
| CoreMatchers.containsString("Map, Array, Union or repeated scalar type should not be used in group by, order by or in a comparison operator")); |
| } |
| } |
| } |