diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/SqlParser.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/SqlParser.scala index 89f4a19add1c..769b098fc3ce 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/SqlParser.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/SqlParser.scala @@ -61,6 +61,7 @@ class SqlParser extends AbstractSparkSQLParser with DataTypeParser { protected val CAST = Keyword("CAST") protected val COALESCE = Keyword("COALESCE") protected val COUNT = Keyword("COUNT") + protected val CROSS = Keyword("CROSS") protected val DESC = Keyword("DESC") protected val DISTINCT = Keyword("DISTINCT") protected val ELSE = Keyword("ELSE") @@ -164,7 +165,7 @@ class SqlParser extends AbstractSparkSQLParser with DataTypeParser { // Based very loosely on the MySQL Grammar. // http://dev.mysql.com/doc/refman/5.0/en/join.html protected lazy val relations: Parser[LogicalPlan] = - ( relation ~ rep1("," ~> relation) ^^ { + ( relation ~ rep1(("," | CROSS ~ JOIN) ~> relation) ^^ { case r1 ~ joins => joins.foldLeft(r1) { case(lhs, r) => Join(lhs, r, Inner, None) } } | relation ) diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/SqlParserSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/SqlParserSuite.scala index 1a0a0e6154ad..f11dfd18e55a 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/SqlParserSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/SqlParserSuite.scala @@ -58,4 +58,11 @@ class SqlParserSuite extends FunSuite { assert(TestCommand("NotRealCommand") === parser("execute NotRealCommand")) assert(TestCommand("NotRealCommand") === parser("exEcute NotRealCommand")) } + + test("cross join") { + val parser = new SqlParser + assert(parser("SELECT * FROM t1, t2") === parser("SELECT * FROM t1 CROSS JOIN t2")) + intercept[RuntimeException](parser("SELECT * FROM t1 CROSS JOIN t2 ON t1.a = t2.a")) + } + }