Skip to content

Commit eeb3712

Browse files
committed
refactoring
1 parent 12af3a7 commit eeb3712

File tree

2 files changed

+90
-63
lines changed

2 files changed

+90
-63
lines changed

sql/core/src/main/scala/org/apache/spark/sql/execution/command/views.scala

Lines changed: 79 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ import scala.collection.mutable
2222
import org.json4s.JsonAST.{JArray, JString}
2323
import org.json4s.jackson.JsonMethods._
2424

25+
import org.apache.spark.internal.Logging
2526
import org.apache.spark.sql.{AnalysisException, Row, SparkSession}
26-
import org.apache.spark.sql.catalyst.{FunctionIdentifier, TableIdentifier}
27+
import org.apache.spark.sql.catalyst.{FunctionIdentifier, SQLConfHelper, TableIdentifier}
2728
import org.apache.spark.sql.catalyst.analysis.{GlobalTempView, LocalTempView, PersistedView, ViewType}
2829
import org.apache.spark.sql.catalyst.catalog.{CatalogStorageFormat, CatalogTable, CatalogTableType, SessionCatalog, TemporaryViewRelation}
2930
import org.apache.spark.sql.catalyst.expressions.{Alias, Attribute, SubqueryExpression, UserDefinedExpression}
@@ -115,48 +116,27 @@ case class CreateViewCommand(
115116

116117
if (viewType == LocalTempView) {
117118
val aliasedPlan = aliasPlan(sparkSession, analyzedPlan)
118-
if (replace && needsToUncache(catalog.getRawTempView(name.table), aliasedPlan)) {
119-
logInfo(s"Try to uncache ${name.quotedString} before replacing.")
120-
checkCyclicViewReference(analyzedPlan, Seq(name), name)
121-
CommandUtils.uncacheTableOrView(sparkSession, name.quotedString)
122-
}
123-
// If there is no sql text (e.g. from Dataset API), we will always store the analyzed plan
124-
val tableDefinition = if (!conf.storeAnalyzedPlanForView && originalText.nonEmpty) {
125-
TemporaryViewRelation(
126-
prepareTemporaryView(
127-
name,
128-
sparkSession,
129-
analyzedPlan,
130-
aliasedPlan.schema,
131-
originalText))
132-
} else {
133-
TemporaryViewRelation(
134-
prepareTemporaryViewFromDataFrame(name, aliasedPlan),
135-
Some(aliasedPlan))
136-
}
119+
val tableDefinition = createTemporaryViewRelation(
120+
name,
121+
sparkSession,
122+
replace,
123+
catalog.getRawTempView(name.table),
124+
originalText,
125+
aliasedPlan,
126+
analyzedPlan)
137127
catalog.createTempView(name.table, tableDefinition, overrideIfExists = replace)
138128
} else if (viewType == GlobalTempView) {
139129
val db = sparkSession.sessionState.conf.getConf(StaticSQLConf.GLOBAL_TEMP_DATABASE)
140130
val viewIdent = TableIdentifier(name.table, Option(db))
141131
val aliasedPlan = aliasPlan(sparkSession, analyzedPlan)
142-
if (replace && needsToUncache(catalog.getRawGlobalTempView(name.table), aliasedPlan)) {
143-
logInfo(s"Try to uncache ${viewIdent.quotedString} before replacing.")
144-
checkCyclicViewReference(analyzedPlan, Seq(viewIdent), viewIdent)
145-
CommandUtils.uncacheTableOrView(sparkSession, viewIdent.quotedString)
146-
}
147-
val tableDefinition = if (!conf.storeAnalyzedPlanForView && originalText.nonEmpty) {
148-
TemporaryViewRelation(
149-
prepareTemporaryView(
150-
viewIdent,
151-
sparkSession,
152-
analyzedPlan,
153-
aliasedPlan.schema,
154-
originalText))
155-
} else {
156-
TemporaryViewRelation(
157-
prepareTemporaryViewFromDataFrame(name, aliasedPlan),
158-
Some(aliasedPlan))
159-
}
132+
val tableDefinition = createTemporaryViewRelation(
133+
viewIdent,
134+
sparkSession,
135+
replace,
136+
catalog.getRawGlobalTempView(name.table),
137+
originalText,
138+
aliasedPlan,
139+
analyzedPlan)
160140
catalog.createGlobalTempView(name.table, tableDefinition, overrideIfExists = replace)
161141
} else if (catalog.tableExists(name)) {
162142
val tableMetadata = catalog.getTableMetadata(name)
@@ -192,20 +172,6 @@ case class CreateViewCommand(
192172
Seq.empty[Row]
193173
}
194174

195-
/**
196-
* Checks if need to uncache the temp view being replaced.
197-
*/
198-
private def needsToUncache(
199-
rawTempView: Option[LogicalPlan],
200-
aliasedPlan: LogicalPlan): Boolean = rawTempView match {
201-
// The temp view doesn't exist, no need to uncache.
202-
case None => false
203-
// Do not need to uncache if the to-be-replaced temp view plan and the new plan are the
204-
// same-result plans.
205-
case Some(TemporaryViewRelation(_, Some(p))) => !p.sameResult(aliasedPlan)
206-
case Some(p) => !p.sameResult(aliasedPlan)
207-
}
208-
209175
/**
210176
* If `userSpecifiedColumns` is defined, alias the analyzed plan to the user specified columns,
211177
* else return the analyzed plan directly.
@@ -284,14 +250,21 @@ case class AlterViewAsCommand(
284250
}
285251

286252
private def alterTemporaryView(session: SparkSession, analyzedPlan: LogicalPlan): Unit = {
287-
val tableDefinition = if (conf.storeAnalyzedPlanForView) {
288-
analyzedPlan
253+
val catalog = session.sessionState.catalog
254+
val rawTempView = if (name.database.isEmpty) {
255+
catalog.getRawTempView(name.table)
289256
} else {
290-
checkCyclicViewReference(analyzedPlan, Seq(name), name)
291-
TemporaryViewRelation(
292-
prepareTemporaryView(
293-
name, session, analyzedPlan, analyzedPlan.schema, Some(originalText)))
257+
catalog.getRawGlobalTempView(name.table)
294258
}
259+
assert(rawTempView.isDefined)
260+
val tableDefinition = createTemporaryViewRelation(
261+
name,
262+
session,
263+
replace = false,
264+
rawTempView = rawTempView,
265+
originalText = Some(originalText),
266+
aliasedPlan = analyzedPlan,
267+
analyzedPlan = analyzedPlan)
295268
session.sessionState.catalog.alterTempViewDefinition(name, tableDefinition)
296269
}
297270

@@ -345,7 +318,7 @@ case class ShowViewsCommand(
345318
}
346319
}
347320

348-
object ViewHelper {
321+
object ViewHelper extends SQLConfHelper with Logging {
349322

350323
private val configPrefixDenyList = Seq(
351324
SQLConf.MAX_NESTED_VIEW_DEPTH.key,
@@ -592,19 +565,62 @@ object ViewHelper {
592565
(collectTempViews(child), collectTempFunctions(child))
593566
}
594567

568+
def createTemporaryViewRelation(
569+
name: TableIdentifier,
570+
session: SparkSession,
571+
replace: Boolean,
572+
rawTempView: Option[LogicalPlan],
573+
originalText: Option[String],
574+
aliasedPlan: LogicalPlan,
575+
analyzedPlan: LogicalPlan): TemporaryViewRelation = {
576+
val needsToUncache = needsToUncacheTempView(rawTempView, aliasedPlan)
577+
if (replace && needsToUncache) {
578+
logInfo(s"Try to uncache ${name.quotedString} before replacing.")
579+
checkCyclicViewReference(analyzedPlan, Seq(name), name)
580+
CommandUtils.uncacheTableOrView(session, name.quotedString)
581+
}
582+
if (!conf.storeAnalyzedPlanForView && originalText.nonEmpty) {
583+
TemporaryViewRelation(
584+
prepareTemporaryView(
585+
name,
586+
session,
587+
analyzedPlan,
588+
aliasedPlan.schema,
589+
originalText.get))
590+
} else {
591+
TemporaryViewRelation(
592+
prepareTemporaryViewFromDataFrame(name, aliasedPlan),
593+
Some(aliasedPlan))
594+
}
595+
}
596+
597+
/**
598+
* Checks if we need to uncache the temp view being replaced by checking if the raw temp
599+
* view will return the same result as the given aliased plan.
600+
*/
601+
private def needsToUncacheTempView(
602+
rawTempView: Option[LogicalPlan],
603+
aliasedPlan: LogicalPlan): Boolean = rawTempView match {
604+
// The temp view doesn't exist, no need to uncache.
605+
case None => false
606+
// Do not need to uncache if the to-be-replaced temp view plan and the new plan are the
607+
// same-result plans.
608+
case Some(TemporaryViewRelation(_, Some(p))) => !p.sameResult(aliasedPlan)
609+
case Some(p) => !p.sameResult(aliasedPlan)
610+
}
595611

596612
/**
597613
* Returns a [[CatalogTable]] that contains information for temporary view.
598614
* Generate the view-specific properties(e.g. view default database, view query output
599615
* column names) and store them as properties in the CatalogTable, and also creates
600616
* the proper schema for the view.
601617
*/
602-
def prepareTemporaryView(
618+
private def prepareTemporaryView(
603619
viewName: TableIdentifier,
604620
session: SparkSession,
605621
analyzedPlan: LogicalPlan,
606622
viewSchema: StructType,
607-
originalText: Option[String]): CatalogTable = {
623+
originalText: String): CatalogTable = {
608624

609625
val catalog = session.sessionState.catalog
610626
val (tempViews, tempFunctions) = collectTemporaryObjects(catalog, analyzedPlan)
@@ -618,15 +634,15 @@ object ViewHelper {
618634
tableType = CatalogTableType.VIEW,
619635
storage = CatalogStorageFormat.empty,
620636
schema = viewSchema,
621-
viewText = originalText,
637+
viewText = Some(originalText),
622638
properties = newProperties)
623639
}
624640

625641
/**
626642
* Returns a [[CatalogTable]] that contains information for the temporary view created
627643
* from a dataframe.
628644
*/
629-
def prepareTemporaryViewFromDataFrame(
645+
private def prepareTemporaryViewFromDataFrame(
630646
viewName: TableIdentifier,
631647
analyzedPlan: LogicalPlan): CatalogTable = {
632648
CatalogTable(

sql/core/src/test/scala/org/apache/spark/sql/execution/SQLViewSuite.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -909,4 +909,15 @@ abstract class SQLViewSuite extends QueryTest with SQLTestUtils {
909909
}
910910
}
911911
}
912+
913+
test("terry") {
914+
withTempView("v1") {
915+
sql("CREATE TEMPORARY VIEW tv1 AS SELECT 1")
916+
sql("CACHE TABLE tv1")
917+
assert(spark.catalog.isCached("tv1"))
918+
sql("ALTER VIEW tv1 as SELECT 2")
919+
assert(!spark.catalog.isCached("tv1"))
920+
sql("select * from tv1").show
921+
}
922+
}
912923
}

0 commit comments

Comments
 (0)