[SPARK-35789][SQL] Refine lateral join syntax to only allow subqueries
### What changes were proposed in this pull request? This PR is a follow-up for SPARK-34382. It refines the lateral join syntax to only allow the LATERAL keyword to be in front of subqueries, instead of all `relationPriamry`. For example, `SELECT * FROM t1, LATERAL t2` should not be allowed. ### Why are the changes needed? To be consistent with Postgres. ### Does this PR introduce _any_ user-facing change? Yes. After this PR, the LATERAL keyword can only be in front of subqueries. ```scala sql("SELECT * FROM t1, LATERAL t2") org.apache.spark.sql.catalyst.parser.ParseException: LATERAL can only be used with subquery(line 1, pos 26) == SQL == select * from t1, lateral t2 --------------------------^^^ ``` ### How was this patch tested? New unit tests. Closes #32937 from allisonwang-db/spark-35789-lateral-join-parser. Authored-by: allisonwang-db <allison.wang@databricks.com> Signed-off-by: Wenchen Fan <wenchen@databricks.com>
This commit is contained in:
parent
509c076bc0
commit
0d900b6cfa
|
@ -873,6 +873,9 @@ class AstBuilder extends SqlBaseBaseVisitor[AnyRef] with SQLConfHelper with Logg
|
|||
val right = plan(relation.relationPrimary)
|
||||
val join = right.optionalMap(left) { (left, right) =>
|
||||
if (relation.LATERAL != null) {
|
||||
if (!relation.relationPrimary.isInstanceOf[AliasedQueryContext]) {
|
||||
throw QueryParsingErrors.invalidLateralJoinRelationError(relation.relationPrimary)
|
||||
}
|
||||
LateralJoin(left, LateralSubquery(right), Inner, None)
|
||||
} else {
|
||||
Join(left, right, Inner, None, JoinHint.NONE)
|
||||
|
@ -1130,6 +1133,10 @@ class AstBuilder extends SqlBaseBaseVisitor[AnyRef] with SQLConfHelper with Logg
|
|||
case _ => Inner
|
||||
}
|
||||
|
||||
if (join.LATERAL != null && !join.right.isInstanceOf[AliasedQueryContext]) {
|
||||
throw QueryParsingErrors.invalidLateralJoinRelationError(join.right)
|
||||
}
|
||||
|
||||
// Resolve the join type and join condition
|
||||
val (joinType, condition) = Option(join.joinCriteria) match {
|
||||
case Some(c) if c.USING != null =>
|
||||
|
|
|
@ -112,6 +112,10 @@ object QueryParsingErrors {
|
|||
new ParseException(s"Unsupported LATERAL join type $joinType", ctx)
|
||||
}
|
||||
|
||||
def invalidLateralJoinRelationError(ctx: RelationPrimaryContext): Throwable = {
|
||||
new ParseException(s"LATERAL can only be used with subquery", ctx)
|
||||
}
|
||||
|
||||
def repetitiveWindowDefinitionError(name: String, ctx: WindowClauseContext): Throwable = {
|
||||
new ParseException(s"The definition of window '$name' is repetitive", ctx)
|
||||
}
|
||||
|
|
|
@ -208,4 +208,14 @@ class ErrorParserSuite extends AnalysisTest {
|
|||
|SELECT b
|
||||
""".stripMargin, 2, 9, 10, msg + " test-table")
|
||||
}
|
||||
|
||||
test("SPARK-35789: lateral join with non-subquery relations") {
|
||||
val msg = "LATERAL can only be used with subquery"
|
||||
intercept("SELECT * FROM t1, LATERAL t2", msg)
|
||||
intercept("SELECT * FROM t1 JOIN LATERAL t2", msg)
|
||||
intercept("SELECT * FROM t1, LATERAL (t2 JOIN t3)", msg)
|
||||
intercept("SELECT * FROM t1, LATERAL (LATERAL t2)", msg)
|
||||
intercept("SELECT * FROM t1, LATERAL VALUES (0, 1)", msg)
|
||||
intercept("SELECT * FROM t1, LATERAL RANGE(0, 1)", msg)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue