2017-08-13 60 views
4

我使用Spark Catalyst來表示openCypher查詢引擎ingraph的查詢計劃。在查詢計劃過程中,我想從某個邏輯計劃(Plan1)轉換爲另一個邏輯計劃(Plan2)。 (我試圖保持簡單的問題,所以我省略了一些細節,因爲這個項目完全是開源的,所以如果需要的話,我很樂意提供關於why this is necessary的更多信息。)將Spark邏輯計劃轉換爲Spark Catalyst中的另一個邏輯計劃

我能找到的最好方法是遞歸使用transformDown。下面是一個小例子,它將Plan1Node s轉換爲Plan2Node s,方法是將替換爲OpA1,將OpB1替換爲OpB2

import org.apache.spark.sql.catalyst.expressions.Attribute 
import org.apache.spark.sql.catalyst.plans.logical.{LeafNode, LogicalPlan, UnaryNode} 

trait Plan1Node extends LogicalPlan 

case class OpA1() extends LeafNode with Plan1Node { 
    override def output: Seq[Attribute] = Seq() 
} 
case class OpB1(child: Plan1Node) extends UnaryNode with Plan1Node { 
    override def output: Seq[Attribute] = Seq() 
} 

trait Plan2Node extends LogicalPlan 

case class OpA2() extends LeafNode with Plan2Node { 
    override def output: Seq[Attribute] = Seq() 
} 
case class OpB2(child: Plan2Node) extends UnaryNode with Plan2Node { 
    override def output: Seq[Attribute] = Seq() 
} 

object Plan1ToPlan2 { 
    def transform(plan: Plan1Node): Plan2Node = { 
    plan.transformDown { 
     case OpA1() => OpA2() 
     case OpB1(child) => OpB2(transform(child)) 
    } 
    }.asInstanceOf[Plan2Node] 
} 

這種方法完成這項工作。此代碼:

val p1 = OpB1(OpA1()) 
val p2 = Plan1ToPlan2.transform(p1) 

結果:

p1: OpB1 = OpB1 
+- OpA1 

p2: Plan2Node = OpB2 
+- OpA2 

但是,使用asInstanceOf[Plan2Node]絕對是代碼難聞的氣味。我考慮使用Strategy來定義轉換規則,但該類是用於從物理轉換爲邏輯計劃。

有沒有更好的方法來定義邏輯計劃之間的轉換?或者正在使用被認爲是反模式的多個邏輯計劃?

回答

0

(回答我的問題。)

更改transformDown到一個簡單的模式匹配(match)和遞歸調用解決了此類問題:

object Plan1ToPlan2 { 
    def transform(plan: Plan1Node): Plan2Node = { 
    plan match { 
     case OpA1() => OpA2() 
     case OpB1(child) => OpB2(transform(child)) 
    } 
    } 
} 

這似乎是一種安全的,(基於我對Catalyst的有限理解)慣用的解決方案。