提交 dd83c209 编写于 作者: D Davies Liu 提交者: Cheng Lian

[SPARK-13603][SQL] support SQL generation for subquery

## What changes were proposed in this pull request?

This is support SQL generation for subquery expressions, which will be replaced to a SubqueryHolder inside SQLBuilder recursively.

## How was this patch tested?

Added unit tests.

Author: Davies Liu <davies@databricks.com>

Closes #11453 from davies/sql_subquery.
上级 465c665d
...@@ -76,6 +76,4 @@ case class ScalarSubquery( ...@@ -76,6 +76,4 @@ case class ScalarSubquery(
override def withNewPlan(plan: LogicalPlan): ScalarSubquery = ScalarSubquery(plan, exprId) override def withNewPlan(plan: LogicalPlan): ScalarSubquery = ScalarSubquery(plan, exprId)
override def toString: String = s"subquery#${exprId.id}" override def toString: String = s"subquery#${exprId.id}"
// TODO: support sql()
} }
...@@ -24,13 +24,22 @@ import scala.util.control.NonFatal ...@@ -24,13 +24,22 @@ import scala.util.control.NonFatal
import org.apache.spark.Logging import org.apache.spark.Logging
import org.apache.spark.sql.{DataFrame, SQLContext} import org.apache.spark.sql.{DataFrame, SQLContext}
import org.apache.spark.sql.catalyst.TableIdentifier import org.apache.spark.sql.catalyst.TableIdentifier
import org.apache.spark.sql.catalyst.expressions.{Attribute, NamedExpression, NonSQLExpression, import org.apache.spark.sql.catalyst.expressions._
SortOrder}
import org.apache.spark.sql.catalyst.optimizer.CollapseProject import org.apache.spark.sql.catalyst.optimizer.CollapseProject
import org.apache.spark.sql.catalyst.plans.logical._ import org.apache.spark.sql.catalyst.plans.logical._
import org.apache.spark.sql.catalyst.rules.{Rule, RuleExecutor} import org.apache.spark.sql.catalyst.rules.{Rule, RuleExecutor}
import org.apache.spark.sql.catalyst.util.quoteIdentifier import org.apache.spark.sql.catalyst.util.quoteIdentifier
import org.apache.spark.sql.execution.datasources.LogicalRelation import org.apache.spark.sql.execution.datasources.LogicalRelation
import org.apache.spark.sql.types.{DataType, NullType}
/**
* A place holder for generated SQL for subquery expression.
*/
case class SubqueryHolder(query: String) extends LeafExpression with Unevaluable {
override def dataType: DataType = NullType
override def nullable: Boolean = true
override def sql: String = s"($query)"
}
/** /**
* A builder class used to convert a resolved logical plan into a SQL query string. Note that this * A builder class used to convert a resolved logical plan into a SQL query string. Note that this
...@@ -46,7 +55,9 @@ class SQLBuilder(logicalPlan: LogicalPlan, sqlContext: SQLContext) extends Loggi ...@@ -46,7 +55,9 @@ class SQLBuilder(logicalPlan: LogicalPlan, sqlContext: SQLContext) extends Loggi
def toSQL: String = { def toSQL: String = {
val canonicalizedPlan = Canonicalizer.execute(logicalPlan) val canonicalizedPlan = Canonicalizer.execute(logicalPlan)
try { try {
canonicalizedPlan.transformAllExpressions { val replaced = canonicalizedPlan.transformAllExpressions {
case e: SubqueryExpression =>
SubqueryHolder(new SQLBuilder(e.query, sqlContext).toSQL)
case e: NonSQLExpression => case e: NonSQLExpression =>
throw new UnsupportedOperationException( throw new UnsupportedOperationException(
s"Expression $e doesn't have a SQL representation" s"Expression $e doesn't have a SQL representation"
...@@ -54,14 +65,14 @@ class SQLBuilder(logicalPlan: LogicalPlan, sqlContext: SQLContext) extends Loggi ...@@ -54,14 +65,14 @@ class SQLBuilder(logicalPlan: LogicalPlan, sqlContext: SQLContext) extends Loggi
case e => e case e => e
} }
val generatedSQL = toSQL(canonicalizedPlan, true) val generatedSQL = toSQL(replaced, true)
logDebug( logDebug(
s"""Built SQL query string successfully from given logical plan: s"""Built SQL query string successfully from given logical plan:
| |
|# Original logical plan: |# Original logical plan:
|${logicalPlan.treeString} |${logicalPlan.treeString}
|# Canonicalized logical plan: |# Canonicalized logical plan:
|${canonicalizedPlan.treeString} |${replaced.treeString}
|# Generated SQL: |# Generated SQL:
|$generatedSQL |$generatedSQL
""".stripMargin) """.stripMargin)
......
...@@ -268,4 +268,9 @@ class ExpressionToSQLSuite extends SQLBuilderTest with SQLTestUtils { ...@@ -268,4 +268,9 @@ class ExpressionToSQLSuite extends SQLBuilderTest with SQLTestUtils {
checkSqlGeneration("SELECT input_file_name()") checkSqlGeneration("SELECT input_file_name()")
checkSqlGeneration("SELECT monotonically_increasing_id()") checkSqlGeneration("SELECT monotonically_increasing_id()")
} }
test("subquery") {
checkSqlGeneration("SELECT 1 + (SELECT 2)")
checkSqlGeneration("SELECT 1 + (SELECT 2 + (SELECT 3 as a))")
}
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册