diff --git a/sql/catalyst/src/main/antlr4/org/apache/spark/sql/catalyst/parser/SqlBase.g4 b/sql/catalyst/src/main/antlr4/org/apache/spark/sql/catalyst/parser/SqlBase.g4 index 547013c23fd78c1f21fcf6baf00f352a14bcdf93..4584aea6196a6d029bd787f4e272c6d9556d2a74 100644 --- a/sql/catalyst/src/main/antlr4/org/apache/spark/sql/catalyst/parser/SqlBase.g4 +++ b/sql/catalyst/src/main/antlr4/org/apache/spark/sql/catalyst/parser/SqlBase.g4 @@ -473,7 +473,7 @@ identifierComment relationPrimary : tableIdentifier sample? tableAlias #tableName - | '(' queryNoWith ')' sample? (AS? strictIdentifier) #aliasedQuery + | '(' queryNoWith ')' sample? (AS? strictIdentifier)? #aliasedQuery | '(' relation ')' sample? (AS? strictIdentifier)? #aliasedRelation | inlineTable #inlineTableDefault2 | functionTable #tableValuedFunction diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala index 5f34d0777d5a19eedbb8f5f103fe1ed75f00a916..4eb5560155781bd6d050d047127916b102bd38cf 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala @@ -749,6 +749,13 @@ class AstBuilder(conf: SQLConf) extends SqlBaseBaseVisitor[AnyRef] with Logging * hooks. */ override def visitAliasedQuery(ctx: AliasedQueryContext): LogicalPlan = withOrigin(ctx) { + // The unaliased subqueries in the FROM clause are disallowed. Instead of rejecting it in + // parser rules, we handle it here in order to provide better error message. + if (ctx.strictIdentifier == null) { + throw new ParseException("The unaliased subqueries in the FROM clause are not supported.", + ctx) + } + aliasPlan(ctx.strictIdentifier, plan(ctx.queryNoWith).optionalMap(ctx.sample)(withSample)) } diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/PlanParserSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/PlanParserSuite.scala index 7a5357eef8f94622a5af2a277743ef4c27868e96..3a26adaef9db068a4b39cababda0664108f11c06 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/PlanParserSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/PlanParserSuite.scala @@ -448,13 +448,15 @@ class PlanParserSuite extends PlanTest { } test("aliased subquery") { + val errMsg = "The unaliased subqueries in the FROM clause are not supported" + assertEqual("select a from (select id as a from t0) tt", table("t0").select('id.as("a")).as("tt").select('a)) - intercept("select a from (select id as a from t0)", "mismatched input") + intercept("select a from (select id as a from t0)", errMsg) assertEqual("from (select id as a from t0) tt select a", table("t0").select('id.as("a")).as("tt").select('a)) - intercept("from (select id as a from t0) select a", "extraneous input 'a'") + intercept("from (select id as a from t0) select a", errMsg) } test("scalar sub-query") { diff --git a/sql/core/src/test/resources/sql-tests/inputs/subquery/subquery-in-from.sql b/sql/core/src/test/resources/sql-tests/inputs/subquery/subquery-in-from.sql new file mode 100644 index 0000000000000000000000000000000000000000..1273b56b6344b906b39292843bff6f5fea9c771f --- /dev/null +++ b/sql/core/src/test/resources/sql-tests/inputs/subquery/subquery-in-from.sql @@ -0,0 +1,14 @@ +-- Aliased subqueries in FROM clause +SELECT * FROM (SELECT * FROM testData) AS t WHERE key = 1; + +FROM (SELECT * FROM testData WHERE key = 1) AS t SELECT *; + +-- Optional `AS` keyword +SELECT * FROM (SELECT * FROM testData) t WHERE key = 1; + +FROM (SELECT * FROM testData WHERE key = 1) t SELECT *; + +-- Disallow unaliased subqueries in FROM clause +SELECT * FROM (SELECT * FROM testData) WHERE key = 1; + +FROM (SELECT * FROM testData WHERE key = 1) SELECT *; diff --git a/sql/core/src/test/resources/sql-tests/results/subquery/subquery-in-from.sql.out b/sql/core/src/test/resources/sql-tests/results/subquery/subquery-in-from.sql.out new file mode 100644 index 0000000000000000000000000000000000000000..14553557d1ffc73b17db0c478f8bc9950107a408 --- /dev/null +++ b/sql/core/src/test/resources/sql-tests/results/subquery/subquery-in-from.sql.out @@ -0,0 +1,62 @@ +-- Automatically generated by SQLQueryTestSuite +-- Number of queries: 6 + + +-- !query 0 +SELECT * FROM (SELECT * FROM testData) AS t WHERE key = 1 +-- !query 0 schema +struct<key:int,value:string> +-- !query 0 output +1 1 + + +-- !query 1 +FROM (SELECT * FROM testData WHERE key = 1) AS t SELECT * +-- !query 1 schema +struct<key:int,value:string> +-- !query 1 output +1 1 + + +-- !query 2 +SELECT * FROM (SELECT * FROM testData) t WHERE key = 1 +-- !query 2 schema +struct<key:int,value:string> +-- !query 2 output +1 1 + + +-- !query 3 +FROM (SELECT * FROM testData WHERE key = 1) t SELECT * +-- !query 3 schema +struct<key:int,value:string> +-- !query 3 output +1 1 + + +-- !query 4 +SELECT * FROM (SELECT * FROM testData) WHERE key = 1 +-- !query 4 schema +struct<> +-- !query 4 output +org.apache.spark.sql.catalyst.parser.ParseException + +The unaliased subqueries in the FROM clause are not supported.(line 1, pos 14) + +== SQL == +SELECT * FROM (SELECT * FROM testData) WHERE key = 1 +--------------^^^ + + +-- !query 5 +FROM (SELECT * FROM testData WHERE key = 1) SELECT * +-- !query 5 schema +struct<> +-- !query 5 output +org.apache.spark.sql.catalyst.parser.ParseException + +The unaliased subqueries in the FROM clause are not supported.(line 1, pos 5) + +== SQL == +FROM (SELECT * FROM testData WHERE key = 1) SELECT * +-----^^^