1818package org .apache .spark .sql .execution .command
1919
2020import org .apache .spark .sql .{AnalysisException , Row , SparkSession }
21+ import org .apache .spark .sql .catalyst .analysis ._
2122import org .apache .spark .sql .catalyst .expressions ._
23+ import org .apache .spark .sql .types .StructField
24+
25+ /**
26+ * This class provides arguments and body expression of the macro function.
27+ */
28+ case class MacroFunctionWrapper (columns : Seq [StructField ], macroFunction : Expression )
2229
2330/**
2431 * The DDL command that creates a macro.
@@ -29,20 +36,54 @@ import org.apache.spark.sql.catalyst.expressions._
2936 */
3037case class CreateMacroCommand (
3138 macroName : String ,
32- columns : Seq [AttributeReference ],
33- macroFunction : Expression )
39+ funcWrapper : MacroFunctionWrapper )
3440 extends RunnableCommand {
3541
3642 override def run (sparkSession : SparkSession ): Seq [Row ] = {
3743 val catalog = sparkSession.sessionState.catalog
38- val macroInfo = columns.mkString(" ," ) + " -> " + macroFunction.toString
44+ val columns = funcWrapper.columns.map { col =>
45+ AttributeReference (col.name, col.dataType, col.nullable, col.metadata)() }
46+ val colToIndex : Map [String , Int ] = columns.map(_.name).zipWithIndex.toMap
47+ if (colToIndex.size != columns.size) {
48+ throw new AnalysisException (s " Cannot support duplicate colNames " +
49+ s " for CREATE TEMPORARY MACRO $macroName, actual columns: ${columns.mkString(" ," )}" )
50+ }
51+ val macroFunction = funcWrapper.macroFunction.transformDown {
52+ case u : UnresolvedAttribute =>
53+ val index = colToIndex.get(u.name).getOrElse(
54+ throw new AnalysisException (s " Cannot find colName: ${u} " +
55+ s " for CREATE TEMPORARY MACRO $macroName, actual columns: ${columns.mkString(" ," )}" ))
56+ BoundReference (index, columns(index).dataType, columns(index).nullable)
57+ case u : UnresolvedFunction =>
58+ sparkSession.sessionState.analyzer.resolveFunction(u)
59+ case s : SubqueryExpression =>
60+ throw new AnalysisException (s " Cannot support Subquery: ${s} " +
61+ s " for CREATE TEMPORARY MACRO $macroName" )
62+ case u : UnresolvedGenerator =>
63+ throw new AnalysisException (s " Cannot support Generator: ${u} " +
64+ s " for CREATE TEMPORARY MACRO $macroName" )
65+ }
66+ if (! macroFunction.resolved) {
67+ if (macroFunction.checkInputDataTypes().isFailure) {
68+ macroFunction.checkInputDataTypes() match {
69+ case TypeCheckResult .TypeCheckFailure (message) =>
70+ throw new AnalysisException (s " Cannot resolve ' ${macroFunction.sql}' " +
71+ s " for CREATE TEMPORARY MACRO $macroName, due to data type mismatch: $message" )
72+ }
73+ } else {
74+ throw new AnalysisException (s " Cannot resolve ' ${macroFunction.sql}' " +
75+ s " for CREATE TEMPORARY MACRO $macroName" )
76+ }
77+ }
78+ val macroInfo = columns.mkString(" ," ) + " -> " + funcWrapper.macroFunction.toString
3979 val info = new ExpressionInfo (macroInfo, macroName)
4080 val builder = (children : Seq [Expression ]) => {
4181 if (children.size != columns.size) {
4282 throw new AnalysisException (s " Actual number of columns: ${children.size} != " +
4383 s " expected number of columns: ${columns.size} for Macro $macroName" )
4484 }
4585 macroFunction.transformUp {
86+ // Skip to validate the input type because Analyzer will check it after ResolveFunctions.
4687 case b : BoundReference => children(b.ordinal)
4788 }
4889 }
0 commit comments