@@ -32,7 +32,7 @@ import org.apache.spark.{SparkEnv, SparkException, SparkSQLException}
32
32
import org .apache .spark .api .python .PythonFunction .PythonAccumulator
33
33
import org .apache .spark .connect .proto
34
34
import org .apache .spark .internal .{Logging , LogKeys , MDC }
35
- import org .apache .spark .sql .DataFrame
35
+ import org .apache .spark .sql .{ DataFrame , Dataset }
36
36
import org .apache .spark .sql .SparkSession
37
37
import org .apache .spark .sql .catalyst .plans .logical .LogicalPlan
38
38
import org .apache .spark .sql .connect .common .InvalidPlanInput
@@ -450,14 +450,14 @@ case class SessionHolder(userId: String, sessionId: String, session: SparkSessio
450
450
*/
451
451
private [connect] def usePlanCache (rel : proto.Relation , cachePlan : Boolean )(
452
452
transform : proto.Relation => LogicalPlan ): LogicalPlan = {
453
- val planCacheEnabled = Option (session)
454
- .forall(_.sessionState.conf.getConf(Connect .CONNECT_SESSION_PLAN_CACHE_ENABLED , true ))
455
453
// We only cache plans that have a plan ID.
456
- val hasPlanId = rel.hasCommon && rel.getCommon.hasPlanId
454
+ val planCacheEnabled = rel.hasCommon && rel.getCommon.hasPlanId &&
455
+ Option (session)
456
+ .forall(_.sessionState.conf.getConf(Connect .CONNECT_SESSION_PLAN_CACHE_ENABLED , true ))
457
457
458
458
def getPlanCache (rel : proto.Relation ): Option [LogicalPlan ] =
459
459
planCache match {
460
- case Some (cache) if planCacheEnabled && hasPlanId =>
460
+ case Some (cache) if planCacheEnabled =>
461
461
Option (cache.getIfPresent(rel)) match {
462
462
case Some (plan) =>
463
463
logDebug(s " Using cached plan for relation ' $rel': $plan" )
@@ -466,20 +466,34 @@ case class SessionHolder(userId: String, sessionId: String, session: SparkSessio
466
466
}
467
467
case _ => None
468
468
}
469
- def putPlanCache (rel : proto.Relation , plan : LogicalPlan ): Unit =
469
+ def putPlanCache (rel : proto.Relation , plan : LogicalPlan ): LogicalPlan =
470
470
planCache match {
471
- case Some (cache) if planCacheEnabled && hasPlanId =>
472
- cache.put(rel, plan)
473
- case _ =>
471
+ case Some (cache) if planCacheEnabled =>
472
+ val analyzedPlan = if (plan.analyzed) {
473
+ plan
474
+ } else {
475
+ val qe = Dataset .ofRows(session, plan).queryExecution
476
+ if (qe.isLazyAnalysis) {
477
+ // The plan is intended to be lazily analyzed.
478
+ plan
479
+ } else {
480
+ // Make sure that the plan is fully analyzed before being cached.
481
+ qe.analyzed
482
+ }
483
+ }
484
+ cache.put(rel, analyzedPlan)
485
+ analyzedPlan
486
+ case _ => plan
474
487
}
475
488
476
489
getPlanCache(rel)
477
490
.getOrElse({
478
491
val plan = transform(rel)
479
492
if (cachePlan) {
480
493
putPlanCache(rel, plan)
494
+ } else {
495
+ plan
481
496
}
482
- plan
483
497
})
484
498
}
485
499
0 commit comments