@@ -165,7 +165,7 @@ case class CreateViewCommand(
165165 throw new AnalysisException (s " $name is not a view " )
166166 } else if (replace) {
167167 // Handles `CREATE OR REPLACE VIEW v0 AS SELECT ...`
168- catalog.alterTable(prepareTable(sparkSession, aliasedPlan))
168+ catalog.alterTable(prepareTable(sparkSession, aliasedPlan, analyzedPlan ))
169169 } else {
170170 // Handles `CREATE VIEW v0 AS SELECT ...`. Throws exception when the target view already
171171 // exists.
@@ -175,7 +175,8 @@ case class CreateViewCommand(
175175 }
176176 } else {
177177 // Create the view if it doesn't exist.
178- catalog.createTable(prepareTable(sparkSession, aliasedPlan), ignoreIfExists = false )
178+ catalog.createTable(prepareTable(sparkSession, aliasedPlan, analyzedPlan),
179+ ignoreIfExists = false )
179180 }
180181 Seq .empty[Row ]
181182 }
@@ -212,14 +213,23 @@ case class CreateViewCommand(
212213 * Returns a [[CatalogTable ]] that can be used to save in the catalog. Generate the view-specific
213214 * properties(e.g. view default database, view query output column names) and store them as
214215 * properties in the CatalogTable, and also creates the proper schema for the view.
216+ *
217+ * @param session the spark session.
218+ * @param aliasedPlan if `userSpecifiedColumns` is defined, the aliased plan outputs the user
219+ * specified columns, else it is the same as the `analyzedPlan`.
220+ * @param analyzedPlan the analyzed logical plan that represents the child of a view.
221+ * @return a CatalogTable that can be used to save in the catalog.
215222 */
216- private def prepareTable (session : SparkSession , aliasedPlan : LogicalPlan ): CatalogTable = {
223+ private def prepareTable (
224+ session : SparkSession ,
225+ aliasedPlan : LogicalPlan ,
226+ analyzedPlan : LogicalPlan ): CatalogTable = {
217227 if (originalText.isEmpty) {
218228 throw new AnalysisException (
219229 " It is not allowed to create a persisted view from the Dataset API" )
220230 }
221231
222- val newProperties = generateViewProperties(properties, session, originalText.get )
232+ val newProperties = generateViewProperties(properties, session, analyzedPlan )
223233
224234 CatalogTable (
225235 identifier = name,
@@ -276,7 +286,7 @@ case class AlterViewAsCommand(
276286 throw new AnalysisException (s " ${viewMeta.identifier} is not a view. " )
277287 }
278288
279- val newProperties = generateViewProperties(viewMeta.properties, session, originalText )
289+ val newProperties = generateViewProperties(viewMeta.properties, session, analyzedPlan )
280290
281291 val updatedViewMeta = viewMeta.copy(
282292 schema = analyzedPlan.schema,
@@ -332,30 +342,17 @@ object ViewHelper {
332342 *
333343 * @param properties the `properties` in CatalogTable.
334344 * @param session the spark session.
335- * @param viewText the query string used to create the child plan on view resolution .
345+ * @param analyzedPlan the analyzed logical plan that represents the child of a view.
336346 * @return new view properties including view default database and query column names properties.
337347 */
338348 def generateViewProperties (
339349 properties : Map [String , String ],
340350 session : SparkSession ,
341- viewText : String ): Map [String , String ] = {
342- // Try to analyze the viewText, throw an AnalysisException if the query is invalid.
343- val queryPlan = try {
344- val unresolvedPlan = session.sessionState.sqlParser.parsePlan(viewText)
345- val resolvedPlan = session.sessionState.analyzer.execute(unresolvedPlan)
346- session.sessionState.analyzer.checkAnalysis(resolvedPlan)
347-
348- resolvedPlan
349- } catch {
350- case e : AnalysisException =>
351- throw new AnalysisException (s " Failed to analyze the view query SQL: $viewText" ,
352- cause = Some (e))
353- }
354-
351+ analyzedPlan : LogicalPlan ): Map [String , String ] = {
355352 // Generate the query column names, throw an AnalysisException if there exists duplicate column
356353 // names.
357- val queryOutput = queryPlan .schema.fieldNames
358- assert(queryOutput.toSet .size == queryOutput.size,
354+ val queryOutput = analyzedPlan .schema.fieldNames
355+ assert(queryOutput.distinct .size == queryOutput.size,
359356 s " The view output ${queryOutput.mkString(" (" , " ," , " )" )} contains duplicate column name. " )
360357
361358 // Generate the view default database name.
0 commit comments