This is an automated email from the ASF dual-hosted git repository.
JingsongLi 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 043c341502 [iceberg] Fix table type when committing iceberg metadata
to Hive (#7770)
043c341502 is described below
commit 043c341502738238ebe957972acc2f991d0b4741
Author: Arnav Balyan <[email protected]>
AuthorDate: Thu May 7 15:35:56 2026 +0530
[iceberg] Fix table type when committing iceberg metadata to Hive (#7770)
- Hive entry for iceberg table stays as `table_type = PAIMON` after
iceberg metadata is committed.
- Iceberg's `SparkSessionCatalog` only loads tables where `table_type =
ICEBERG`, so Spark falls back to the Hive serde path and skips partition
prune.
- Ensure table type can be updated to follow Iceberg when committed
through IcebergHiveMetadataCommitter.
---
.../iceberg/IcebergHiveMetadataCommitter.java | 4 ++
.../IcebergHiveMetadataCommitterITCaseBase.java | 47 ++++++++++++++++++++++
2 files changed, 51 insertions(+)
diff --git
a/paimon-hive/paimon-hive-catalog/src/main/java/org/apache/paimon/iceberg/IcebergHiveMetadataCommitter.java
b/paimon-hive/paimon-hive-catalog/src/main/java/org/apache/paimon/iceberg/IcebergHiveMetadataCommitter.java
index 37ce56a140..6d0554c8cc 100644
---
a/paimon-hive/paimon-hive-catalog/src/main/java/org/apache/paimon/iceberg/IcebergHiveMetadataCommitter.java
+++
b/paimon-hive/paimon-hive-catalog/src/main/java/org/apache/paimon/iceberg/IcebergHiveMetadataCommitter.java
@@ -161,6 +161,10 @@ public class IcebergHiveMetadataCommitter implements
IcebergMetadataCommitter {
hiveTable = createTable(databaseName, tableName, newMetadataPath);
}
+ // Iceberg readers (e.g. iceberg.spark.SparkSessionCatalog) only load
tables where
+ // table_type=ICEBERG, so stamp it on every commit, existing entries
created by Paimon's
+ // HiveCatalog as table_type=PAIMON are migrated here.
+ hiveTable.getParameters().put("table_type", "ICEBERG");
hiveTable.getParameters().put("metadata_location",
newMetadataPath.toString());
if (baseMetadataPath != null) {
hiveTable
diff --git
a/paimon-hive/paimon-hive-connector-common/src/test/java/org/apache/paimon/iceberg/IcebergHiveMetadataCommitterITCaseBase.java
b/paimon-hive/paimon-hive-connector-common/src/test/java/org/apache/paimon/iceberg/IcebergHiveMetadataCommitterITCaseBase.java
index 7278f6f9b1..765018109b 100644
---
a/paimon-hive/paimon-hive-connector-common/src/test/java/org/apache/paimon/iceberg/IcebergHiveMetadataCommitterITCaseBase.java
+++
b/paimon-hive/paimon-hive-connector-common/src/test/java/org/apache/paimon/iceberg/IcebergHiveMetadataCommitterITCaseBase.java
@@ -321,6 +321,53 @@ public abstract class
IcebergHiveMetadataCommitterITCaseBase {
"SELECT * FROM my_iceberg.iceberg_db2.t2 ORDER
BY pt, id")));
}
+ /**
+ * Verifies that when a Paimon table is created via Paimon's HiveCatalog
with Iceberg
+ * compatibility enabled, the resulting Hive entry has {@code
table_type=ICEBERG} after the
+ * first commit so Iceberg readers can recognize it and partition-prune
correctly.
+ */
+ @Test
+ public void testIcebergCommitSetsHiveTableTypeToIceberg() throws Exception
{
+ TableEnvironment tEnv =
+ TableEnvironmentImpl.create(
+
EnvironmentSettings.newInstance().inBatchMode().build());
+ tEnv.executeSql(
+ "CREATE CATALOG my_paimon_hive WITH ( 'type' = 'paimon',
'metastore' = 'hive', "
+ + "'uri' = '', 'warehouse' = '"
+ + path
+ + "' )");
+ tEnv.executeSql("CREATE DATABASE my_paimon_hive.test_db");
+ tEnv.executeSql(
+ "CREATE TABLE my_paimon_hive.test_db.t ( pt INT, id INT, data
STRING ) "
+ + "PARTITIONED BY (pt) WITH "
+ + "( 'metadata.iceberg.storage' = 'hive-catalog', "
+ + " 'metadata.iceberg.uri' = '', 'file.format' =
'avro' )");
+ tEnv.executeSql(
+ "INSERT INTO my_paimon_hive.test_db.t VALUES "
+ + "(1, 1, 'apple'), (1, 2, 'pear'), "
+ + "(2, 1, 'cat'), (2, 2, 'dog')")
+ .await();
+
+ List<String> tblPropRows = hiveShell.executeQuery("SHOW TBLPROPERTIES
test_db.t");
+ String tableTypeRow =
+ tblPropRows.stream()
+ .filter(r -> r.toLowerCase().startsWith("table_type"))
+ .findFirst()
+ .orElse("(table_type row missing)");
+ boolean metadataLocationPresent =
+ tblPropRows.stream().anyMatch(r ->
r.toLowerCase().startsWith("metadata_location"));
+ assertTrue(
+ metadataLocationPresent,
+ "metadata_location must be written on commit; rows=" +
tblPropRows);
+ assertTrue(
+ tableTypeRow.toUpperCase().contains("ICEBERG"),
+ "Expected table_type=ICEBERG so Iceberg readers can load the
table; "
+ + "got row: '"
+ + tableTypeRow
+ + "'; full props: "
+ + tblPropRows);
+ }
+
@Test
public void testCustomMetastoreClass() {
TableEnvironment tEnv =