如何将spark.sql查询中引用为table的所有出现的表名替换为另一个?

问题描述 投票:0回答:1

例如,我有一个 SQL 查询

SELECT id, "delta.`/example/table/path`" FROM delta.`/example/table/path` WHERE str LIKE "%delta.`/example/table/path`"

我怎样才能只替换出现的

FROM delta.`/example/table/path`

FROM new_table_name

沿着逻辑计划树

lp
生成

val plan = spark.sessionState.sqlParser.parsePlan(query)
var lp = spark.sessionState.analyzer
    .executeAndCheck(plan, new QueryPlanningTracker)

我知道所有表格都由

LogicalRelation
节点表示,从那里,我失去了方向。

    Project [ID#1619]
    +- Join Inner, (fk#1620 = ID#1643)
       :- SubqueryAlias T1
       :  +- SubqueryAlias spark_catalog.delta.`T1`
       :     +- Relation [ID#1619,fk#1620] parquet
       +- SubqueryAlias T2
          +- SubqueryAlias spark_catalog.delta.`T2`
         +- Relation [ID#1643,amount#1644,cost#1645] parquet

有人对我如何只替换表名有建议吗? 预先感谢您!

我尝试通过沿着树走来检索所有表名

def getTableNamesOnlyWrapper(root: LogicalPlan): Set[String] = {
    var nameSet: Set[String] = Set()
    def getTableNamesOnly(root: LogicalPlan, prevAlias: String): Unit = {
      root match {
        case a: SubqueryAlias => {
          getTableNamesOnly(a.child, a.alias)
        }
        case r: LogicalRelation => {
          val name = r.catalogTable.map(_.identifier.unquotedString).getOrElse(prevAlias)
          nameSet += name
        } 
        case p: LogicalPlan =>
          for (c <- p.children) {
            getTableNamesOnly(c, prevAlias)
          }
      }
    }
    getTableNamesOnly(root, "")
    println("kebing name set is: " + nameSet)
    nameSet
  }

然后匹配原SQL中的表,替换为

new_table_name
。但是,这不能处理相同表名显示为字符串文字的情况。

SELECT id, "delta.`/example/table/path`" FROM delta.`/example/table/path` WHERE str LIKE "%delta.`/example/table/path`"
string scala apache-spark
1个回答
0
投票

字符串文字显示为 Literal 表达式的实例。

在模式匹配中,您可以使用 StringLiteral 来简化。

Spark 计划中有许多结构组合,这些组合不容易预测,并且在每个版本中可能会发生变化。 要导航/更改内容,您应该更喜欢 QueryPlan/TreeNode 上的内置操作(对于文字而言,transformAllExpressionsWithSubqueries 似乎合适,而 transformWithSubqueries 则可以换行)。

通常最好查看源代码以获取转换示例,查询优化非常适合这种洞察力,CTESubstitution对于处理 cte、子查询、别名等看起来非常完整。

© www.soinside.com 2019 - 2024. All rights reserved.