diff options
author | Srinath Shankar <srinath@databricks.com> | 2016-09-03 00:20:43 +0200 |
---|---|---|
committer | Herman van Hovell <hvanhovell@databricks.com> | 2016-09-03 00:20:43 +0200 |
commit | e6132a6cf10df8b12af8dd8d1a2c563792b5cc5a (patch) | |
tree | d706ac4d4091a7ae31eda5c7d62c2d8c2c4a7414 /sql/hive/src | |
parent | a2c9acb0e54b2e38cb8ee6431f1ea0e0b4cd959a (diff) | |
download | spark-e6132a6cf10df8b12af8dd8d1a2c563792b5cc5a.tar.gz spark-e6132a6cf10df8b12af8dd8d1a2c563792b5cc5a.tar.bz2 spark-e6132a6cf10df8b12af8dd8d1a2c563792b5cc5a.zip |
[SPARK-17298][SQL] Require explicit CROSS join for cartesian products
## What changes were proposed in this pull request?
Require the use of CROSS join syntax in SQL (and a new crossJoin
DataFrame API) to specify explicit cartesian products between relations.
By cartesian product we mean a join between relations R and S where
there is no join condition involving columns from both R and S.
If a cartesian product is detected in the absence of an explicit CROSS
join, an error must be thrown. Turning on the
"spark.sql.crossJoin.enabled" configuration flag will disable this check
and allow cartesian products without an explicit CROSS join.
The new crossJoin DataFrame API must be used to specify explicit cross
joins. The existing join(DataFrame) method will produce a INNER join
that will require a subsequent join condition.
That is df1.join(df2) is equivalent to select * from df1, df2.
## How was this patch tested?
Added cross-join.sql to the SQLQueryTestSuite to test the check for cartesian products. Added a couple of tests to the DataFrameJoinSuite to test the crossJoin API. Modified various other test suites to explicitly specify a cross join where an INNER join or a comma-separated list was previously used.
Author: Srinath Shankar <srinath@databricks.com>
Closes #14866 from srinathshankar/crossjoin.
Diffstat (limited to 'sql/hive/src')
4 files changed, 6 insertions, 10 deletions
diff --git a/sql/hive/src/test/resources/sqlgen/join_2_tables.sql b/sql/hive/src/test/resources/sqlgen/join_2_tables.sql index 9dd200c3c0..0f033a04ae 100644 --- a/sql/hive/src/test/resources/sqlgen/join_2_tables.sql +++ b/sql/hive/src/test/resources/sqlgen/join_2_tables.sql @@ -1,7 +1,7 @@ -- This file is automatically generated by LogicalPlanToSQLSuite. SELECT COUNT(a.value), b.KEY, a.KEY -FROM parquet_t1 a, parquet_t1 b +FROM parquet_t1 a CROSS JOIN parquet_t1 b GROUP BY a.KEY, b.KEY HAVING MAX(a.KEY) > 0 -------------------------------------------------------------------------------- -SELECT `gen_attr_0` AS `count(value)`, `gen_attr_1` AS `KEY`, `gen_attr_2` AS `KEY` FROM (SELECT `gen_attr_0`, `gen_attr_1`, `gen_attr_2` FROM (SELECT count(`gen_attr_4`) AS `gen_attr_0`, `gen_attr_1`, `gen_attr_2`, max(`gen_attr_2`) AS `gen_attr_3` FROM (SELECT `key` AS `gen_attr_2`, `value` AS `gen_attr_4` FROM `default`.`parquet_t1`) AS gen_subquery_0 INNER JOIN (SELECT `key` AS `gen_attr_1`, `value` AS `gen_attr_5` FROM `default`.`parquet_t1`) AS gen_subquery_1 GROUP BY `gen_attr_2`, `gen_attr_1` HAVING (`gen_attr_3` > CAST(0 AS BIGINT))) AS gen_subquery_2) AS gen_subquery_3 +SELECT `gen_attr_0` AS `count(value)`, `gen_attr_1` AS `KEY`, `gen_attr_2` AS `KEY` FROM (SELECT `gen_attr_0`, `gen_attr_1`, `gen_attr_2` FROM (SELECT count(`gen_attr_4`) AS `gen_attr_0`, `gen_attr_1`, `gen_attr_2`, max(`gen_attr_2`) AS `gen_attr_3` FROM (SELECT `key` AS `gen_attr_2`, `value` AS `gen_attr_4` FROM `default`.`parquet_t1`) AS gen_subquery_0 CROSS JOIN (SELECT `key` AS `gen_attr_1`, `value` AS `gen_attr_5` FROM `default`.`parquet_t1`) AS gen_subquery_1 GROUP BY `gen_attr_2`, `gen_attr_1` HAVING (`gen_attr_3` > CAST(0 AS BIGINT))) AS gen_subquery_2) AS gen_subquery_3 diff --git a/sql/hive/src/test/scala/org/apache/spark/sql/catalyst/LogicalPlanToSQLSuite.scala b/sql/hive/src/test/scala/org/apache/spark/sql/catalyst/LogicalPlanToSQLSuite.scala index 9c6da6a628..3e0fdc1f8b 100644 --- a/sql/hive/src/test/scala/org/apache/spark/sql/catalyst/LogicalPlanToSQLSuite.scala +++ b/sql/hive/src/test/scala/org/apache/spark/sql/catalyst/LogicalPlanToSQLSuite.scala @@ -642,7 +642,7 @@ class LogicalPlanToSQLSuite extends SQLBuilderTest with SQLTestUtils { checkColumnNames( """SELECT x.a, y.a, x.b, y.b |FROM (SELECT 1 AS a, 2 AS b) x - |INNER JOIN (SELECT 1 AS a, 2 AS b) y + |CROSS JOIN (SELECT 1 AS a, 2 AS b) y |ON x.a = y.a """.stripMargin, "a", "a", "b", "b" @@ -810,7 +810,7 @@ class LogicalPlanToSQLSuite extends SQLBuilderTest with SQLTestUtils { checkSQL( """ |SELECT COUNT(a.value), b.KEY, a.KEY - |FROM parquet_t1 a, parquet_t1 b + |FROM parquet_t1 a CROSS JOIN parquet_t1 b |GROUP BY a.KEY, b.KEY |HAVING MAX(a.KEY) > 0 """.stripMargin, diff --git a/sql/hive/src/test/scala/org/apache/spark/sql/hive/execution/HiveQuerySuite.scala b/sql/hive/src/test/scala/org/apache/spark/sql/hive/execution/HiveQuerySuite.scala index 3c7dbb449c..1d1a958d3f 100644 --- a/sql/hive/src/test/scala/org/apache/spark/sql/hive/execution/HiveQuerySuite.scala +++ b/sql/hive/src/test/scala/org/apache/spark/sql/hive/execution/HiveQuerySuite.scala @@ -318,10 +318,6 @@ class HiveQuerySuite extends HiveComparisonTest with BeforeAndAfter { createQueryTest("trivial join ON clause", "SELECT * FROM src a JOIN src b ON a.key = b.key") - createQueryTest("small.cartesian", - "SELECT a.key, b.key FROM (SELECT key FROM src WHERE key < 1) a JOIN " + - "(SELECT key FROM src WHERE key = 2) b") - createQueryTest("length.udf", "SELECT length(\"test\") FROM src LIMIT 1") diff --git a/sql/hive/src/test/scala/org/apache/spark/sql/hive/parquetSuites.scala b/sql/hive/src/test/scala/org/apache/spark/sql/hive/parquetSuites.scala index e92bbdea75..2f6d9fb96b 100644 --- a/sql/hive/src/test/scala/org/apache/spark/sql/hive/parquetSuites.scala +++ b/sql/hive/src/test/scala/org/apache/spark/sql/hive/parquetSuites.scala @@ -592,9 +592,9 @@ class ParquetMetastoreSuite extends ParquetPartitioningTest { test("self-join") { val table = spark.table("normal_parquet") - val selfJoin = table.as("t1").join(table.as("t2")) + val selfJoin = table.as("t1").crossJoin(table.as("t2")) checkAnswer(selfJoin, - sql("SELECT * FROM normal_parquet x JOIN normal_parquet y")) + sql("SELECT * FROM normal_parquet x CROSS JOIN normal_parquet y")) } } |