This is an automated email from the ASF dual-hosted git repository. wangzhen pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/kyuubi.git
The following commit(s) were added to refs/heads/master by this push: new 4c1412bdd0 [KYUUBI #7168] Adapt PermanentViewMarker introduced by authz plugin in lineage plugin 4c1412bdd0 is described below commit 4c1412bdd0674de37f45f60cc070f2a1ecadca09 Author: wforget <643348...@qq.com> AuthorDate: Wed Aug 13 16:58:44 2025 +0800 [KYUUBI #7168] Adapt PermanentViewMarker introduced by authz plugin in lineage plugin ### Why are the changes needed? Fix the lineage plugin cannot capture lineage of view after integrating authz plugin. closes #7168 ### How was this patch tested? added unit test ### Was this patch authored or co-authored using generative AI tooling? No Closes #7169 from wForget/KYUUBI-7168. Closes #7168 42ac01639 [wforget] fix test 208550a3e [wforget] [KYUUBI-7168] Adapt PermanentViewMarker introduced by authz plugin in lineage plugin Authored-by: wforget <643348...@qq.com> Signed-off-by: wforget <643348...@qq.com> --- extensions/spark/kyuubi-spark-authz/pom.xml | 6 +++++ .../authz/ranger/RangerSparkExtensionSuite.scala | 29 ++++++++++++++++++++++ .../helper/SparkSQLLineageParseHelper.scala | 7 ++++++ 3 files changed, 42 insertions(+) diff --git a/extensions/spark/kyuubi-spark-authz/pom.xml b/extensions/spark/kyuubi-spark-authz/pom.xml index fae03aca72..49c79d4964 100644 --- a/extensions/spark/kyuubi-spark-authz/pom.xml +++ b/extensions/spark/kyuubi-spark-authz/pom.xml @@ -391,6 +391,12 @@ <scope>test</scope> </dependency> + <dependency> + <groupId>org.apache.kyuubi</groupId> + <artifactId>kyuubi-spark-lineage_${scala.binary.version}</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> </dependencies> <build> diff --git a/extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/ranger/RangerSparkExtensionSuite.scala b/extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/ranger/RangerSparkExtensionSuite.scala index 4e8cddb68c..1fdea0ed96 100644 --- a/extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/ranger/RangerSparkExtensionSuite.scala +++ b/extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/ranger/RangerSparkExtensionSuite.scala @@ -37,6 +37,8 @@ import org.scalatest.BeforeAndAfterAll import org.scalatest.funsuite.AnyFunSuite import org.apache.kyuubi.Utils +import org.apache.kyuubi.plugin.lineage.Lineage +import org.apache.kyuubi.plugin.lineage.helper.SparkSQLLineageParseHelper import org.apache.kyuubi.plugin.spark.authz.{AccessControlException, SparkSessionProvider} import org.apache.kyuubi.plugin.spark.authz.MysqlContainerEnv import org.apache.kyuubi.plugin.spark.authz.RangerTestNamespace._ @@ -1513,4 +1515,31 @@ class HiveCatalogRangerSparkExtensionSuite extends RangerSparkExtensionSuite { } } } + + test("Test view lineage") { + def extractLineage(sql: String): Lineage = { + val parsed = spark.sessionState.sqlParser.parsePlan(sql) + val qe = spark.sessionState.executePlan(parsed) + val analyzed = qe.analyzed + SparkSQLLineageParseHelper(spark).transformToLineage(0, analyzed).get + } + + val db1 = defaultDb + val table1 = "table1" + val view1 = "view1" + withSingleCallEnabled { + withCleanTmpResources(Seq((s"$db1.$table1", "table"), (s"$db1.$view1", "view"))) { + doAs(admin, sql(s"CREATE TABLE IF NOT EXISTS $db1.$table1 (id int, scope int)")) + doAs(admin, sql(s"CREATE VIEW $db1.$view1 AS SELECT * FROM $db1.$table1")) + + val lineage = doAs( + admin, + extractLineage(s"SELECT id FROM $db1.$view1 WHERE id > 1")) + assert(lineage.inputTables.size == 1) + assert(lineage.inputTables.head === s"spark_catalog.$db1.$table1") + assert(lineage.columnLineage.size == 1) + assert(lineage.columnLineage.head.originalColumns.head === s"spark_catalog.$db1.$table1.id") + } + } + } } diff --git a/extensions/spark/kyuubi-spark-lineage/src/main/scala/org/apache/kyuubi/plugin/lineage/helper/SparkSQLLineageParseHelper.scala b/extensions/spark/kyuubi-spark-lineage/src/main/scala/org/apache/kyuubi/plugin/lineage/helper/SparkSQLLineageParseHelper.scala index effe2ae831..a6cb6934f6 100644 --- a/extensions/spark/kyuubi-spark-lineage/src/main/scala/org/apache/kyuubi/plugin/lineage/helper/SparkSQLLineageParseHelper.scala +++ b/extensions/spark/kyuubi-spark-lineage/src/main/scala/org/apache/kyuubi/plugin/lineage/helper/SparkSQLLineageParseHelper.scala @@ -448,6 +448,13 @@ trait LineageParser { }) } + // PermanentViewMarker is introduced by kyuubi authz plugin, which is a wrapper of View, + // so we just extract the columns lineage from its inner children (original view) + case pvm if pvm.nodeName == "PermanentViewMarker" => + pvm.innerChildren.asInstanceOf[Seq[LogicalPlan]] + .map(extractColumnsLineage(_, parentColumnsLineage)) + .reduce(mergeColumnsLineage) + case p: View => if (!p.isTempView && SparkContextHelper.getConf( LineageConf.SKIP_PARSING_PERMANENT_VIEW_ENABLED)) {