diff --git a/airframe-sql/src/main/scala/wvlet/airframe/sql/parser/SQLGenerator.scala b/airframe-sql/src/main/scala/wvlet/airframe/sql/parser/SQLGenerator.scala index 87cef3b902..06f343dec4 100644 --- a/airframe-sql/src/main/scala/wvlet/airframe/sql/parser/SQLGenerator.scala +++ b/airframe-sql/src/main/scala/wvlet/airframe/sql/parser/SQLGenerator.scala @@ -122,22 +122,7 @@ object SQLGenerator extends LogSupport { findNonEmpty(nonFilterChild).map { f => b += "FROM" - f match { - case _: Selection => - b += s"(${printRelation(f)})" - case _: SetOperation => - b += s"(${printRelation(f)})" - case _: Limit => - b += s"(${printRelation(f)})" - case _: Filter => - b += s"(${printRelation(f)})" - case _: Sort => - b += s"(${printRelation(f)})" - case _: Distinct => - b += s"(${printRelation(f)})" - case _ => - b += printRelation(f) - } + b += printRelationWithParenthesesIfNecessary(f) } val filterSet = s match { @@ -227,12 +212,8 @@ object SQLGenerator extends LogSupport { case _ => s"(${r}) AS ${alias.sqlExpr}${c}" } case Join(joinType, left, right, cond, _) => - val l = printRelation(left) - val r = right match { - case _: Selection => s"(${printRelation(right)})" - case _: SetOperation => s"(${printRelation(right)})" - case _ => printRelation(right) - } + val l = printRelationWithParenthesesIfNecessary(left) + val r = printRelationWithParenthesesIfNecessary(right) val c = cond match { case NaturalJoin(_) => "" case JoinUsing(columns, _) => s" USING (${columns.map(_.sqlExpr).mkString(", ")})" @@ -276,6 +257,18 @@ object SQLGenerator extends LogSupport { } } + def printRelationWithParenthesesIfNecessary(r: Relation): String = { + r match { + case _: Selection => s"(${printRelation(r)})" + case _: SetOperation => s"(${printRelation(r)})" + case _: Limit => s"(${printRelation(r)})" + case _: Filter => s"(${printRelation(r)})" + case _: Sort => s"(${printRelation(r)})" + case _: Distinct => s"(${printRelation(r)})" + case _ => printRelation(r) + } + } + def printDDL(e: DDL): String = { e match { case CreateSchema(name, ifNotExists, propsOpt, _) => diff --git a/airframe-sql/src/test/scala/wvlet/airframe/sql/parser/SQLGeneratorTest.scala b/airframe-sql/src/test/scala/wvlet/airframe/sql/parser/SQLGeneratorTest.scala index a829d4fe8c..68d92e2805 100644 --- a/airframe-sql/src/test/scala/wvlet/airframe/sql/parser/SQLGeneratorTest.scala +++ b/airframe-sql/src/test/scala/wvlet/airframe/sql/parser/SQLGeneratorTest.scala @@ -178,4 +178,12 @@ class SQLGeneratorTest extends AirSpec { val sql = SQLGenerator.print(resolvedPlan).toLowerCase sql shouldBe "with t1 as (select id as xid from (select id as pid from a)) select xid from t1" } + + test("join with sub query at left side") { + val resolvedPlan = + SQLAnalyzer.analyze("select * from (select * from A) inner join A using (id)", "default", demoCatalog) + + val sql = SQLGenerator.print(resolvedPlan).toLowerCase + sql shouldBe "select * from (select * from a) join a using (id)" + } }