This is an automated email from the ASF dual-hosted git repository.

lzljs3620320 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git


The following commit(s) were added to refs/heads/master by this push:
     new 409dd85e51 [spark] Fix view query failure with VARCHAR/CHAR column 
types (#7585)
409dd85e51 is described below

commit 409dd85e51065496301aa3db55babf72de250368
Author: Zouxxyy <[email protected]>
AuthorDate: Thu Apr 2 21:52:18 2026 +0800

    [spark] Fix view query failure with VARCHAR/CHAR column types (#7585)
    
    Fix querying Paimon View fails with "Cannot up cast from STRING to
    VARCHAR(n)" when the underlying table has VARCHAR or CHAR columns.
    
    Spark replaces CharType/VarcharType with StringType during V2 table
    resolution, but the view schema still preserves the original types. This
    causes UpCast(StringType → VarcharType(n)) to fail. The fix uses
    CharVarcharUtils.replaceCharVarcharWithStringInSchema to normalize the
    view schema before applying UpCast.
---
 .../catalyst/analysis/PaimonViewResolver.scala     |  9 +++-
 .../paimon/spark/sql/PaimonViewTestBase.scala      | 48 ++++++++++++++++++++++
 2 files changed, 56 insertions(+), 1 deletion(-)

diff --git 
a/paimon-spark/paimon-spark-common/src/main/scala/org/apache/paimon/spark/catalyst/analysis/PaimonViewResolver.scala
 
b/paimon-spark/paimon-spark-common/src/main/scala/org/apache/paimon/spark/catalyst/analysis/PaimonViewResolver.scala
index b45463e916..95b8ab6e18 100644
--- 
a/paimon-spark/paimon-spark-common/src/main/scala/org/apache/paimon/spark/catalyst/analysis/PaimonViewResolver.scala
+++ 
b/paimon-spark/paimon-spark-common/src/main/scala/org/apache/paimon/spark/catalyst/analysis/PaimonViewResolver.scala
@@ -30,6 +30,7 @@ import org.apache.spark.sql.catalyst.parser.ParseException
 import org.apache.spark.sql.catalyst.parser.extensions.{CurrentOrigin, Origin}
 import org.apache.spark.sql.catalyst.plans.logical.{LeafNode, LogicalPlan, 
Project, SubqueryAlias}
 import org.apache.spark.sql.catalyst.rules.Rule
+import org.apache.spark.sql.catalyst.util.CharVarcharUtils
 import org.apache.spark.sql.connector.catalog.{Identifier, PaimonLookupCatalog}
 
 case class PaimonViewResolver(spark: SparkSession)
@@ -66,7 +67,13 @@ case class PaimonViewResolver(spark: SparkSession)
     val earlyRules = Seq(CTESubstitution, SubstituteUnresolvedOrdinals)
     val rewritten = earlyRules.foldLeft(parsedPlan)((plan, rule) => 
rule.apply(plan))
 
-    val aliases = 
SparkTypeUtils.fromPaimonRowType(view.rowType()).fields.zipWithIndex.map {
+    // Spark internally replaces CharType/VarcharType with StringType during 
V2 table resolution,
+    // so the view's schema must also use StringType to avoid UpCast failures
+    // (e.g., "Cannot up cast from STRING to VARCHAR(50)").
+    val viewSchema = CharVarcharUtils.replaceCharVarcharWithStringInSchema(
+      SparkTypeUtils.fromPaimonRowType(view.rowType()))
+
+    val aliases = viewSchema.fields.zipWithIndex.map {
       case (expected, pos) =>
         val attr = GetColumnByOrdinal(pos, expected.dataType)
         Alias(UpCast(attr, expected.dataType), expected.name)(explicitMetadata 
=
diff --git 
a/paimon-spark/paimon-spark-ut/src/test/scala/org/apache/paimon/spark/sql/PaimonViewTestBase.scala
 
b/paimon-spark/paimon-spark-ut/src/test/scala/org/apache/paimon/spark/sql/PaimonViewTestBase.scala
index 7c503d98a5..a0c29bfcbc 100644
--- 
a/paimon-spark/paimon-spark-ut/src/test/scala/org/apache/paimon/spark/sql/PaimonViewTestBase.scala
+++ 
b/paimon-spark/paimon-spark-ut/src/test/scala/org/apache/paimon/spark/sql/PaimonViewTestBase.scala
@@ -242,4 +242,52 @@ abstract class PaimonViewTestBase extends 
PaimonHiveTestBase {
         }
     }
   }
+
+  test("Paimon View: create view on table with VARCHAR columns") {
+    Seq(sparkCatalogName, paimonHiveCatalogName).foreach {
+      catalogName =>
+        sql(s"USE $catalogName")
+        withDatabase("test_db") {
+          sql("CREATE DATABASE test_db")
+          sql("USE test_db")
+          withTable("t") {
+            withView("v1") {
+              sql("CREATE TABLE t (id INT, name VARCHAR(50), country STRING) 
USING paimon")
+              sql("INSERT INTO t VALUES (1, 'alice', 'beijing'), (2, 'bob', 
'shanghai')")
+              sql("CREATE VIEW v1 AS SELECT * FROM t")
+              checkAnswer(
+                sql("SELECT * FROM v1"),
+                Seq(Row(1, "alice", "beijing"), Row(2, "bob", "shanghai")))
+            }
+          }
+        }
+    }
+  }
+
+  test("Paimon View: create view on table with nested VARCHAR and CHAR 
columns") {
+    Seq(sparkCatalogName, paimonHiveCatalogName).foreach {
+      catalogName =>
+        sql(s"USE $catalogName")
+        withDatabase("test_db") {
+          sql("CREATE DATABASE test_db")
+          sql("USE test_db")
+          withTable("t") {
+            withView("v1") {
+              sql("""CREATE TABLE t (
+                    |  id INT,
+                    |  tags ARRAY<VARCHAR(100)>,
+                    |  props MAP<STRING, VARCHAR(200)>
+                    |) USING paimon""".stripMargin)
+              sql("""INSERT INTO t VALUES
+                    |  (1, ARRAY('a', 'b'), MAP('k1', 'v1')),
+                    |  (2, ARRAY('c'), MAP('k2', 'v2'))""".stripMargin)
+              sql("CREATE VIEW v1 AS SELECT * FROM t")
+              checkAnswer(
+                sql("SELECT * FROM v1"),
+                Seq(Row(1, Seq("a", "b"), Map("k1" -> "v1")), Row(2, Seq("c"), 
Map("k2" -> "v2"))))
+            }
+          }
+        }
+    }
+  }
 }

Reply via email to