You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hudi.apache.org by vh...@apache.org on 2026/06/04 06:43:17 UTC

(hudi) tag rfc-105-pre-cleanup created (now 045170cc2542)

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

voonhous pushed a change to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git


      at 045170cc2542 (commit)
This tag includes the following new commits:

     new 72b78687d6ba feat(trino): wire hudi-trino-plugin and bundle for RFC-105 shim split
     new 89782db0e343 docs(trino): add hudi-trino-plugin README with build and IDE setup
     new 91a7324929e5 fix: Append Only Required Hudi Meta Fields for MOR Tables
     new edeaad573343 test: disable resolve column name casing by default
     new a775758e87b1 chore: Bump hudi-trino-plugin to 1.1.0
     new 7ed8b07983ad docs(trino): add hudi-trino-bundle README covering build and consume flow
     new 2b67d23daea8 fix(trino): port hudi-trino-plugin to Hudi 1.3 HoodieSchema APIs
     new 36fc2b93f110 chore(trino): bump trino.connector.version to 480
     new 77b10f539814 fix(trino): port hudi-trino-plugin to Trino 480 and slim bundle deps
     new 83b236f43305 refactor(trino): drop shaded bundle, publish hudi-trino per RFC-105
     new 64baf5d23665 fix(trino): port hudi-trino to Trino 482 SPI and restore metadata table fallback
     new f251d1e019ce fix(trino): drop stale partition-column injection for count(*) projections
     new 046a4c5b1880 chore(trino): trim porting-history comments and verbose pom rationale
     new da0664709b84 fix(trino): drop ./mvnw wrapper from Trino CI workflows
     new 664e9f11299e fix(trino): pin to released Trino 481 and gate test-jars behind a profile
     new aff98c018a1a fix(trino): two-stage build under JDK 17 + JDK 25 in Trino workflows
     new 20034a3e5f11 fix(trino): use :artifactId form for -pl in two-stage workflows
     new db35c3793fdd fix(trino): gate hudi-client-common/hadoop-common/java-client behind test profile
     new 8a84c553f3de ci(trino): consolidate build + test in hudi_trino_ci, drop stale bot.yml job
     new 2d5088f3d09e fix(trino): port connector tests off removed Trino 481 APIs
     new b13ae80dc817 fix(trino): pin junit-platform to keep it aligned with jupiter 5.14.1
     new a0bb1a57b574 fix(trino): add junit-platform-launcher as explicit test dep to fix surefire
     new b47c851a6044 fix(trino): pin Jackson to 2.21.3 so Trino's airlift APIs resolve at runtime
     new d6080d254251 fix(trino): pin Jetty to 12.1.9 to unblock TestingTrinoServer startup
     new b714a5b74b9e fix(trino): add jdk.incubator.vector to surefire argLine
     new b4f82bf7327b fix(trino): exclude log4j-slf4j-impl from trino-filesystem-manager
     new c89c199ccf2e fix(trino): pin Jersey to 4.0.2 to match Trino's jakarta stack
     new 19f67bd4ece4 fix(trino): share file metastore between hive and hudi in TestHudiSharedMetastore
     new 932806b84f0e fix(trino): pin joda-time to 2.14.2 to unblock DateTimeZoneIndex clinit
     new e106b48dc2df test(trino): mark LIMIT pushdown unsupported and disable stale file-op count tests
     new 0e58d4b79984 todo(trino): mark LIMIT pushdown as a follow-up
     new a37e4548f3ba feat(trino): apply LIMIT pushdown into HudiTableHandle
     new fed1d02718e2 docs(trino): update SUPPORTS_LIMIT_PUSHDOWN comment after applyLimit lands
     new 3418cf277cfb test(trino): recalibrate file-op counts and re-enable disabled tests
     new 8fa5aba2f547 chore(trino): drop trino docker modules and bundle references
     new 045170cc2542 fix(integ): drop stale trino-coordinator-1 / trinobase refs after module removal

The 36 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(hudi) 02/36: docs(trino): add hudi-trino-plugin README with build and IDE setup

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit 89782db0e343862146576b99aae65bd4583d7c60
Author: voon <vo...@gmail.com>
AuthorDate: Fri May 22 16:18:35 2026 +0800

    docs(trino): add hudi-trino-plugin README with build and IDE setup
    
    Documents the -Phudi-trino activation and a per-module JDK 25 override
    for hudi-trino-plugin so contributors do not have to toggle the project
    SDK when working across modules.
---
 hudi-trino-plugin/README.md | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/hudi-trino-plugin/README.md b/hudi-trino-plugin/README.md
new file mode 100644
index 000000000000..4a9aba1403db
--- /dev/null
+++ b/hudi-trino-plugin/README.md
@@ -0,0 +1,24 @@
+# hudi-trino-plugin
+
+Hudi connector for Trino (RFC-105). Published as part of `org.apache.hudi:hudi-trino-bundle`; the Trino-side `HudiPlugin` shim loads classes from that bundle.
+
+## Build
+
+Excluded from default builds. Activate the `hudi-trino` Maven profile:
+
+```
+mvn -Phudi-trino -pl hudi-trino-plugin,packaging/hudi-trino-bundle -am install
+```
+
+Requires JDK 25 (enforced via `maven-enforcer-plugin`).
+
+## IDE setup
+
+Only `hudi-trino-plugin` needs JDK 25. Leave the rest of Hudi on its native JDK (11 or 17) so you are not toggling the project default.
+
+1. Activate the `hudi-trino` Maven profile so the IDE picks up the module.
+   - IntelliJ: Maven tool window, Profiles, tick `hudi-trino`.
+2. Override the SDK for the `hudi-trino-plugin` module only, to Temurin 25 with Language level 25.
+   - IntelliJ: `File > Project Structure > Modules > hudi-trino-plugin > Dependencies > Module SDK`.
+
+The enforcer rule only runs during `mvn`, not during the IDE's incremental compile.
\ No newline at end of file


(hudi) 29/36: fix(trino): pin joda-time to 2.14.2 to unblock DateTimeZoneIndex clinit

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit 932806b84f0e47e93a0d1949e958a353788ac3ba
Author: voon <vo...@gmail.com>
AuthorDate: Wed May 27 16:39:47 2026 +0800

    fix(trino): pin joda-time to 2.14.2 to unblock DateTimeZoneIndex clinit
    
    Hudi parent pins joda-time at 2.9.9 (released 2016). Trino's
    io.trino.util.DateTimeZoneIndex statically initializes a table of
    DateTimeZone instances by name, and the 2.9.9 tzdb does not contain all
    the IDs the modern Trino code path requests, so the class fails its
    <clinit>.
    
    Override joda-time to 2.14.2 (matches the airbase BOM) in plugin
    dependencyManagement.
---
 hudi-trino-plugin/pom.xml | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/hudi-trino-plugin/pom.xml b/hudi-trino-plugin/pom.xml
index 46c594359aba..c1f85550e7c6 100644
--- a/hudi-trino-plugin/pom.xml
+++ b/hudi-trino-plugin/pom.xml
@@ -85,6 +85,13 @@
                 <artifactId>jetty-server</artifactId>
                 <version>12.1.9</version>
             </dependency>
+            <!-- Hudi parent pins joda-time at 2.9.9 (from 2016). Trino's DateTimeZoneIndex
+                 clinit needs the newer time-zone names in 2.14.2 (matches airbase). -->
+            <dependency>
+                <groupId>joda-time</groupId>
+                <artifactId>joda-time</artifactId>
+                <version>2.14.2</version>
+            </dependency>
             <!-- Hudi parent pins jersey-server at 2.17 (legacy javax). Trino runs on Jersey 4.x
                  (jakarta). The mixed-version classpath crashes with NoSuchFieldError on
                  ComponentBag.INCLUDE_ALL during ResourceConfig init. -->


(hudi) 35/36: chore(trino): drop trino docker modules and bundle references

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit 8fa5aba2f54783493bf7c4983834c9fab803eb08
Author: voon <vo...@gmail.com>
AuthorDate: Thu May 28 19:14:41 2026 +0800

    chore(trino): drop trino docker modules and bundle references
    
    The integ-test docker images hudi-hadoop-trinobase-docker /
    hudi-hadoop-trinocoordinator-docker / hudi-hadoop-trinoworker-docker
    copied packaging/hudi-trino-bundle/target/hudi-trino-bundle-*.jar into a
    Trino plugin directory. The bundle was removed per RFC-105 (connector
    ships as the regular non-shaded hudi-trino artifact, consumed from the
    Trino-side shim), so the antrun copy step crashes when the
    integration-tests profile is activated.
    
    Removes the three docker module directories, unregisters them in
    docker/hoodie/hadoop/pom.xml, drops the trino services from the amd64
    and arm64 docker-compose files, and removes the now-dead
    hudi-trino-bundle entries from the azure pipeline ignore list and the
    release bundle validation script.
    
    Any docker-based Trino integ test setup belongs with the Trino-side
    connector going forward.
---
 azure-pipelines-20230430.yml                       |   1 -
 ...r-compose_hadoop284_hive2310_spark353_amd64.yml |  30 ------
 ...r-compose_hadoop284_hive2310_spark353_arm64.yml |  28 -----
 docker/hoodie/hadoop/pom.xml                       |   3 -
 docker/hoodie/hadoop/trinobase/Dockerfile          |  67 ------------
 docker/hoodie/hadoop/trinobase/pom.xml             | 116 ---------------------
 docker/hoodie/hadoop/trinobase/scripts/trino.sh    |  25 -----
 docker/hoodie/hadoop/trinocoordinator/Dockerfile   |  29 ------
 .../trinocoordinator/etc/catalog/hive.properties   |  22 ----
 .../hadoop/trinocoordinator/etc/config.properties  |  26 -----
 .../hoodie/hadoop/trinocoordinator/etc/jvm.config  |  27 -----
 .../hadoop/trinocoordinator/etc/log.properties     |  19 ----
 .../hadoop/trinocoordinator/etc/node.properties    |  21 ----
 docker/hoodie/hadoop/trinocoordinator/pom.xml      |  96 -----------------
 docker/hoodie/hadoop/trinoworker/Dockerfile        |  29 ------
 .../hadoop/trinoworker/etc/catalog/hive.properties |  22 ----
 .../hadoop/trinoworker/etc/config.properties       |  24 -----
 docker/hoodie/hadoop/trinoworker/etc/jvm.config    |  27 -----
 .../hoodie/hadoop/trinoworker/etc/log.properties   |  19 ----
 .../hoodie/hadoop/trinoworker/etc/node.properties  |  21 ----
 docker/hoodie/hadoop/trinoworker/pom.xml           |  96 -----------------
 scripts/release/validate_staged_bundles.sh         |   2 +-
 22 files changed, 1 insertion(+), 749 deletions(-)

diff --git a/azure-pipelines-20230430.yml b/azure-pipelines-20230430.yml
index 3edac6046b1a..0574bfa6704c 100644
--- a/azure-pipelines-20230430.yml
+++ b/azure-pipelines-20230430.yml
@@ -97,7 +97,6 @@ parameters:
       - '!packaging/hudi-presto-bundle'
       - '!packaging/hudi-spark-bundle'
       - '!packaging/hudi-timeline-server-bundle'
-      - '!packaging/hudi-trino-bundle'
       - '!packaging/hudi-utilities-slim-bundle'
 
 variables:
diff --git a/docker/compose/docker-compose_hadoop284_hive2310_spark353_amd64.yml b/docker/compose/docker-compose_hadoop284_hive2310_spark353_amd64.yml
index 1d84417b378a..6e7c3c778e77 100644
--- a/docker/compose/docker-compose_hadoop284_hive2310_spark353_amd64.yml
+++ b/docker/compose/docker-compose_hadoop284_hive2310_spark353_amd64.yml
@@ -228,36 +228,6 @@ services:
       - ${HUDI_WS}:/var/hoodie/ws
     command: worker
 
-  trino-coordinator-1:
-    container_name: trino-coordinator-1
-    hostname: trino-coordinator-1
-    image: apachehudi/hudi-hadoop_2.8.4-trinocoordinator_368:latest
-    platform: linux/amd64
-    ports:
-      - "8091:8091"
-    links:
-      - "hivemetastore"
-    volumes:
-      - ${HUDI_WS}:/var/hoodie/ws
-    command: http://trino-coordinator-1:8091 trino-coordinator-1
-
-  trino-worker-1:
-    container_name: trino-worker-1
-    hostname: trino-worker-1
-    image: apachehudi/hudi-hadoop_2.8.4-trinoworker_368:latest
-    platform: linux/amd64
-    depends_on: [ "trino-coordinator-1" ]
-    ports:
-      - "8092:8092"
-    links:
-      - "hivemetastore"
-      - "hiveserver"
-      - "hive-metastore-postgresql"
-      - "namenode"
-    volumes:
-      - ${HUDI_WS}:/var/hoodie/ws
-    command: http://trino-coordinator-1:8091 trino-worker-1
-
   graphite:
     container_name: graphite
     hostname: graphite
diff --git a/docker/compose/docker-compose_hadoop284_hive2310_spark353_arm64.yml b/docker/compose/docker-compose_hadoop284_hive2310_spark353_arm64.yml
index b995859c8022..678bc33f0449 100644
--- a/docker/compose/docker-compose_hadoop284_hive2310_spark353_arm64.yml
+++ b/docker/compose/docker-compose_hadoop284_hive2310_spark353_arm64.yml
@@ -219,34 +219,6 @@ services:
       - ${HUDI_WS}:/var/hoodie/ws
     command: worker
 
-  trino-coordinator-1:
-    container_name: trino-coordinator-1
-    hostname: trino-coordinator-1
-    image: apachehudi/hudi-hadoop_2.8.4-trinocoordinator_368:latest
-    ports:
-      - "8091:8091"
-    links:
-      - "hivemetastore"
-    volumes:
-      - ${HUDI_WS}:/var/hoodie/ws
-    command: http://trino-coordinator-1:8091 trino-coordinator-1
-
-  trino-worker-1:
-    container_name: trino-worker-1
-    hostname: trino-worker-1
-    image: apachehudi/hudi-hadoop_2.8.4-trinoworker_368:latest
-    depends_on: [ "trino-coordinator-1" ]
-    ports:
-      - "8092:8092"
-    links:
-      - "hivemetastore"
-      - "hiveserver"
-      - "hive-metastore-postgresql"
-      - "namenode"
-    volumes:
-      - ${HUDI_WS}:/var/hoodie/ws
-    command: http://trino-coordinator-1:8091 trino-worker-1
-
   graphite:
     container_name: graphite
     hostname: graphite
diff --git a/docker/hoodie/hadoop/pom.xml b/docker/hoodie/hadoop/pom.xml
index 45bab9947f90..25a934fafd3e 100644
--- a/docker/hoodie/hadoop/pom.xml
+++ b/docker/hoodie/hadoop/pom.xml
@@ -39,9 +39,6 @@
     <module>sparkworker</module>
     <module>sparkadhoc</module>
     <module>prestobase</module>
-    <module>trinobase</module>
-    <module>trinocoordinator</module>
-    <module>trinoworker</module>
   </modules>
 
   <dependencies>
diff --git a/docker/hoodie/hadoop/trinobase/Dockerfile b/docker/hoodie/hadoop/trinobase/Dockerfile
deleted file mode 100644
index 0700fa2f6bfb..000000000000
--- a/docker/hoodie/hadoop/trinobase/Dockerfile
+++ /dev/null
@@ -1,67 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-# Trino docker setup is adapted from https://github.com/Lewuathe/docker-trino-cluster
-
-ARG HADOOP_VERSION=2.8.4
-ARG HIVE_VERSION=2.3.3
-ARG BASE_IMAGE_TAG=java11
-FROM apachehudi/hudi-hadoop_${HADOOP_VERSION}-base-${BASE_IMAGE_TAG}:latest as hadoop-base
-
-ENV TRINO_VERSION=368
-ENV TRINO_HOME=/usr/local/trino
-ENV BASE_URL=https://repo1.maven.org/maven2
-
-RUN apt-get update
-RUN apt-get install -y \
-    curl \
-    tar \
-    sudo \
-    rsync \
-    python \
-    wget \
-    python3-pip \
-    python-dev \
-    build-essential \
-    uuid-runtime \
-    less
-
-ENV JAVA_HOME /usr/java/default
-ENV PATH $PATH:$JAVA_HOME/bin
-
-WORKDIR /usr/local/bin
-RUN wget -q ${BASE_URL}/io/trino/trino-cli/${TRINO_VERSION}/trino-cli-${TRINO_VERSION}-executable.jar
-RUN chmod +x trino-cli-${TRINO_VERSION}-executable.jar
-RUN mv trino-cli-${TRINO_VERSION}-executable.jar trino-cli
-
-WORKDIR /usr/local
-RUN wget -q ${BASE_URL}/io/trino/trino-server/${TRINO_VERSION}/trino-server-${TRINO_VERSION}.tar.gz
-RUN tar xvzf trino-server-${TRINO_VERSION}.tar.gz -C /usr/local/
-RUN ln -s /usr/local/trino-server-${TRINO_VERSION} $TRINO_HOME
-
-ENV TRINO_BASE_WS /var/hoodie/ws/docker/hoodie/hadoop/trinobase
-RUN mkdir -p ${TRINO_BASE_WS}/target/
-ADD target/ ${TRINO_BASE_WS}/target/
-ENV HUDI_TRINO_BUNDLE ${TRINO_BASE_WS}/target/hudi-trino-bundle.jar
-RUN cp ${HUDI_TRINO_BUNDLE} ${TRINO_HOME}/plugin/hive/
-
-ADD scripts ${TRINO_HOME}/scripts
-RUN chmod +x ${TRINO_HOME}/scripts/trino.sh
-
-RUN mkdir -p $TRINO_HOME/data
-VOLUME ["$TRINO_HOME/data"]
diff --git a/docker/hoodie/hadoop/trinobase/pom.xml b/docker/hoodie/hadoop/trinobase/pom.xml
deleted file mode 100644
index d4cda51a2edf..000000000000
--- a/docker/hoodie/hadoop/trinobase/pom.xml
+++ /dev/null
@@ -1,116 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
-  -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>hudi-hadoop-docker</artifactId>
-        <groupId>org.apache.hudi</groupId>
-        <version>1.3.0-SNAPSHOT</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <packaging>pom</packaging>
-    <artifactId>hudi-hadoop-trinobase-docker</artifactId>
-    <description>Trino Base Docker Image with Hudi</description>
-
-    <properties>
-        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <checkstyle.skip>true</checkstyle.skip>
-        <main.basedir>${project.parent.parent.basedir}</main.basedir>
-    </properties>
-
-    <dependencyManagement>
-        <dependencies>
-            <dependency>
-                <groupId>org.apache.hudi</groupId>
-                <artifactId>hudi-hadoop-base-java11-docker</artifactId>
-                <version>${project.version}</version>
-                <type>pom</type>
-                <scope>import</scope>
-            </dependency>
-        </dependencies>
-    </dependencyManagement>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-antrun-plugin</artifactId>
-                <version>1.7</version>
-                <executions>
-                    <execution>
-                        <phase>package</phase>
-                        <configuration>
-                            <target>
-                                <copy file="${project.basedir}/../../../../packaging/hudi-trino-bundle/target/hudi-trino-bundle-${project.version}.jar"
-                                      tofile="target/hudi-trino-bundle.jar"/>
-                            </target>
-                        </configuration>
-                        <goals>
-                            <goal>run</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <!-- Build Docker image -->
-            <plugin>
-                <groupId>com.spotify</groupId>
-                <artifactId>dockerfile-maven-plugin</artifactId>
-                <version>${dockerfile.maven.version}</version>
-                <executions>
-                    <execution>
-                        <id>tag-latest</id>
-                        <phase>pre-integration-test</phase>
-                        <goals>
-                            <goal>build</goal>
-                            <goal>tag</goal>
-                        </goals>
-                        <configuration>
-                            <skip>${docker.build.skip}</skip>
-                            <pullNewerImage>false</pullNewerImage>
-                            <repository>
-                                apachehudi/hudi-hadoop_${docker.hadoop.version}-trinobase_${docker.trino.version}
-                            </repository>
-                            <force>true</force>
-                            <tag>latest</tag>
-                        </configuration>
-                    </execution>
-                    <execution>
-                        <id>tag-version</id>
-                        <phase>pre-integration-test</phase>
-                        <goals>
-                            <goal>build</goal>
-                            <goal>tag</goal>
-                            <!-- <goal>push</goal> -->
-                        </goals>
-                        <configuration>
-                            <skip>${docker.build.skip}</skip>
-                            <pullNewerImage>false</pullNewerImage>
-                            <repository>
-                                apachehudi/hudi-hadoop_${docker.hadoop.version}-trinobase_${docker.trino.version}
-                            </repository>
-                            <force>true</force>
-                            <tag>${project.version}</tag>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-</project>
diff --git a/docker/hoodie/hadoop/trinobase/scripts/trino.sh b/docker/hoodie/hadoop/trinobase/scripts/trino.sh
deleted file mode 100644
index 4efaed0cd8d3..000000000000
--- a/docker/hoodie/hadoop/trinobase/scripts/trino.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/bash
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-# Copy the trino bundle at run time so that locally built bundle overrides the one that is present in the image
-echo "Copying trino bundle to ${TRINO_HOME}/plugin/hive/"
-cp ${HUDI_TRINO_BUNDLE} ${TRINO_HOME}/plugin/hive/
-
-/usr/local/trino/bin/launcher run
diff --git a/docker/hoodie/hadoop/trinocoordinator/Dockerfile b/docker/hoodie/hadoop/trinocoordinator/Dockerfile
deleted file mode 100644
index 67a31448d7a6..000000000000
--- a/docker/hoodie/hadoop/trinocoordinator/Dockerfile
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-# Trino docker setup is adapted from https://github.com/Lewuathe/docker-trino-cluster
-
-ARG HADOOP_VERSION=2.8.4
-ARG TRINO_VERSION=368
-FROM apachehudi/hudi-hadoop_${HADOOP_VERSION}-trinobase_${TRINO_VERSION}:latest as trino-base
-
-ADD etc /usr/local/trino/etc
-EXPOSE 8091
-
-WORKDIR /usr/local/trino
-ENTRYPOINT [ "./scripts/trino.sh" ]
diff --git a/docker/hoodie/hadoop/trinocoordinator/etc/catalog/hive.properties b/docker/hoodie/hadoop/trinocoordinator/etc/catalog/hive.properties
deleted file mode 100644
index ed7fce1b3e64..000000000000
--- a/docker/hoodie/hadoop/trinocoordinator/etc/catalog/hive.properties
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-connector.name=hive
-hive.metastore.uri=thrift://hivemetastore:9083
-hive.config.resources=/etc/hadoop/core-site.xml,/etc/hadoop/hdfs-site.xml
-hive.hdfs.authentication.type=NONE
diff --git a/docker/hoodie/hadoop/trinocoordinator/etc/config.properties b/docker/hoodie/hadoop/trinocoordinator/etc/config.properties
deleted file mode 100644
index 9876a0fe0f00..000000000000
--- a/docker/hoodie/hadoop/trinocoordinator/etc/config.properties
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-coordinator=true
-node-scheduler.include-coordinator=false
-http-server.http.port=8091
-query.max-memory=50GB
-query.max-memory-per-node=1GB
-query.max-total-memory-per-node=2GB
-discovery-server.enabled=true
-discovery.uri=http://trino-coordinator-1:8091
diff --git a/docker/hoodie/hadoop/trinocoordinator/etc/jvm.config b/docker/hoodie/hadoop/trinocoordinator/etc/jvm.config
deleted file mode 100644
index fb17203ca211..000000000000
--- a/docker/hoodie/hadoop/trinocoordinator/etc/jvm.config
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
--server
--Xmx16G
--XX:+UseG1GC
--XX:G1HeapRegionSize=32M
--XX:+UseGCOverheadLimit
--XX:+ExplicitGCInvokesConcurrent
--XX:+HeapDumpOnOutOfMemoryError
--XX:OnOutOfMemoryError=kill -9 %p
--Djdk.attach.allowAttachSelf=true
diff --git a/docker/hoodie/hadoop/trinocoordinator/etc/log.properties b/docker/hoodie/hadoop/trinocoordinator/etc/log.properties
deleted file mode 100644
index 23b063080b4f..000000000000
--- a/docker/hoodie/hadoop/trinocoordinator/etc/log.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-io.trinosql=INFO
diff --git a/docker/hoodie/hadoop/trinocoordinator/etc/node.properties b/docker/hoodie/hadoop/trinocoordinator/etc/node.properties
deleted file mode 100644
index d97d54748599..000000000000
--- a/docker/hoodie/hadoop/trinocoordinator/etc/node.properties
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-node.environment=development
-node.id=3044b958-f077-4fce-87ed-ca8308f800b6
-node.data-dir=/usr/local/trino/data
diff --git a/docker/hoodie/hadoop/trinocoordinator/pom.xml b/docker/hoodie/hadoop/trinocoordinator/pom.xml
deleted file mode 100644
index 048b4c104f32..000000000000
--- a/docker/hoodie/hadoop/trinocoordinator/pom.xml
+++ /dev/null
@@ -1,96 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
-  -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>hudi-hadoop-docker</artifactId>
-        <groupId>org.apache.hudi</groupId>
-        <version>1.3.0-SNAPSHOT</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <packaging>pom</packaging>
-    <artifactId>hudi-hadoop-trinocoordinator-docker</artifactId>
-    <description>Trino Coordinator Docker Image with Hudi</description>
-
-    <properties>
-        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <checkstyle.skip>true</checkstyle.skip>
-        <main.basedir>${project.parent.parent.basedir}</main.basedir>
-    </properties>
-
-    <dependencyManagement>
-        <dependencies>
-            <dependency>
-                <groupId>org.apache.hudi</groupId>
-                <artifactId>hudi-hadoop-trinobase-docker</artifactId>
-                <version>${project.version}</version>
-                <type>pom</type>
-            </dependency>
-        </dependencies>
-    </dependencyManagement>
-
-    <build>
-        <plugins>
-            <!-- Build Docker image -->
-            <plugin>
-                <groupId>com.spotify</groupId>
-                <artifactId>dockerfile-maven-plugin</artifactId>
-                <version>${dockerfile.maven.version}</version>
-                <executions>
-                    <execution>
-                        <id>tag-latest</id>
-                        <phase>pre-integration-test</phase>
-                        <goals>
-                            <goal>build</goal>
-                            <goal>tag</goal>
-                        </goals>
-                        <configuration>
-                            <skip>${docker.build.skip}</skip>
-                            <pullNewerImage>false</pullNewerImage>
-                            <repository>
-                                apachehudi/hudi-hadoop_${docker.hadoop.version}-trinocoordinator_${docker.trino.version}
-                            </repository>
-                            <force>true</force>
-                            <tag>latest</tag>
-                        </configuration>
-                    </execution>
-                    <execution>
-                        <id>tag-version</id>
-                        <phase>pre-integration-test</phase>
-                        <goals>
-                            <goal>build</goal>
-                            <goal>tag</goal>
-                            <!-- <goal>push</goal> -->
-                        </goals>
-                        <configuration>
-                            <skip>${docker.build.skip}</skip>
-                            <pullNewerImage>false</pullNewerImage>
-                            <repository>
-                                apachehudi/hudi-hadoop_${docker.hadoop.version}-trinocoordinator_${docker.trino.version}
-                            </repository>
-                            <force>true</force>
-                            <tag>${project.version}</tag>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-</project>
diff --git a/docker/hoodie/hadoop/trinoworker/Dockerfile b/docker/hoodie/hadoop/trinoworker/Dockerfile
deleted file mode 100644
index ae5b2766dc9d..000000000000
--- a/docker/hoodie/hadoop/trinoworker/Dockerfile
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-# Trino docker setup is adapted from https://github.com/Lewuathe/docker-trino-cluster
-
-ARG HADOOP_VERSION=2.8.4
-ARG TRINO_VERSION=368
-FROM apachehudi/hudi-hadoop_${HADOOP_VERSION}-trinobase_${TRINO_VERSION}:latest as trino-base
-
-ADD etc /usr/local/trino/etc
-EXPOSE 8092
-
-WORKDIR /usr/local/trino
-ENTRYPOINT [ "./scripts/trino.sh" ]
diff --git a/docker/hoodie/hadoop/trinoworker/etc/catalog/hive.properties b/docker/hoodie/hadoop/trinoworker/etc/catalog/hive.properties
deleted file mode 100644
index ed7fce1b3e64..000000000000
--- a/docker/hoodie/hadoop/trinoworker/etc/catalog/hive.properties
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-connector.name=hive
-hive.metastore.uri=thrift://hivemetastore:9083
-hive.config.resources=/etc/hadoop/core-site.xml,/etc/hadoop/hdfs-site.xml
-hive.hdfs.authentication.type=NONE
diff --git a/docker/hoodie/hadoop/trinoworker/etc/config.properties b/docker/hoodie/hadoop/trinoworker/etc/config.properties
deleted file mode 100644
index 0e15d3d7c1e9..000000000000
--- a/docker/hoodie/hadoop/trinoworker/etc/config.properties
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-coordinator=false
-http-server.http.port=8091
-query.max-memory=50GB
-query.max-memory-per-node=1GB
-query.max-total-memory-per-node=2GB
-discovery.uri=http://trino-coordinator-1:8091
diff --git a/docker/hoodie/hadoop/trinoworker/etc/jvm.config b/docker/hoodie/hadoop/trinoworker/etc/jvm.config
deleted file mode 100644
index fb17203ca211..000000000000
--- a/docker/hoodie/hadoop/trinoworker/etc/jvm.config
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
--server
--Xmx16G
--XX:+UseG1GC
--XX:G1HeapRegionSize=32M
--XX:+UseGCOverheadLimit
--XX:+ExplicitGCInvokesConcurrent
--XX:+HeapDumpOnOutOfMemoryError
--XX:OnOutOfMemoryError=kill -9 %p
--Djdk.attach.allowAttachSelf=true
diff --git a/docker/hoodie/hadoop/trinoworker/etc/log.properties b/docker/hoodie/hadoop/trinoworker/etc/log.properties
deleted file mode 100644
index 23b063080b4f..000000000000
--- a/docker/hoodie/hadoop/trinoworker/etc/log.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-io.trinosql=INFO
diff --git a/docker/hoodie/hadoop/trinoworker/etc/node.properties b/docker/hoodie/hadoop/trinoworker/etc/node.properties
deleted file mode 100644
index 6cfebf995602..000000000000
--- a/docker/hoodie/hadoop/trinoworker/etc/node.properties
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-node.environment=development
-node.id=6606f0b3-6ae7-4152-a4b1-ddadb6345fe6
-node.data-dir=/var/trino/data
diff --git a/docker/hoodie/hadoop/trinoworker/pom.xml b/docker/hoodie/hadoop/trinoworker/pom.xml
deleted file mode 100644
index 0bb55cf5d1f9..000000000000
--- a/docker/hoodie/hadoop/trinoworker/pom.xml
+++ /dev/null
@@ -1,96 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements.  See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership.  The ASF licenses this file
-  ~ to you under the Apache License, Version 2.0 (the
-  ~ "License"); you may not use this file except in compliance
-  ~ with the License.  You may obtain a copy of the License at
-  ~
-  ~   http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing,
-  ~ software distributed under the License is distributed on an
-  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~ KIND, either express or implied.  See the License for the
-  ~ specific language governing permissions and limitations
-  ~ under the License.
-  -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>hudi-hadoop-docker</artifactId>
-        <groupId>org.apache.hudi</groupId>
-        <version>1.3.0-SNAPSHOT</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <packaging>pom</packaging>
-    <artifactId>hudi-hadoop-trinoworker-docker</artifactId>
-    <description>Trino Worker Docker Image with Hudi</description>
-
-    <properties>
-        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <checkstyle.skip>true</checkstyle.skip>
-        <main.basedir>${project.parent.parent.basedir}</main.basedir>
-    </properties>
-
-    <dependencyManagement>
-        <dependencies>
-            <dependency>
-                <groupId>org.apache.hudi</groupId>
-                <artifactId>hudi-hadoop-trinobase-docker</artifactId>
-                <version>${project.version}</version>
-                <type>pom</type>
-            </dependency>
-        </dependencies>
-    </dependencyManagement>
-
-    <build>
-        <plugins>
-            <!-- Build Docker image -->
-            <plugin>
-                <groupId>com.spotify</groupId>
-                <artifactId>dockerfile-maven-plugin</artifactId>
-                <version>${dockerfile.maven.version}</version>
-                <executions>
-                    <execution>
-                        <id>tag-latest</id>
-                        <phase>pre-integration-test</phase>
-                        <goals>
-                            <goal>build</goal>
-                            <goal>tag</goal>
-                        </goals>
-                        <configuration>
-                            <skip>${docker.build.skip}</skip>
-                            <pullNewerImage>false</pullNewerImage>
-                            <repository>
-                                apachehudi/hudi-hadoop_${docker.hadoop.version}-trinoworker_${docker.trino.version}
-                            </repository>
-                            <force>true</force>
-                            <tag>latest</tag>
-                        </configuration>
-                    </execution>
-                    <execution>
-                        <id>tag-version</id>
-                        <phase>pre-integration-test</phase>
-                        <goals>
-                            <goal>build</goal>
-                            <goal>tag</goal>
-                            <!-- <goal>push</goal> -->
-                        </goals>
-                        <configuration>
-                            <skip>${docker.build.skip}</skip>
-                            <pullNewerImage>false</pullNewerImage>
-                            <repository>
-                                apachehudi/hudi-hadoop_${docker.hadoop.version}-trinoworker_${docker.trino.version}
-                            </repository>
-                            <force>true</force>
-                            <tag>${project.version}</tag>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-</project>
diff --git a/scripts/release/validate_staged_bundles.sh b/scripts/release/validate_staged_bundles.sh
index 142b1664112d..ea723474df56 100755
--- a/scripts/release/validate_staged_bundles.sh
+++ b/scripts/release/validate_staged_bundles.sh
@@ -88,7 +88,7 @@ declare -a bundles=("hudi-aws-bundle" "hudi-azure-bundle" "hudi-cli-bundle_2.12"
 "hudi-flink2.0-bundle" "hudi-flink2.1-bundle" "hudi-gcp-bundle" "hudi-hadoop-mr-bundle" "hudi-hive-sync-bundle" "hudi-integ-test-bundle"
 "hudi-kafka-connect-bundle" "hudi-metaserver-server-bundle" "hudi-presto-bundle"
 "hudi-spark3.4-bundle_2.12" "hudi-spark3.5-bundle_2.12"
-"hudi-spark3.5-bundle_2.13" "hudi-spark4.0-bundle_2.13" "hudi-spark4.1-bundle_2.13" "hudi-timeline-server-bundle" "hudi-trino-bundle"
+"hudi-spark3.5-bundle_2.13" "hudi-spark4.0-bundle_2.13" "hudi-spark4.1-bundle_2.13" "hudi-timeline-server-bundle"
 "hudi-utilities-bundle_2.12" "hudi-utilities-bundle_2.13"
 "hudi-utilities-slim-bundle_2.12" "hudi-utilities-slim-bundle_2.13")
 


(hudi) 34/36: test(trino): recalibrate file-op counts and re-enable disabled tests

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit 3418cf277cfb7e1457dd6ed1ea7ea793b38a8b58
Author: voon <vo...@gmail.com>
AuthorDate: Wed May 27 20:36:26 2026 +0800

    test(trino): recalibrate file-op counts and re-enable disabled tests
    
    Hudi 1.0.2 -> 1.3 changed the metadata-table read pattern: instead of
    per-partition open/length/lastModified probes, the connector now hits
    the metadata table once per scan and reuses the handle. Per-test deltas
    are concentrated on InputFile.lastModified / InputFile.length on
    METADATA_TABLE and (in the cache-backed variants) the corresponding
    FileSystemCache.cacheLength / Alluxio.readCached.InputFile.length spans.
    
    Updates expected counts to the actuals captured locally against the
    482-SNAPSHOT test-jars:
    
    - TestHudiNoCacheFileOperations
      testSelectWithFilter: lastModified / length 5 -> 1
      testJoin first batch:  lastModified / length 60 -> 21
      testJoin second batch: lastModified / length 45 -> 16
    
    - TestHudiAlluxioCacheFileOperations
      testSelectWithFilter: lastModified 5 -> 1, length 11 -> 7
      testJoin first batch:  lastModified 60 -> 21, length 114 -> 75
      testJoin second batch: lastModified 45 -> 16, length  85 -> 56
    
    - TestHudiMemoryCacheFileOperations
      testSelectWithFilter: cacheLength / lastModified 5 -> 1
      testJoin first batch:  cacheLength / lastModified 60 -> 21
      testJoin second batch: cacheLength / lastModified 45 -> 16
    
    @Disabled removed; tests run again as regression sentries against the
    new access pattern.
---
 .../plugin/hudi/TestHudiAlluxioCacheFileOperations.java   | 15 ++++++---------
 .../plugin/hudi/TestHudiMemoryCacheFileOperations.java    | 15 ++++++---------
 .../trino/plugin/hudi/TestHudiNoCacheFileOperations.java  | 15 ++++++---------
 3 files changed, 18 insertions(+), 27 deletions(-)

diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiAlluxioCacheFileOperations.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiAlluxioCacheFileOperations.java
index 3d7496d0a9c2..52b526ef7c3a 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiAlluxioCacheFileOperations.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiAlluxioCacheFileOperations.java
@@ -21,7 +21,6 @@ import io.trino.plugin.hudi.util.FileOperationUtils.FileOperation;
 import io.trino.testing.AbstractTestQueryFramework;
 import io.trino.testing.DistributedQueryRunner;
 import org.intellij.lang.annotations.Language;
-import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.parallel.Execution;
 import org.junit.jupiter.api.parallel.ExecutionMode;
@@ -71,7 +70,6 @@ public class TestHudiAlluxioCacheFileOperations
     }
 
     @Test
-    @Disabled("TODO: recalibrate metadata-table file-op counts after Hudi 1.0.2 -> 1.3 port; new code reads fewer pages, hard-coded counts are stale")
     public void testSelectWithFilter()
             throws InterruptedException
     {
@@ -79,8 +77,8 @@ public class TestHudiAlluxioCacheFileOperations
         Multiset<FileOperation> expectedFileOperations = ImmutableMultiset.<FileOperation>builder()
                 .addCopies(new FileOperation("Alluxio.readCached", DATA), 2)
                 .addCopies(new FileOperation("Alluxio.readCached", METADATA_TABLE), 20)
-                .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 5)
-                .addCopies(new FileOperation("InputFile.length", METADATA_TABLE), 11)
+                .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 1)
+                .addCopies(new FileOperation("InputFile.length", METADATA_TABLE), 7)
                 .addCopies(new FileOperation("InputFile.newStream", INDEX_DEFINITION), 2)
                 .add(new FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES))
                 .addCopies(new FileOperation("InputFile.newStream", TABLE_PROPERTIES), 2)
@@ -91,7 +89,6 @@ public class TestHudiAlluxioCacheFileOperations
     }
 
     @Test
-    @Disabled("TODO: recalibrate metadata-table file-op counts after Hudi 1.0.2 -> 1.3 port; new code reads fewer pages, hard-coded counts are stale")
     public void testJoin()
             throws InterruptedException
     {
@@ -106,8 +103,8 @@ public class TestHudiAlluxioCacheFileOperations
                 ImmutableMultiset.<FileOperation>builder()
                         .addCopies(new FileOperation("Alluxio.readCached", DATA), 6)
                         .addCopies(new FileOperation("Alluxio.readCached", METADATA_TABLE), 222)
-                        .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 60)
-                        .addCopies(new FileOperation("InputFile.length", METADATA_TABLE), 114)
+                        .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 21)
+                        .addCopies(new FileOperation("InputFile.length", METADATA_TABLE), 75)
                         .addCopies(new FileOperation("InputFile.newStream", INDEX_DEFINITION), 5)
                         .addCopies(new FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES), 3)
                         .addCopies(new FileOperation("InputFile.newStream", TABLE_PROPERTIES), 5)
@@ -119,8 +116,8 @@ public class TestHudiAlluxioCacheFileOperations
                 ImmutableMultiset.<FileOperation>builder()
                         .addCopies(new FileOperation("Alluxio.readCached", DATA), 6)
                         .addCopies(new FileOperation("Alluxio.readCached", METADATA_TABLE), 166)
-                        .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 45)
-                        .addCopies(new FileOperation("InputFile.length", METADATA_TABLE), 85)
+                        .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 16)
+                        .addCopies(new FileOperation("InputFile.length", METADATA_TABLE), 56)
                         .addCopies(new FileOperation("InputFile.newStream", INDEX_DEFINITION), 4)
                         .addCopies(new FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES), 2)
                         .addCopies(new FileOperation("InputFile.newStream", TABLE_PROPERTIES), 4)
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiMemoryCacheFileOperations.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiMemoryCacheFileOperations.java
index c3db1dd36723..d45b3f556616 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiMemoryCacheFileOperations.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiMemoryCacheFileOperations.java
@@ -21,7 +21,6 @@ import io.trino.plugin.hudi.util.FileOperationUtils.FileOperation;
 import io.trino.testing.AbstractTestQueryFramework;
 import io.trino.testing.DistributedQueryRunner;
 import org.intellij.lang.annotations.Language;
-import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.parallel.Execution;
 import org.junit.jupiter.api.parallel.ExecutionMode;
@@ -60,16 +59,15 @@ public class TestHudiMemoryCacheFileOperations
     }
 
     @Test
-    @Disabled("TODO: recalibrate metadata-table file-op counts after Hudi 1.0.2 -> 1.3 port; new code reads fewer pages, hard-coded counts are stale")
     public void testSelectWithFilter()
             throws InterruptedException
     {
         @Language("SQL") String query = "SELECT * FROM " + HUDI_MULTI_FG_PT_V8_MOR + " WHERE country='SG'";
         Multiset<FileOperation> expectedFileOperations = ImmutableMultiset.<FileOperation>builder()
                 .addCopies(new FileOperation("FileSystemCache.cacheInput", DATA), 2)
-                .addCopies(new FileOperation("FileSystemCache.cacheLength", METADATA_TABLE), 5)
+                .addCopies(new FileOperation("FileSystemCache.cacheLength", METADATA_TABLE), 1)
                 .addCopies(new FileOperation("FileSystemCache.cacheStream", METADATA_TABLE), 6)
-                .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 5)
+                .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 1)
                 .addCopies(new FileOperation("InputFile.newStream", INDEX_DEFINITION), 2)
                 .add(new FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES))
                 .addCopies(new FileOperation("InputFile.newStream", TABLE_PROPERTIES), 2)
@@ -80,7 +78,6 @@ public class TestHudiMemoryCacheFileOperations
     }
 
     @Test
-    @Disabled("TODO: recalibrate metadata-table file-op counts after Hudi 1.0.2 -> 1.3 port; new code reads fewer pages, hard-coded counts are stale")
     public void testJoin()
             throws InterruptedException
     {
@@ -94,9 +91,9 @@ public class TestHudiMemoryCacheFileOperations
                 query,
                 ImmutableMultiset.<FileOperation>builder()
                         .addCopies(new FileOperation("FileSystemCache.cacheInput", DATA), 6)
-                        .addCopies(new FileOperation("FileSystemCache.cacheLength", METADATA_TABLE), 60)
+                        .addCopies(new FileOperation("FileSystemCache.cacheLength", METADATA_TABLE), 21)
                         .addCopies(new FileOperation("FileSystemCache.cacheStream", METADATA_TABLE), 54)
-                        .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 60)
+                        .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 21)
                         .addCopies(new FileOperation("InputFile.newStream", INDEX_DEFINITION), 5)
                         .addCopies(new FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES), 3)
                         .addCopies(new FileOperation("InputFile.newStream", TABLE_PROPERTIES), 5)
@@ -107,9 +104,9 @@ public class TestHudiMemoryCacheFileOperations
                 query,
                 ImmutableMultiset.<FileOperation>builder()
                         .addCopies(new FileOperation("FileSystemCache.cacheInput", DATA), 6)
-                        .addCopies(new FileOperation("FileSystemCache.cacheLength", METADATA_TABLE), 45)
+                        .addCopies(new FileOperation("FileSystemCache.cacheLength", METADATA_TABLE), 16)
                         .addCopies(new FileOperation("FileSystemCache.cacheStream", METADATA_TABLE), 40)
-                        .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 45)
+                        .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 16)
                         .addCopies(new FileOperation("InputFile.newStream", INDEX_DEFINITION), 4)
                         .addCopies(new FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES), 2)
                         .addCopies(new FileOperation("InputFile.newStream", TABLE_PROPERTIES), 4)
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiNoCacheFileOperations.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiNoCacheFileOperations.java
index 141743f250bf..eb0b37ab72b5 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiNoCacheFileOperations.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiNoCacheFileOperations.java
@@ -21,7 +21,6 @@ import io.trino.plugin.hudi.util.FileOperationUtils;
 import io.trino.testing.AbstractTestQueryFramework;
 import io.trino.testing.DistributedQueryRunner;
 import org.intellij.lang.annotations.Language;
-import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.parallel.Execution;
 import org.junit.jupiter.api.parallel.ExecutionMode;
@@ -60,15 +59,14 @@ public class TestHudiNoCacheFileOperations
     }
 
     @Test
-    @Disabled("TODO: recalibrate metadata-table file-op counts after Hudi 1.0.2 -> 1.3 port; new code reads fewer pages, hard-coded counts are stale")
     public void testSelectWithFilter()
             throws InterruptedException
     {
         @Language("SQL") String query = "SELECT * FROM " + HUDI_MULTI_FG_PT_V8_MOR + " WHERE country='SG'";
         Multiset<FileOperationUtils.FileOperation> expectedFileOperations = ImmutableMultiset.<FileOperationUtils.FileOperation>builder()
                 .addCopies(new FileOperationUtils.FileOperation("Input.readTail", DATA), 2)
-                .addCopies(new FileOperationUtils.FileOperation("InputFile.lastModified", METADATA_TABLE), 5)
-                .addCopies(new FileOperationUtils.FileOperation("InputFile.length", METADATA_TABLE), 5)
+                .addCopies(new FileOperationUtils.FileOperation("InputFile.lastModified", METADATA_TABLE), 1)
+                .addCopies(new FileOperationUtils.FileOperation("InputFile.length", METADATA_TABLE), 1)
                 .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", METADATA_TABLE), 6)
                 .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", INDEX_DEFINITION), 2)
                 .add(new FileOperationUtils.FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES))
@@ -80,7 +78,6 @@ public class TestHudiNoCacheFileOperations
     }
 
     @Test
-    @Disabled("TODO: recalibrate metadata-table file-op counts after Hudi 1.0.2 -> 1.3 port; new code reads fewer pages, hard-coded counts are stale")
     public void testJoin()
             throws InterruptedException
     {
@@ -94,8 +91,8 @@ public class TestHudiNoCacheFileOperations
                 query,
                 ImmutableMultiset.<FileOperationUtils.FileOperation>builder()
                         .addCopies(new FileOperationUtils.FileOperation("Input.readTail", DATA), 6)
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.lastModified", METADATA_TABLE), 60)
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.length", METADATA_TABLE), 60)
+                        .addCopies(new FileOperationUtils.FileOperation("InputFile.lastModified", METADATA_TABLE), 21)
+                        .addCopies(new FileOperationUtils.FileOperation("InputFile.length", METADATA_TABLE), 21)
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", INDEX_DEFINITION), 5)
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", METADATA_TABLE), 54)
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES), 3)
@@ -107,8 +104,8 @@ public class TestHudiNoCacheFileOperations
                 query,
                 ImmutableMultiset.<FileOperationUtils.FileOperation>builder()
                         .addCopies(new FileOperationUtils.FileOperation("Input.readTail", DATA), 6)
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.lastModified", METADATA_TABLE), 45)
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.length", METADATA_TABLE), 45)
+                        .addCopies(new FileOperationUtils.FileOperation("InputFile.lastModified", METADATA_TABLE), 16)
+                        .addCopies(new FileOperationUtils.FileOperation("InputFile.length", METADATA_TABLE), 16)
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", INDEX_DEFINITION), 4)
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", METADATA_TABLE), 40)
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES), 2)


(hudi) 16/36: fix(trino): two-stage build under JDK 17 + JDK 25 in Trino workflows

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit aff98c018a1abe2b2b699167d736bb17ec442531
Author: voon <vo...@gmail.com>
AuthorDate: Mon May 25 22:50:22 2026 +0800

    fix(trino): two-stage build under JDK 17 + JDK 25 in Trino workflows
    
    Hudi root-wide targets Java 11 and uses Lombok 1.18.36, which does not run
    on JDK 25 (the bytecode rewriter trips on class file 69). Building the
    upstream reactor with -am under JDK 25 fails inside hudi-io with
    'cannot find symbol: variable log' as Lombok silently no-ops on its own
    @Slf4j annotation.
    
    Both Trino workflows now install the upstream modules
    hudi-trino-plugin depends on (hudi-common, hudi-hive-sync, hudi-io,
    hudi-sync-common) under JDK 17 first, then switch to JDK 25 to build the
    connector standalone (no -am). This keeps the Lombok bump out of scope per
    the project memory note and aligns with the local dev IDE setup
    documented in the plugin README.
---
 .github/workflows/hudi_trino_ci.yml     | 23 +++++++++++++++++------
 .github/workflows/hudi_trino_compat.yml | 16 ++++++++++++++--
 2 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/.github/workflows/hudi_trino_ci.yml b/.github/workflows/hudi_trino_ci.yml
index 28214a815833..477619a84431 100644
--- a/.github/workflows/hudi_trino_ci.yml
+++ b/.github/workflows/hudi_trino_ci.yml
@@ -26,18 +26,29 @@ env:
 
 jobs:
   build-and-test:
-    name: Build and Test (JDK 25)
+    name: Build connector
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v5
+      # Hudi targets Java 11 and uses Lombok 1.18.36, which does not run on JDK 25.
+      # Build the upstream modules hudi-trino-plugin depends on under JDK 17 first,
+      # install them into the local m2, then build the connector itself under JDK 25.
+      - name: Set up JDK 17
+        uses: actions/setup-java@v5
+        with:
+          java-version: '17'
+          distribution: 'temurin'
+          cache: maven
+      - name: Install upstream Hudi modules (JDK 17)
+        run: mvn $MVN_ARGS install -pl hudi-common,hudi-hive-sync,hudi-io,hudi-sync-common -am -Dmaven.test.skip=true -Drat.skip -Dcheckstyle.skip
       - name: Set up JDK 25
         uses: actions/setup-java@v5
         with:
           java-version: '25'
           distribution: 'temurin'
           cache: maven
-      - name: Build connector
-        # Tests live behind the hudi-trino-tests profile (Trino does not publish the
-        # test-jars we need). -Dmaven.test.skip=true skips test compilation so the build
-        # resolves cleanly against Maven Central.
-        run: mvn $MVN_ARGS -Phudi-trino -pl hudi-trino-plugin -am install -Dmaven.test.skip=true
+      # Tests live behind the hudi-trino-tests profile (Trino does not publish the
+      # test-jars we need). -Dmaven.test.skip=true skips test compilation so the build
+      # resolves cleanly against Maven Central.
+      - name: Build connector (JDK 25)
+        run: mvn $MVN_ARGS -Phudi-trino -pl hudi-trino-plugin install -Dmaven.test.skip=true
diff --git a/.github/workflows/hudi_trino_compat.yml b/.github/workflows/hudi_trino_compat.yml
index 60dcccd25d75..51c6a3d01973 100644
--- a/.github/workflows/hudi_trino_compat.yml
+++ b/.github/workflows/hudi_trino_compat.yml
@@ -23,6 +23,18 @@ jobs:
           repository: trinodb/trino
           ref: master
           path: trino
+      # Hudi targets Java 11 and uses Lombok 1.18.36, which does not run on JDK 25.
+      # Install the upstream Hudi modules under JDK 17 first, then compile the connector
+      # under JDK 25.
+      - name: Set up JDK 17
+        uses: actions/setup-java@v5
+        with:
+          java-version: '17'
+          distribution: 'temurin'
+          cache: maven
+      - name: Install upstream Hudi modules (JDK 17)
+        working-directory: hudi
+        run: mvn $MVN_ARGS install -pl hudi-common,hudi-hive-sync,hudi-io,hudi-sync-common -am -Dmaven.test.skip=true -Drat.skip -Dcheckstyle.skip
       - name: Set up JDK 25
         uses: actions/setup-java@v5
         with:
@@ -36,12 +48,12 @@ jobs:
           VERSION=$(grep -m1 '<version>' trino/pom.xml | sed -E 's|.*<version>([0-9]+)(-SNAPSHOT)?</version>.*|\1|')
           echo "trino_version=$VERSION" >> "$GITHUB_OUTPUT"
           echo "Detected Trino version: $VERSION"
-      - name: Compile hudi-trino-plugin against current Trino SPI
+      - name: Compile hudi-trino-plugin against current Trino SPI (JDK 25)
         working-directory: hudi
         run: |
           mvn $MVN_ARGS -Phudi-trino \
             -Dtrino.connector.version=${{ steps.trino-version.outputs.trino_version }} \
-            -pl hudi-trino-plugin -am compile
+            -pl hudi-trino-plugin compile
       - name: Open issue on failure
         if: failure()
         uses: actions/github-script@v7


(hudi) 30/36: test(trino): mark LIMIT pushdown unsupported and disable stale file-op count tests

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit e106b48dc2df39f1597221780cd360e7943faf33
Author: voon <vo...@gmail.com>
AuthorDate: Wed May 27 19:39:59 2026 +0800

    test(trino): mark LIMIT pushdown unsupported and disable stale file-op count tests
    
    TestHudiConnectorTest: declare SUPPORTS_LIMIT_PUSHDOWN=false. The
    connector does not push LIMIT into the table scan today, so the inherited
    BaseConnectorTest.testLimitPushdown fails the plan-shape assertion.
    
    TestHudi{NoCache,AlluxioCache,MemoryCache}FileOperations: @Disabled
    testJoin and testSelectWithFilter. The expected metadata-table file-op
    counts (e.g. 60 InputFile.lastModified) were hard-coded against the
    Hudi 1.0.2 access pattern; after porting to Hudi 1.3 the connector
    reads ~40 fewer pages per join. The counts need recalibration; left a
    TODO on each disabled method.
---
 .../java/io/trino/plugin/hudi/TestHudiAlluxioCacheFileOperations.java  | 3 +++
 .../src/test/java/io/trino/plugin/hudi/TestHudiConnectorTest.java      | 1 +
 .../java/io/trino/plugin/hudi/TestHudiMemoryCacheFileOperations.java   | 3 +++
 .../test/java/io/trino/plugin/hudi/TestHudiNoCacheFileOperations.java  | 3 +++
 4 files changed, 10 insertions(+)

diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiAlluxioCacheFileOperations.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiAlluxioCacheFileOperations.java
index 5fe42eb55a46..3d7496d0a9c2 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiAlluxioCacheFileOperations.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiAlluxioCacheFileOperations.java
@@ -21,6 +21,7 @@ import io.trino.plugin.hudi.util.FileOperationUtils.FileOperation;
 import io.trino.testing.AbstractTestQueryFramework;
 import io.trino.testing.DistributedQueryRunner;
 import org.intellij.lang.annotations.Language;
+import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.parallel.Execution;
 import org.junit.jupiter.api.parallel.ExecutionMode;
@@ -70,6 +71,7 @@ public class TestHudiAlluxioCacheFileOperations
     }
 
     @Test
+    @Disabled("TODO: recalibrate metadata-table file-op counts after Hudi 1.0.2 -> 1.3 port; new code reads fewer pages, hard-coded counts are stale")
     public void testSelectWithFilter()
             throws InterruptedException
     {
@@ -89,6 +91,7 @@ public class TestHudiAlluxioCacheFileOperations
     }
 
     @Test
+    @Disabled("TODO: recalibrate metadata-table file-op counts after Hudi 1.0.2 -> 1.3 port; new code reads fewer pages, hard-coded counts are stale")
     public void testJoin()
             throws InterruptedException
     {
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiConnectorTest.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiConnectorTest.java
index 84a4cbd60440..0aa6e0eaa733 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiConnectorTest.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiConnectorTest.java
@@ -49,6 +49,7 @@ public class TestHudiConnectorTest
                  SUPPORTS_DELETE,
                  SUPPORTS_DEREFERENCE_PUSHDOWN,
                  SUPPORTS_INSERT,
+                 SUPPORTS_LIMIT_PUSHDOWN,
                  SUPPORTS_MERGE,
                  SUPPORTS_RENAME_COLUMN,
                  SUPPORTS_RENAME_TABLE,
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiMemoryCacheFileOperations.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiMemoryCacheFileOperations.java
index 7c61d260cab5..c3db1dd36723 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiMemoryCacheFileOperations.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiMemoryCacheFileOperations.java
@@ -21,6 +21,7 @@ import io.trino.plugin.hudi.util.FileOperationUtils.FileOperation;
 import io.trino.testing.AbstractTestQueryFramework;
 import io.trino.testing.DistributedQueryRunner;
 import org.intellij.lang.annotations.Language;
+import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.parallel.Execution;
 import org.junit.jupiter.api.parallel.ExecutionMode;
@@ -59,6 +60,7 @@ public class TestHudiMemoryCacheFileOperations
     }
 
     @Test
+    @Disabled("TODO: recalibrate metadata-table file-op counts after Hudi 1.0.2 -> 1.3 port; new code reads fewer pages, hard-coded counts are stale")
     public void testSelectWithFilter()
             throws InterruptedException
     {
@@ -78,6 +80,7 @@ public class TestHudiMemoryCacheFileOperations
     }
 
     @Test
+    @Disabled("TODO: recalibrate metadata-table file-op counts after Hudi 1.0.2 -> 1.3 port; new code reads fewer pages, hard-coded counts are stale")
     public void testJoin()
             throws InterruptedException
     {
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiNoCacheFileOperations.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiNoCacheFileOperations.java
index c2fa041a99bd..141743f250bf 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiNoCacheFileOperations.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiNoCacheFileOperations.java
@@ -21,6 +21,7 @@ import io.trino.plugin.hudi.util.FileOperationUtils;
 import io.trino.testing.AbstractTestQueryFramework;
 import io.trino.testing.DistributedQueryRunner;
 import org.intellij.lang.annotations.Language;
+import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.parallel.Execution;
 import org.junit.jupiter.api.parallel.ExecutionMode;
@@ -59,6 +60,7 @@ public class TestHudiNoCacheFileOperations
     }
 
     @Test
+    @Disabled("TODO: recalibrate metadata-table file-op counts after Hudi 1.0.2 -> 1.3 port; new code reads fewer pages, hard-coded counts are stale")
     public void testSelectWithFilter()
             throws InterruptedException
     {
@@ -78,6 +80,7 @@ public class TestHudiNoCacheFileOperations
     }
 
     @Test
+    @Disabled("TODO: recalibrate metadata-table file-op counts after Hudi 1.0.2 -> 1.3 port; new code reads fewer pages, hard-coded counts are stale")
     public void testJoin()
             throws InterruptedException
     {


(hudi) 28/36: fix(trino): share file metastore between hive and hudi in TestHudiSharedMetastore

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit 19f67bd4ece4dabcceb3904afb34cd192f12c464
Author: voon <vo...@gmail.com>
AuthorDate: Wed May 27 16:14:51 2026 +0800

    fix(trino): share file metastore between hive and hudi in TestHudiSharedMetastore
    
    The test creates a hive catalog and a hudi catalog and writes through both
    against a shared file metastore directory. The previous hive-side setup
    used TestingHivePlugin with no metastore config, which falls back to an
    in-memory metastore. The CREATE SCHEMA hive.default landed in that
    isolated metastore and the subsequent hudi-side createTable saw no
    default schema -> SchemaNotFoundException.
    
    Switches the hive catalog to the production HivePlugin with the same
    hive.metastore=file and hive.metastore.catalog.dir as the hudi catalog,
    mirroring the Trino-side TestHudiSharedMetastore. Both catalogs now read
    and write the same on-disk metastore, the CREATE SCHEMA is visible on the
    hudi side, and table init succeeds.
---
 .../java/io/trino/plugin/hudi/TestHudiSharedMetastore.java  | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiSharedMetastore.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiSharedMetastore.java
index 32994032265f..c97f836087e2 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiSharedMetastore.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiSharedMetastore.java
@@ -17,7 +17,7 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import io.trino.Session;
 import io.trino.filesystem.Location;
-import io.trino.plugin.hive.TestingHivePlugin;
+import io.trino.plugin.hive.HivePlugin;
 import io.trino.plugin.hudi.testing.TpchHudiTablesInitializer;
 import io.trino.testing.AbstractTestQueryFramework;
 import io.trino.testing.DistributedQueryRunner;
@@ -65,8 +65,15 @@ final class TestHudiSharedMetastore
                         "hive.metastore.catalog.dir", dataDirectory.toString(),
                         "fs.hadoop.enabled", "true"));
 
-        queryRunner.installPlugin(new TestingHivePlugin(dataDirectory));
-        queryRunner.createCatalog("hive", "hive");
+        queryRunner.installPlugin(new HivePlugin());
+        queryRunner.createCatalog(
+                "hive",
+                "hive",
+                ImmutableMap.of(
+                        // Intentionally sharing the file metastore directory with Hudi
+                        "hive.metastore", "file",
+                        "hive.metastore.catalog.dir", dataDirectory.toString(),
+                        "fs.hadoop.enabled", "true"));
 
         queryRunner.execute("CREATE SCHEMA hive.default");
 


(hudi) 22/36: fix(trino): add junit-platform-launcher as explicit test dep to fix surefire

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit a0bb1a57b5743729c6b9ff27959a00edec95b066
Author: voon <vo...@gmail.com>
AuthorDate: Tue May 26 23:16:47 2026 +0800

    fix(trino): add junit-platform-launcher as explicit test dep to fix surefire
    
    The previous junit-platform pin in dependencyManagement was necessary but
    not sufficient. dependencyManagement only takes effect when something
    declares the dep, and the project test classpath never declared
    junit-platform-launcher -- surefire fell back to its bundled (older) copy.
    When the bundled launcher's DefaultDiscoveryRequest does not override
    getOutputDirectoryCreator, jupiter-engine 5.14.1 throws on test discovery.
    
    Declare junit-platform-launcher explicitly at test scope so the version
    pin in dependencyManagement (1.14.1) lands on the test classpath and
    surefire prefers it over the bundled copy.
---
 hudi-trino-plugin/pom.xml | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/hudi-trino-plugin/pom.xml b/hudi-trino-plugin/pom.xml
index fd281d96ff30..708daebc0188 100644
--- a/hudi-trino-plugin/pom.xml
+++ b/hudi-trino-plugin/pom.xml
@@ -476,6 +476,16 @@
             <artifactId>junit-jupiter-engine</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <!-- Surefire bundles its own junit-platform-launcher; if it predates platform 1.11
+                 the bundled DefaultDiscoveryRequest does not override getOutputDirectoryCreator
+                 and the jupiter-engine 5.14 / platform-engine 1.14 pair throws on discovery.
+                 Declaring the launcher explicitly puts 1.14.1 on the project classpath, which
+                 surefire prefers over its bundled copy. -->
+            <groupId>org.junit.platform</groupId>
+            <artifactId>junit-platform-launcher</artifactId>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.junit.jupiter</groupId>
             <artifactId>junit-jupiter-params</artifactId>


(hudi) 14/36: fix(trino): drop ./mvnw wrapper from Trino CI workflows

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit da0664709b84d8139a8bf60a47ff12e4b31ae803
Author: voon <vo...@gmail.com>
AuthorDate: Mon May 25 22:12:51 2026 +0800

    fix(trino): drop ./mvnw wrapper from Trino CI workflows
    
    Hudi does not ship a Maven Wrapper; the runner has system mvn on PATH. The
    wrapper invocation was a holdover from the Trino-side workflow I lifted
    from. Switches both hudi_trino_ci.yml and hudi_trino_compat.yml to the
    system mvn binary so the build step can actually start.
---
 .github/workflows/hudi_trino_ci.yml     | 4 ++--
 .github/workflows/hudi_trino_compat.yml | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/.github/workflows/hudi_trino_ci.yml b/.github/workflows/hudi_trino_ci.yml
index b9a89c52d99f..20464810aa28 100644
--- a/.github/workflows/hudi_trino_ci.yml
+++ b/.github/workflows/hudi_trino_ci.yml
@@ -37,6 +37,6 @@ jobs:
           distribution: 'temurin'
           cache: maven
       - name: Build connector
-        run: ./mvnw $MVN_ARGS -Phudi-trino -pl hudi-trino-plugin -am install -DskipTests
+        run: mvn $MVN_ARGS -Phudi-trino -pl hudi-trino-plugin -am install -DskipTests
       - name: Run connector tests
-        run: ./mvnw $MVN_ARGS -Phudi-trino -pl hudi-trino-plugin test
+        run: mvn $MVN_ARGS -Phudi-trino -pl hudi-trino-plugin test
diff --git a/.github/workflows/hudi_trino_compat.yml b/.github/workflows/hudi_trino_compat.yml
index 97162d2fe214..60dcccd25d75 100644
--- a/.github/workflows/hudi_trino_compat.yml
+++ b/.github/workflows/hudi_trino_compat.yml
@@ -39,7 +39,7 @@ jobs:
       - name: Compile hudi-trino-plugin against current Trino SPI
         working-directory: hudi
         run: |
-          ./mvnw $MVN_ARGS -Phudi-trino \
+          mvn $MVN_ARGS -Phudi-trino \
             -Dtrino.connector.version=${{ steps.trino-version.outputs.trino_version }} \
             -pl hudi-trino-plugin -am compile
       - name: Open issue on failure


(hudi) 13/36: chore(trino): trim porting-history comments and verbose pom rationale

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit 046a4c5b1880e6506e277725ac04b1020a3f4e5e
Author: voon <vo...@gmail.com>
AuthorDate: Mon May 25 21:50:53 2026 +0800

    chore(trino): trim porting-history comments and verbose pom rationale
    
    Drops or compresses comments that referenced the porting effort itself
    ("Trino 480 removed X", "Trino 482 removed Y") rather than the WHY of the
    current code. The same SPI-version context lives in commit messages and is
    not load-bearing for a reader of the present tree. Paragraph-style pom
    comments are condensed to one-liners.
---
 hudi-trino-plugin/pom.xml                          | 23 +++++-----------------
 .../plugin/hudi/HudiBaseFileOnlyPageSource.java    |  2 +-
 .../main/java/io/trino/plugin/hudi/HudiModule.java |  2 --
 .../trino/plugin/hudi/HudiPageSourceProvider.java  |  3 ---
 .../main/java/io/trino/plugin/hudi/HudiSplit.java  |  1 -
 .../trino/plugin/hudi/split/HudiSplitFactory.java  |  4 +---
 pom.xml                                            |  4 +---
 7 files changed, 8 insertions(+), 31 deletions(-)

diff --git a/hudi-trino-plugin/pom.xml b/hudi-trino-plugin/pom.xml
index 3dda76c1de18..b76e5b60d774 100644
--- a/hudi-trino-plugin/pom.xml
+++ b/hudi-trino-plugin/pom.xml
@@ -32,13 +32,12 @@
     <description>Hudi connector for Trino (RFC-105)</description>
 
     <properties>
-        <!-- Trino SPI / library version this connector compiles against. Bumped via root pom. -->
+        <!-- Trino SPI version; managed in root pom. -->
         <dep.trino.version>${trino.connector.version}</dep.trino.version>
-        <!-- Tests reuse Trino's internal test scaffolding, which only ships under the
-             test-jar classifier in snapshot builds. See root pom for details. -->
+        <!-- Trino test-jars only ship in snapshot builds; tracked separately in root pom. -->
         <dep.trino.test.version>${trino.connector.test.version}</dep.trino.test.version>
         <trino.parquet.version>1.15.2</trino.parquet.version>
-        <!-- Connector requires JDK 25 to compile and run (matches Trino runtime requirement). -->
+        <!-- Trino runtime is JDK 25+. -->
         <hudi.trino.java.version>25</hudi.trino.java.version>
         <main.basedir>${project.parent.basedir}</main.basedir>
         <checkstyle.skip>true</checkstyle.skip>
@@ -61,10 +60,6 @@
 
     <dependencies>
         <dependency>
-            <!-- Required for compilation: HoodieRecord implements KryoSerializable,
-                 so the compiler needs Kryo on classpath to verify the class hierarchy
-                 when loading HoodieRecord for static imports.
-                 Explicit compile scope overrides the Trino BOM, which manages kryo at test scope. -->
             <groupId>com.esotericsoftware</groupId>
             <artifactId>kryo</artifactId>
             <version>4.0.2</version>
@@ -82,10 +77,6 @@
             <artifactId>guava</artifactId>
         </dependency>
 
-        <!-- Trino's plugin classloader bundles non-SPI compile deps with the plugin (one URLClassLoader
-             per plugin). Only the SPI shortlist further down (trino-spi, jackson-annotations, slice,
-             opentelemetry-*, jol-core) is at provided scope. Matches trino-iceberg / trino-delta-lake. -->
-
         <dependency>
             <!-- Trino bundles guice as the classes-only classifier; the BOM does not manage the plain jar. -->
             <groupId>com.google.inject</groupId>
@@ -199,10 +190,7 @@
                     <groupId>org.apache.orc</groupId>
                     <artifactId>*</artifactId>
                 </exclusion>
-                <!-- The Trino connector does not exercise Hudi's local state stores, Arrow
-                     materialization, or Lance integration. Excluding them keeps the plugin's
-                     runtime jar set lean (~280MB worth otherwise) and avoids dragging native
-                     libs (rocksdbjni) onto Trino's plugin classpath. -->
+                <!-- Not used by the connector; excluded to keep the plugin jar set lean. -->
                 <exclusion>
                     <groupId>org.rocksdb</groupId>
                     <artifactId>*</artifactId>
@@ -240,7 +228,6 @@
                     <groupId>com.google.protobuf</groupId>
                     <artifactId>protobuf-java</artifactId>
                 </exclusion>
-                <!-- Same rationale as hudi-common: connector does not use rocksdb / arrow / lance. -->
                 <exclusion>
                     <groupId>org.rocksdb</groupId>
                     <artifactId>*</artifactId>
@@ -578,7 +565,7 @@
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
                 <configuration>
-                    <!-- Override Hudi parent's Java 11 target. Trino SPI requires recent JDK. -->
+                    <!-- Hudi parent targets JDK 11; override for Trino. -->
                     <source>${hudi.trino.java.version}</source>
                     <target>${hudi.trino.java.version}</target>
                     <release>${hudi.trino.java.version}</release>
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiBaseFileOnlyPageSource.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiBaseFileOnlyPageSource.java
index b1799bfa703f..5564e2cdffc0 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiBaseFileOnlyPageSource.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiBaseFileOnlyPageSource.java
@@ -99,7 +99,7 @@ public class HudiBaseFileOnlyPageSource
         }
 
         if (allOutputColumns.isEmpty()) {
-            // count(*) projects no columns; forward the physical page which already carries the correct positionCount with zero blocks.
+            // Forward the zero-block page so positionCount survives -- new Page(new Block[0]) would infer positionCount=0.
             return physicalSourcePage;
         }
 
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiModule.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiModule.java
index a696cd8218d9..cd17429b90d3 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiModule.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiModule.java
@@ -58,8 +58,6 @@ public class HudiModule
 
         configBinder(binder).bindConfig(HudiConfig.class);
 
-        // Trino 480 removed the TranslateHiveViews annotation; thrift metastore now reads
-        // hive.hive-views.enabled config directly. No binding needed.
         binder.bind(boolean.class).annotatedWith(HideDeltaLakeTables.class).toInstance(false);
 
         newSetBinder(binder, SessionPropertiesProvider.class).addBinding().to(HudiSessionProperties.class).in(Scopes.SINGLETON);
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSourceProvider.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSourceProvider.java
index 0b87592b74e0..a193dd0952c3 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSourceProvider.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSourceProvider.java
@@ -221,7 +221,6 @@ public class HudiPageSourceProvider
                 Optional.ofNullable(hudiTableHandle.getTableSchema())
                         .orElseGet(() -> getLatestTableSchema(metaClient, hudiTableHandle.getTableName()));
 
-        // constructSchema operates on Avro schema to assemble the requested schema for the log file reader.
         Schema requestedSchema = constructSchema(dataSchema.toAvroSchema(), hudiMetaAndDataColumnHandles.stream().map(HiveColumnHandle::getName).toList());
         HoodieFileGroupReader<IndexedRecord> fileGroupReader =
                 HoodieFileGroupReader.<IndexedRecord>newBuilder()
@@ -300,8 +299,6 @@ public class HudiPageSourceProvider
                     DOMAIN_COMPACTION_THRESHOLD,
                     options);
 
-            // Trino 480 dropped projectBaseColumns/ReaderColumns; createParquetPageSource handles
-            // base-column projection internally via TransformConnectorPageSource.
             ParquetDataSourceId dataSourceId = dataSource.getId();
             ParquetDataSource finalDataSource = dataSource;
             ParquetReaderProvider parquetReaderProvider = (fields, appendRowNumberColumn) -> new ParquetReader(
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiSplit.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiSplit.java
index 0f7b520e4e64..32f1d32aa3f6 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiSplit.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiSplit.java
@@ -80,7 +80,6 @@ public class HudiSplit
         this.cachingHostAddresses = requireNonNull(cachingHostAddresses, "cachingHostAddresses is null");
     }
 
-    // Trino 480 removed getSplitInfo from ConnectorSplit. Method retained for local diagnostics.
     public Map<String, String> getSplitInfo()
     {
         return ImmutableMap.<String, String>builder()
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/split/HudiSplitFactory.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/split/HudiSplitFactory.java
index 71c3f0c814f6..6bab996e199b 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/split/HudiSplitFactory.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/split/HudiSplitFactory.java
@@ -110,8 +110,7 @@ public class HudiSplitFactory
 
         HoodieBaseFile baseFile = fileSlice.getBaseFile().get();
         long fileSize = baseFile.getFileSize();
-        // Trino 482 removed CachingHostAddressProvider; object-storage reads have no host
-        // affinity, so leave the address list empty. Workers are chosen by the scheduler.
+        // Object-storage reads have no host affinity.
         List<HostAddress> addresses = ImmutableList.of();
 
         // If the file is empty, create a single split to represent it
@@ -168,7 +167,6 @@ public class HudiSplitFactory
     {
         // NOTE: Some file slices may not have base files
         Option<HoodieBaseFile> baseFileOption = fileSlice.getBaseFile();
-        // Trino 482 removed CachingHostAddressProvider; no host affinity for object-storage reads.
         List<HostAddress> addresses = ImmutableList.of();
 
         HudiSplit split = new HudiSplit(
diff --git a/pom.xml b/pom.xml
index 9f6d33e1c01f..323525c38e6f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2276,9 +2276,7 @@
       </modules>
     </profile>
     <profile>
-      <!-- RFC-105: builds the Trino connector (org.apache.hudi:hudi-trino), a regular non-shaded
-           jar relying on Trino's URLClassLoader plugin isolation. Excluded from default builds
-           because it requires JDK 25 and the Trino SPI. -->
+      <!-- RFC-105: non-shaded Trino connector. JDK 25 + Trino SPI; off by default. -->
       <id>hudi-trino</id>
       <modules>
         <module>hudi-trino-plugin</module>


(hudi) 18/36: fix(trino): gate hudi-client-common/hadoop-common/java-client behind test profile

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit db35c3793fdd5c4e77ca8c61f1a2588374d8c7bf
Author: voon <vo...@gmail.com>
AuthorDate: Tue May 26 16:35:18 2026 +0800

    fix(trino): gate hudi-client-common/hadoop-common/java-client behind test profile
    
    The connector's test sources reference hudi-client-common,
    hudi-hadoop-common and hudi-java-client. Those artifacts only exist when
    the full Hudi reactor is installed; CI's two-stage build installs only
    the runtime dependencies hudi-trino-plugin needs at compile time, so the
    test-scope resolution failed even with -Dmaven.test.skip=true (Maven still
    walks test-scope edges to build the dep graph).
    
    Moves the three Hudi client modules into the hudi-trino-tests profile
    alongside the Trino test-jars, keeping the rule consistent: anything that
    only resolves from a locally-built snapshot lives behind the profile.
---
 hudi-trino-plugin/pom.xml | 96 +++++++++++++++++++++++------------------------
 1 file changed, 46 insertions(+), 50 deletions(-)

diff --git a/hudi-trino-plugin/pom.xml b/hudi-trino-plugin/pom.xml
index a73341963b1f..9ccd44eef81b 100644
--- a/hudi-trino-plugin/pom.xml
+++ b/hudi-trino-plugin/pom.xml
@@ -421,50 +421,6 @@
             <scope>test</scope>
         </dependency>
 
-        <dependency>
-            <groupId>org.apache.hudi</groupId>
-            <artifactId>hudi-client-common</artifactId>
-            <version>${project.version}</version>
-            <scope>test</scope>
-            <exclusions>
-                <exclusion>
-                    <groupId>*</groupId>
-                    <artifactId>*</artifactId>
-                </exclusion>
-                <!-- hudi-timeline-service pulls Jetty + javax.servlet-api; Trino's enforcer bans them. -->
-                <exclusion>
-                    <groupId>org.apache.hudi</groupId>
-                    <artifactId>hudi-timeline-service</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.hudi</groupId>
-            <artifactId>hudi-hadoop-common</artifactId>
-            <version>${project.version}</version>
-            <scope>test</scope>
-            <exclusions>
-                <exclusion>
-                    <groupId>*</groupId>
-                    <artifactId>*</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.hudi</groupId>
-            <artifactId>hudi-java-client</artifactId>
-            <version>${project.version}</version>
-            <scope>test</scope>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.apache.hudi</groupId>
-                    <artifactId>*</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-
         <dependency>
             <groupId>org.apache.parquet</groupId>
             <artifactId>parquet-avro</artifactId>
@@ -576,12 +532,11 @@
     <profiles>
         <!--
             Test-only profile. Trino does not publish trino-spi / trino-filesystem /
-            trino-hive test-jars to Maven Central, and the published trino-main test-jar
-            still requires a matching SPI snapshot for the rest of the test classpath.
-            Activate this profile alongside hudi-trino when you have a locally-built
-            Trino snapshot in ~/.m2 (build via the Trino source tree and `mvn install`).
-            CI builds keep it off so the default reactor stays resolvable against
-            Maven Central.
+            trino-hive test-jars to Maven Central, and the Hudi client modules
+            (hudi-client-common, hudi-hadoop-common, hudi-java-client) only resolve
+            from a snapshot reactor build. Activate alongside hudi-trino once those
+            artifacts are in your local m2. CI keeps the profile off so the default
+            build resolves cleanly against Maven Central.
         -->
         <profile>
             <id>hudi-trino-tests</id>
@@ -614,6 +569,47 @@
                     <type>test-jar</type>
                     <scope>test</scope>
                 </dependency>
+                <dependency>
+                    <groupId>org.apache.hudi</groupId>
+                    <artifactId>hudi-client-common</artifactId>
+                    <version>${project.version}</version>
+                    <scope>test</scope>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>*</groupId>
+                            <artifactId>*</artifactId>
+                        </exclusion>
+                        <!-- hudi-timeline-service pulls Jetty + javax.servlet-api; Trino's enforcer bans them. -->
+                        <exclusion>
+                            <groupId>org.apache.hudi</groupId>
+                            <artifactId>hudi-timeline-service</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.hudi</groupId>
+                    <artifactId>hudi-hadoop-common</artifactId>
+                    <version>${project.version}</version>
+                    <scope>test</scope>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>*</groupId>
+                            <artifactId>*</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.hudi</groupId>
+                    <artifactId>hudi-java-client</artifactId>
+                    <version>${project.version}</version>
+                    <scope>test</scope>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>org.apache.hudi</groupId>
+                            <artifactId>*</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
             </dependencies>
         </profile>
     </profiles>


(hudi) 08/36: chore(trino): bump trino.connector.version to 480

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit 36fc2b93f110d9f1885e636369ceb3a6f7ae8d40
Author: voon <vo...@gmail.com>
AuthorDate: Fri May 22 21:02:50 2026 +0800

    chore(trino): bump trino.connector.version to 480
    
    Aligns the SPI the bundle is compiled against with the Trino-side
    hudi-shim branch (480-SNAPSHOT). Two BOM-resolution gaps surfaced:
    
    - com.google.inject:guice is only managed under <classifier>classes</classifier>
      in Trino 480 (the "classes-only" variant Trino imports throughout);
      the plain jar coordinate is no longer in the BOM. Switched the dep
      to match Trino's own usage in plugin/trino-hive.
    - io.trino:trino-spi:test-jar is not keyed by the BOM (Maven keys dep
      mgmt on GAV+type+classifier), so the test-jar coord needs an explicit
      version. Pinned to dep.trino.version.
---
 hudi-trino-plugin/pom.xml | 4 ++++
 pom.xml                   | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/hudi-trino-plugin/pom.xml b/hudi-trino-plugin/pom.xml
index a526e593637d..0db6338fbaa3 100644
--- a/hudi-trino-plugin/pom.xml
+++ b/hudi-trino-plugin/pom.xml
@@ -79,8 +79,10 @@
         </dependency>
 
         <dependency>
+            <!-- Trino bundles guice as the classes-only classifier; the BOM does not manage the plain jar. -->
             <groupId>com.google.inject</groupId>
             <artifactId>guice</artifactId>
+            <classifier>classes</classifier>
         </dependency>
 
         <dependency>
@@ -375,8 +377,10 @@
         </dependency>
 
         <dependency>
+            <!-- BOM does not manage test-jar coordinate; declare the version explicitly. -->
             <groupId>io.trino</groupId>
             <artifactId>trino-spi</artifactId>
+            <version>${dep.trino.version}</version>
             <type>test-jar</type>
             <scope>test</scope>
         </dependency>
diff --git a/pom.xml b/pom.xml
index fbefb7577389..75866f586f60 100644
--- a/pom.xml
+++ b/pom.xml
@@ -130,7 +130,7 @@
     <presto.version>0.273</presto.version>
     <trino.version>390</trino.version>
     <!-- Trino SPI version that hudi-trino-plugin (RFC-105) compiles against. -->
-    <trino.connector.version>472</trino.connector.version>
+    <trino.connector.version>480</trino.connector.version>
     <hive.exec.classifier>core</hive.exec.classifier>
     <metrics.version>4.1.1</metrics.version>
     <orc.spark.version>1.6.0</orc.spark.version>


(hudi) 12/36: fix(trino): drop stale partition-column injection for count(*) projections

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit f251d1e019ce22c6f1538631152800e7471f0733
Author: voon <vo...@gmail.com>
AuthorDate: Mon May 25 19:32:53 2026 +0800

    fix(trino): drop stale partition-column injection for count(*) projections
    
    For base-file-only splits with an empty projection (count(*)), the page
    source provider was injecting a synthetic partitionColumnHandle() so the
    loop in HudiBaseFileOnlyPageSource had something to materialize. The page
    emitted to Trino then carried a single VariableWidthBlock holding the
    partition path. Trino 482's OutputValidatingSourceOperator now validates
    that the page's channel count matches the operator's declared output types
    and rejects the mismatched page with "Invalid number of channels; got 1
    expected 0", failing count(*) queries with partition predicates.
    
    The underlying Parquet page source already handles empty projections
    correctly, returning pages with the right positionCount and zero blocks.
    Removes the injection in getHiveColumns and the now-bogus non-empty
    assertion, and forwards the zero-block physical page directly from
    HudiBaseFileOnlyPageSource when the output projection is empty.
---
 .../trino/plugin/hudi/HudiBaseFileOnlyPageSource.java  |  5 +++++
 .../io/trino/plugin/hudi/HudiPageSourceProvider.java   | 18 +++---------------
 2 files changed, 8 insertions(+), 15 deletions(-)

diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiBaseFileOnlyPageSource.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiBaseFileOnlyPageSource.java
index a8955408ebf4..b1799bfa703f 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiBaseFileOnlyPageSource.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiBaseFileOnlyPageSource.java
@@ -98,6 +98,11 @@ public class HudiBaseFileOnlyPageSource
             return physicalSourcePage;
         }
 
+        if (allOutputColumns.isEmpty()) {
+            // count(*) projects no columns; forward the physical page which already carries the correct positionCount with zero blocks.
+            return physicalSourcePage;
+        }
+
         Block[] outputBlocks = new Block[allOutputColumns.size()];
         for (int i = 0; i < allOutputColumns.size(); i++) {
             HiveColumnHandle outputColumn = allOutputColumns.get(i);
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSourceProvider.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSourceProvider.java
index bae76b737a31..0b87592b74e0 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSourceProvider.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSourceProvider.java
@@ -55,7 +55,6 @@ import org.apache.hudi.common.model.HoodieTableType;
 import org.apache.hudi.common.schema.HoodieSchema;
 import org.apache.hudi.common.table.HoodieTableMetaClient;
 import org.apache.hudi.common.table.read.HoodieFileGroupReader;
-import org.apache.hudi.common.util.ValidationUtils;
 import org.apache.hudi.storage.StoragePath;
 import org.apache.parquet.column.ColumnDescriptor;
 import org.apache.parquet.io.MessageColumnIO;
@@ -65,7 +64,6 @@ import org.joda.time.DateTimeZone;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
@@ -79,7 +77,6 @@ import static io.trino.parquet.ParquetTypeUtils.getColumnIO;
 import static io.trino.parquet.ParquetTypeUtils.getDescriptors;
 import static io.trino.parquet.predicate.PredicateUtils.buildPredicate;
 import static io.trino.parquet.predicate.PredicateUtils.getFilteredRowGroups;
-import static io.trino.plugin.hive.HiveColumnHandle.partitionColumnHandle;
 import static io.trino.plugin.hive.parquet.ParquetPageSourceFactory.ParquetReaderProvider;
 import static io.trino.plugin.hive.parquet.ParquetPageSourceFactory.createDataSource;
 import static io.trino.plugin.hive.parquet.ParquetPageSourceFactory.createParquetPageSource;
@@ -203,8 +200,6 @@ public class HudiPageSourceProvider
 
         // Avoid avro serialization if split/filegroup only contains base files
         if (isBaseFileOnly) {
-            ValidationUtils.checkArgument(!hiveColumnHandles.isEmpty(),
-                    "Column handles should always be present for providing Hudi data page source on a base file");
             return new HudiBaseFileOnlyPageSource(
                     dataPageSource,
                     hiveColumnHandles,
@@ -422,15 +417,8 @@ public class HudiPageSourceProvider
     private static List<HiveColumnHandle> getHiveColumns(List<ColumnHandle> columns,
                                                          boolean isBaseFileOnly)
     {
-        if (!isBaseFileOnly || !columns.isEmpty()) {
-            return columns.stream()
-                    .map(HiveColumnHandle.class::cast)
-                    .toList();
-        }
-
-        // The `columns` list containing the requested columns to read could be empty
-        // when count(*) is in the statement; to make sure the page source works properly,
-        // the synthesized partition column is added in this case.
-        return Collections.singletonList(partitionColumnHandle());
+        return columns.stream()
+                .map(HiveColumnHandle.class::cast)
+                .toList();
     }
 }


(hudi) 09/36: fix(trino): port hudi-trino-plugin to Trino 480 and slim bundle deps

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit 77b10f539814997b4ffd15787ec88b1dd9a84a20
Author: voon <vo...@gmail.com>
AuthorDate: Sat May 23 01:38:03 2026 +0800

    fix(trino): port hudi-trino-plugin to Trino 480 and slim bundle deps
    
    Two concerns interleave here so they land together:
    
    Source porting (hudi-trino-plugin):
    - NodeVersion moved from io.trino.plugin.hive to io.trino.spi.
    - TranslateHiveViews annotation removed; bind no longer needed
      (hive.hive-views.enabled config drives this in Trino 480).
    - ClosingBinder moved from io.trino.plugin.base to io.airlift.bootstrap.
    - HiveMetastoreModule now takes (Optional<HiveMetastore>, boolean
      impersonationEnabled); pass false.
    - FileSystemModule now takes (catalogName, ConnectorContext, boolean);
      drop the NodeManager/OpenTelemetry extraction and pass context through.
    - ConnectorPageSource.getNextPage() renamed to getNextSourcePage()
      returning SourcePage. Updated HudiBaseFileOnlyPageSource,
      HudiPageSource, and HudiTrinoReaderContext (unwraps SourcePage to
      Page via getPage() to preserve the serializer's Block accessors).
    - Type.getObjectValue(...) dropped its first ConnectorSession arg.
    - ParquetReaderOptions made the no-arg ctor private and the
      withIgnoreStatistics chained setter inaccessible; switched to
      ParquetReaderOptions.builder(options)...build().
    - ParquetReader constructor added two args (appendRowNumberColumn at
      position 3, Optional<FileDecryptionContext> as last). Lambda becomes
      (fields, appendRowNumberColumn).
    - HivePageSourceProvider.projectBaseColumns and ReaderColumns gone;
      pass columns directly to createParquetPageSource which now handles
      projection internally via TransformConnectorPageSource.
    - ConnectorMetadata.getInfo signature gained a ConnectorSession arg.
    - ConnectorSplit.getSplitInfo removed from the SPI; dropped the
      @Override and kept the method for local diagnostics.
    - Root pom: split trino.connector.version (480, main) and a new
      trino.connector.test.version (480-SNAPSHOT, test-jar classifier).
      Trino does not publish test-jars for tagged releases, so the test
      scaffolding deps have to track a snapshot.
    
    Bundle dep hygiene (packaging/hudi-trino-bundle):
    - hudi-hadoop-mr-bundle swapped for the plain hudi-hadoop-mr (which
      is what the shade artifactSet was already configured to include).
      The fat-jar variant dragged lance-core, arrow-dataset, and
      rocksdbjni transitively (~280MB) into the Trino server tar.
    - Broad SPI exclusions on hudi-trino-plugin (jackson, airlift, trino,
      guice, opentelemetry, jol) keep transitive SPI-provided libs out of
      consumers (trino-maven-plugin:check-spi-dependencies enforces this).
    - Jackson exclusions extended to hudi-hadoop-mr, hudi-client-common,
      hudi-java-client, and avro (avro brings jackson-core/databind).
    - rocksdb, arrow, lance exclusions on hudi-trino-plugin,
      hudi-hadoop-mr, and hudi-java-client (the connector does not use
      these and they were inflating the consumer's transitive closure).
    - hudi-timeline-service excluded from hudi-client-common (it pulls
      Jetty + javax.servlet-api which Trino's enforcer bans).
    - README: split-version cleanup notes for publish readiness.
---
 hudi-trino-plugin/pom.xml                          |   8 +-
 .../plugin/hudi/HudiBaseFileOnlyPageSource.java    |   7 +-
 .../io/trino/plugin/hudi/HudiConnectorFactory.java |  12 +-
 .../java/io/trino/plugin/hudi/HudiMetadata.java    |   2 +-
 .../main/java/io/trino/plugin/hudi/HudiModule.java |   6 +-
 .../java/io/trino/plugin/hudi/HudiPageSource.java  |   5 +-
 .../trino/plugin/hudi/HudiPageSourceProvider.java  |  24 ++-
 .../main/java/io/trino/plugin/hudi/HudiSplit.java  |   2 +-
 .../plugin/hudi/reader/HudiTrinoReaderContext.java |   7 +-
 .../trino/plugin/hudi/util/HudiAvroSerializer.java |   2 +-
 packaging/hudi-trino-bundle/README.md              |  35 +++-
 packaging/hudi-trino-bundle/pom.xml                | 192 ++++++++++++++++++++-
 pom.xml                                            |   8 +-
 13 files changed, 271 insertions(+), 39 deletions(-)

diff --git a/hudi-trino-plugin/pom.xml b/hudi-trino-plugin/pom.xml
index 0db6338fbaa3..5f699d03a110 100644
--- a/hudi-trino-plugin/pom.xml
+++ b/hudi-trino-plugin/pom.xml
@@ -33,6 +33,9 @@
     <properties>
         <!-- Trino SPI / library version this connector compiles against. Bumped via root pom. -->
         <dep.trino.version>${trino.connector.version}</dep.trino.version>
+        <!-- Tests reuse Trino's internal test scaffolding, which only ships under the
+             test-jar classifier in snapshot builds. See root pom for details. -->
+        <dep.trino.test.version>${trino.connector.test.version}</dep.trino.test.version>
         <trino.parquet.version>1.15.2</trino.parquet.version>
         <!-- Connector requires JDK 25 to compile and run (matches Trino runtime requirement). -->
         <hudi.trino.java.version>25</hudi.trino.java.version>
@@ -340,6 +343,7 @@
         <dependency>
             <groupId>io.trino</groupId>
             <artifactId>trino-filesystem</artifactId>
+            <version>${dep.trino.test.version}</version>
             <type>test-jar</type>
             <scope>test</scope>
         </dependency>
@@ -353,6 +357,7 @@
         <dependency>
             <groupId>io.trino</groupId>
             <artifactId>trino-hive</artifactId>
+            <version>${dep.trino.test.version}</version>
             <type>test-jar</type>
             <scope>test</scope>
         </dependency>
@@ -366,6 +371,7 @@
         <dependency>
             <groupId>io.trino</groupId>
             <artifactId>trino-main</artifactId>
+            <version>${dep.trino.test.version}</version>
             <type>test-jar</type>
             <scope>test</scope>
         </dependency>
@@ -380,7 +386,7 @@
             <!-- BOM does not manage test-jar coordinate; declare the version explicitly. -->
             <groupId>io.trino</groupId>
             <artifactId>trino-spi</artifactId>
-            <version>${dep.trino.version}</version>
+            <version>${dep.trino.test.version}</version>
             <type>test-jar</type>
             <scope>test</scope>
         </dependency>
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiBaseFileOnlyPageSource.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiBaseFileOnlyPageSource.java
index 1180638a7cc4..a8955408ebf4 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiBaseFileOnlyPageSource.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiBaseFileOnlyPageSource.java
@@ -19,6 +19,7 @@ import io.trino.plugin.hudi.util.SynthesizedColumnHandler;
 import io.trino.spi.Page;
 import io.trino.spi.block.Block;
 import io.trino.spi.connector.ConnectorPageSource;
+import io.trino.spi.connector.SourcePage;
 
 import java.io.IOException;
 import java.util.HashMap;
@@ -84,9 +85,9 @@ public class HudiBaseFileOnlyPageSource
     }
 
     @Override
-    public Page getNextPage()
+    public SourcePage getNextSourcePage()
     {
-        Page physicalSourcePage = dataPageSource.getNextPage();
+        SourcePage physicalSourcePage = dataPageSource.getNextSourcePage();
         if (physicalSourcePage == null) {
             return null;
         }
@@ -108,7 +109,7 @@ public class HudiBaseFileOnlyPageSource
                 outputBlocks[i] = synthesizedColumnHandler.createRleSynthesizedBlock(outputColumn, positionCount);
             }
         }
-        return new Page(outputBlocks);
+        return SourcePage.create(new Page(outputBlocks));
     }
 
     @Override
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiConnectorFactory.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiConnectorFactory.java
index 0db65192baf8..226c7c507b4c 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiConnectorFactory.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiConnectorFactory.java
@@ -30,9 +30,9 @@ import io.trino.plugin.base.classloader.ClassLoaderSafeConnectorSplitManager;
 import io.trino.plugin.base.classloader.ClassLoaderSafeNodePartitioningProvider;
 import io.trino.plugin.base.jmx.MBeanServerModule;
 import io.trino.plugin.base.session.SessionPropertiesProvider;
-import io.trino.plugin.hive.NodeVersion;
 import io.trino.plugin.hive.metastore.HiveMetastoreModule;
 import io.trino.spi.NodeManager;
+import io.trino.spi.NodeVersion;
 import io.trino.spi.catalog.CatalogName;
 import io.trino.spi.classloader.ThreadContextClassLoader;
 import io.trino.spi.connector.Connector;
@@ -80,7 +80,7 @@ public class HudiConnectorFactory
                     new MBeanModule(),
                     new JsonModule(),
                     new HudiModule(),
-                    new HiveMetastoreModule(Optional.empty()),
+                    new HiveMetastoreModule(Optional.empty(), false),
                     new HudiFileSystemModule(catalogName, context),
                     new MBeanServerModule(),
                     module.orElse(EMPTY_MODULE),
@@ -123,21 +123,19 @@ public class HudiConnectorFactory
             extends AbstractConfigurationAwareModule
     {
         private final String catalogName;
-        private final NodeManager nodeManager;
-        private final OpenTelemetry openTelemetry;
+        private final ConnectorContext context;
 
         public HudiFileSystemModule(String catalogName, ConnectorContext context)
         {
             this.catalogName = requireNonNull(catalogName, "catalogName is null");
-            this.nodeManager = context.getNodeManager();
-            this.openTelemetry = context.getOpenTelemetry();
+            this.context = requireNonNull(context, "context is null");
         }
 
         @Override
         protected void setup(Binder binder)
         {
             boolean metadataCacheEnabled = buildConfigObject(HudiConfig.class).isMetadataCacheEnabled();
-            install(new FileSystemModule(catalogName, nodeManager, openTelemetry, metadataCacheEnabled));
+            install(new FileSystemModule(catalogName, context, metadataCacheEnabled));
         }
     }
 }
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiMetadata.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiMetadata.java
index 90bdd2c6e2fd..9f49718f77ba 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiMetadata.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiMetadata.java
@@ -278,7 +278,7 @@ public class HudiMetadata
     }
 
     @Override
-    public Optional<Object> getInfo(ConnectorTableHandle tableHandle)
+    public Optional<Object> getInfo(ConnectorSession session, ConnectorTableHandle tableHandle)
     {
         HudiTableHandle table = (HudiTableHandle) tableHandle;
         return Optional.of(new HudiTableInfo(table.getSchemaTableName(), table.getTableType().name(), table.getBasePath()));
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiModule.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiModule.java
index bd3c1923ebad..a696cd8218d9 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiModule.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiModule.java
@@ -26,7 +26,6 @@ import io.trino.plugin.base.session.SessionPropertiesProvider;
 import io.trino.plugin.hive.HideDeltaLakeTables;
 import io.trino.plugin.hive.HiveNodePartitioningProvider;
 import io.trino.plugin.hive.HiveTransactionHandle;
-import io.trino.plugin.hive.metastore.thrift.TranslateHiveViews;
 import io.trino.plugin.hive.parquet.ParquetReaderConfig;
 import io.trino.plugin.hive.parquet.ParquetWriterConfig;
 import io.trino.plugin.hudi.cache.HudiCacheKeyProvider;
@@ -44,7 +43,7 @@ import static com.google.inject.multibindings.Multibinder.newSetBinder;
 import static com.google.inject.multibindings.OptionalBinder.newOptionalBinder;
 import static io.airlift.concurrent.Threads.daemonThreadsNamed;
 import static io.airlift.configuration.ConfigBinder.configBinder;
-import static io.trino.plugin.base.ClosingBinder.closingBinder;
+import static io.airlift.bootstrap.ClosingBinder.closingBinder;
 import static java.util.concurrent.Executors.newCachedThreadPool;
 import static java.util.concurrent.Executors.newScheduledThreadPool;
 import static org.weakref.jmx.guice.ExportBinder.newExporter;
@@ -59,7 +58,8 @@ public class HudiModule
 
         configBinder(binder).bindConfig(HudiConfig.class);
 
-        binder.bind(boolean.class).annotatedWith(TranslateHiveViews.class).toInstance(false);
+        // Trino 480 removed the TranslateHiveViews annotation; thrift metastore now reads
+        // hive.hive-views.enabled config directly. No binding needed.
         binder.bind(boolean.class).annotatedWith(HideDeltaLakeTables.class).toInstance(false);
 
         newSetBinder(binder, SessionPropertiesProvider.class).addBinding().to(HudiSessionProperties.class).in(Scopes.SINGLETON);
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSource.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSource.java
index 5186341b0a50..a4c4b151c548 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSource.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSource.java
@@ -20,6 +20,7 @@ import io.trino.plugin.hudi.util.SynthesizedColumnHandler;
 import io.trino.spi.Page;
 import io.trino.spi.PageBuilder;
 import io.trino.spi.connector.ConnectorPageSource;
+import io.trino.spi.connector.SourcePage;
 import io.trino.spi.metrics.Metrics;
 import org.apache.avro.generic.IndexedRecord;
 import org.apache.hudi.common.table.read.HoodieFileGroupReader;
@@ -103,7 +104,7 @@ public class HudiPageSource
     }
 
     @Override
-    public Page getNextPage()
+    public SourcePage getNextSourcePage()
     {
         checkState(pageBuilder.isEmpty(), "PageBuilder is not empty at the beginning of a new page");
         while (recordIterator.hasNext()) {
@@ -112,7 +113,7 @@ public class HudiPageSource
 
         Page newPage = pageBuilder.build();
         pageBuilder.reset();
-        return newPage;
+        return SourcePage.create(newPage);
     }
 
     @Override
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSourceProvider.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSourceProvider.java
index 980739af6dcd..bae76b737a31 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSourceProvider.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSourceProvider.java
@@ -34,7 +34,6 @@ import io.trino.parquet.reader.ParquetReader;
 import io.trino.parquet.reader.RowGroupInfo;
 import io.trino.plugin.base.metrics.FileFormatDataSourceStats;
 import io.trino.plugin.hive.HiveColumnHandle;
-import io.trino.plugin.hive.ReaderColumns;
 import io.trino.plugin.hive.parquet.ParquetReaderConfig;
 import io.trino.plugin.hudi.file.HudiBaseFile;
 import io.trino.plugin.hudi.reader.HudiTrinoReaderContext;
@@ -81,7 +80,6 @@ import static io.trino.parquet.ParquetTypeUtils.getDescriptors;
 import static io.trino.parquet.predicate.PredicateUtils.buildPredicate;
 import static io.trino.parquet.predicate.PredicateUtils.getFilteredRowGroups;
 import static io.trino.plugin.hive.HiveColumnHandle.partitionColumnHandle;
-import static io.trino.plugin.hive.HivePageSourceProvider.projectBaseColumns;
 import static io.trino.plugin.hive.parquet.ParquetPageSourceFactory.ParquetReaderProvider;
 import static io.trino.plugin.hive.parquet.ParquetPageSourceFactory.createDataSource;
 import static io.trino.plugin.hive.parquet.ParquetPageSourceFactory.createParquetPageSource;
@@ -105,7 +103,6 @@ import static io.trino.plugin.hudi.HudiUtil.getLatestTableSchema;
 import static io.trino.plugin.hudi.HudiUtil.prependHudiMetaAndOrderingColumns;
 import static java.lang.String.format;
 import static java.util.Objects.requireNonNull;
-import static java.util.stream.Collectors.toUnmodifiableList;
 
 public class HudiPageSourceProvider
         implements ConnectorPageSourceProvider
@@ -191,14 +188,15 @@ public class HudiPageSourceProvider
                 hudiSplit,
                 fileSystem.newInputFile(Location.of(hudiBaseFileOpt.get().getPath()), hudiBaseFileOpt.get().getFileSize()),
                 dataSourceStats,
-                options
+                ParquetReaderOptions.builder(options)
                         .withIgnoreStatistics(isParquetIgnoreStatistics(session))
                         .withMaxReadBlockSize(getParquetMaxReadBlockSize(session))
                         .withMaxReadBlockRowCount(getParquetMaxReadBlockRowCount(session))
                         .withSmallFileThreshold(getParquetSmallFileThreshold(session))
                         .withUseColumnIndex(isParquetUseColumnIndex(session))
                         .withBloomFilter(useParquetBloomFilter(session))
-                        .withVectorizedDecodingEnabled(isParquetVectorizedDecodingEnabled(session)),
+                        .withVectorizedDecodingEnabled(isParquetVectorizedDecodingEnabled(session))
+                        .build(),
                 timeZone, dynamicFilter, isBaseFileOnly);
 
         SynthesizedColumnHandler synthesizedColumnHandler = SynthesizedColumnHandler.create(hudiSplit);
@@ -307,17 +305,14 @@ public class HudiPageSourceProvider
                     DOMAIN_COMPACTION_THRESHOLD,
                     options);
 
-            Optional<ReaderColumns> readerProjections = projectBaseColumns(columns);
-            List<HiveColumnHandle> baseColumns = readerProjections.map(projection ->
-                            projection.get().stream()
-                                    .map(HiveColumnHandle.class::cast)
-                                    .collect(toUnmodifiableList()))
-                    .orElse(columns);
+            // Trino 480 dropped projectBaseColumns/ReaderColumns; createParquetPageSource handles
+            // base-column projection internally via TransformConnectorPageSource.
             ParquetDataSourceId dataSourceId = dataSource.getId();
             ParquetDataSource finalDataSource = dataSource;
-            ParquetReaderProvider parquetReaderProvider = fields -> new ParquetReader(
+            ParquetReaderProvider parquetReaderProvider = (fields, appendRowNumberColumn) -> new ParquetReader(
                     Optional.ofNullable(fileMetaData.getCreatedBy()),
                     fields,
+                    appendRowNumberColumn,
                     rowGroups,
                     finalDataSource,
                     timeZone,
@@ -325,8 +320,9 @@ public class HudiPageSourceProvider
                     options,
                     exception -> handleException(dataSourceId, exception),
                     Optional.of(parquetPredicate),
-                    Optional.empty());
-            return createParquetPageSource(baseColumns, fileSchema, messageColumn, useColumnNames, parquetReaderProvider);
+                    Optional.empty(),
+                    parquetMetadata.getDecryptionContext());
+            return createParquetPageSource(columns, fileSchema, messageColumn, useColumnNames, parquetReaderProvider);
         }
         catch (IOException | RuntimeException e) {
             try {
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiSplit.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiSplit.java
index e2de10ca98a4..0f7b520e4e64 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiSplit.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiSplit.java
@@ -80,7 +80,7 @@ public class HudiSplit
         this.cachingHostAddresses = requireNonNull(cachingHostAddresses, "cachingHostAddresses is null");
     }
 
-    @Override
+    // Trino 480 removed getSplitInfo from ConnectorSplit. Method retained for local diagnostics.
     public Map<String, String> getSplitInfo()
     {
         return ImmutableMap.<String, String>builder()
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/reader/HudiTrinoReaderContext.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/reader/HudiTrinoReaderContext.java
index cb1bc2e09a83..ed9ddb261e4a 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/reader/HudiTrinoReaderContext.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/reader/HudiTrinoReaderContext.java
@@ -18,6 +18,7 @@ import io.trino.plugin.hudi.util.HudiAvroSerializer;
 import io.trino.plugin.hudi.util.SynthesizedColumnHandler;
 import io.trino.spi.Page;
 import io.trino.spi.connector.ConnectorPageSource;
+import io.trino.spi.connector.SourcePage;
 import org.apache.avro.generic.IndexedRecord;
 import org.apache.hudi.avro.AvroRecordContext;
 import org.apache.hudi.common.config.RecordMergeMode;
@@ -119,8 +120,10 @@ public class HudiTrinoReaderContext
                         return false;
                     }
 
-                    // Get next page and reset currentPosition
-                    currentPage = pageSource.getNextPage();
+                    // Get next page and reset currentPosition. Unwrap the SourcePage to the
+                    // underlying Page so the serializer's Block accessors keep working.
+                    SourcePage nextSourcePage = pageSource.getNextSourcePage();
+                    currentPage = nextSourcePage == null ? null : nextSourcePage.getPage();
                     currentPosition = 0;
 
                     // If no more pages are available
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/util/HudiAvroSerializer.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/util/HudiAvroSerializer.java
index 2fc020020252..24c653511fe0 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/util/HudiAvroSerializer.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/util/HudiAvroSerializer.java
@@ -135,7 +135,7 @@ public class HudiAvroSerializer
 
     public Object getValue(Page sourcePage, int channel, int position)
     {
-        return columnTypes.get(channel).getObjectValue(null, sourcePage.getBlock(channel), position);
+        return columnTypes.get(channel).getObjectValue(sourcePage.getBlock(channel), position);
     }
 
     public void buildRecordInPage(PageBuilder pageBuilder, IndexedRecord record)
diff --git a/packaging/hudi-trino-bundle/README.md b/packaging/hudi-trino-bundle/README.md
index 8f7d99dad154..e73f2dd0903e 100644
--- a/packaging/hudi-trino-bundle/README.md
+++ b/packaging/hudi-trino-bundle/README.md
@@ -1,3 +1,20 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
 # hudi-trino-bundle
 
 Shaded jar that ships the Trino-Hudi connector. Published as `org.apache.hudi:hudi-trino-bundle` (RFC-105). The Trino-side `HudiPlugin` shim depends on this artifact and loads `io.trino.plugin.hudi.HudiConnectorFactory` from it.
@@ -67,4 +84,20 @@ JAVA_HOME=$(/usr/libexec/java_home -v 25) \
   mvn deploy -Phudi-trino -pl hudi-trino-plugin,packaging/hudi-trino-bundle -DskipTests
 ```
 
-For release candidates, include this bundle in the RC validation step alongside the other published Hudi bundles.
\ No newline at end of file
+For release candidates, include this bundle in the RC validation step alongside the other published Hudi bundles.
+
+### Before publishing: switch Trino version off SNAPSHOT
+
+The root pom currently sets `<trino.connector.version>480-SNAPSHOT</trino.connector.version>` because the connector tests depend on `trino-*-tests.jar` artifacts, and Trino only publishes the test-jar classifier for snapshot builds (not for tagged releases). Shipping a bundle whose installed POM references a Trino SNAPSHOT version is awkward for downstream consumers.
+
+Before cutting a release, split the property so main jars resolve to a Trino release while test-jars stay on snapshot:
+
+1. Add a sibling property to the root pom:
+   ```
+   <trino.connector.version>480</trino.connector.version>
+   <trino.connector.test.version>480-SNAPSHOT</trino.connector.test.version>
+   ```
+2. In `hudi-trino-plugin/pom.xml`, change each `<type>test-jar</type>` dependency to use `${dep.trino.test.version}` instead of inheriting from the main version.
+3. Verify with `mvn dependency:tree -Phudi-trino -pl hudi-trino-plugin` that compile deps resolve at `480` and test deps at `480-SNAPSHOT`.
+
+Alternative if the release pipeline must not touch SNAPSHOT artifacts at all: build with `-Dmaven.test.skip=true` so test-jar deps are never resolved. Trade-off is no unit test run during the release build; CI should still exercise tests separately under the snapshot path.
\ No newline at end of file
diff --git a/packaging/hudi-trino-bundle/pom.xml b/packaging/hudi-trino-bundle/pom.xml
index c58d7ae3c80b..8c22384b9551 100644
--- a/packaging/hudi-trino-bundle/pom.xml
+++ b/packaging/hudi-trino-bundle/pom.xml
@@ -31,8 +31,23 @@
     <checkstyle.skip>true</checkstyle.skip>
     <main.basedir>${project.parent.basedir}</main.basedir>
     <skipTests>true</skipTests>
+    <dep.trino.version>${trino.connector.version}</dep.trino.version>
   </properties>
 
+  <dependencyManagement>
+    <dependencies>
+      <!-- Import Trino's parent POM as a BOM so the SPI artifacts declared as
+           provided below resolve to versions matching the connector code. -->
+      <dependency>
+        <groupId>io.trino</groupId>
+        <artifactId>trino-root</artifactId>
+        <version>${dep.trino.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+
   <build>
     <plugins>
       <plugin>
@@ -170,14 +185,95 @@
   <dependencies>
     <!-- Hoodie -->
     <dependency>
+      <!-- Plugin classes are shaded into this bundle. Its compile-scope deps on Trino,
+           Airlift, Jackson, Guice, OpenTelemetry are SPI-provided at Trino runtime and
+           must NOT leak into the bundle's transitive closure (trino-maven-plugin's
+           check-spi-dependencies enforces this on the consumer side). -->
       <groupId>org.apache.hudi</groupId>
       <artifactId>hudi-trino-plugin</artifactId>
       <version>${project.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>com.fasterxml.jackson.core</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>com.fasterxml.jackson.module</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>com.fasterxml.jackson.datatype</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>io.airlift</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>io.trino</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>com.google.inject</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>io.opentelemetry</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.openjdk.jol</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+        <!-- The connector does not use rocksdb (Hudi's local state stores), arrow, or lance.
+             These leak via hudi-common's compile deps and bloat the Trino server tar. -->
+        <exclusion>
+          <groupId>org.rocksdb</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.apache.arrow</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.lance</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
     <dependency>
+      <!-- Use the plain hudi-hadoop-mr artifact (already listed in the shade artifactSet).
+           hudi-hadoop-mr-bundle pulled lance-core, arrow-dataset, and rocksdbjni transitively
+           (~280MB), which the connector does not use and which blew the trino-server tar size cap. -->
       <groupId>org.apache.hudi</groupId>
-      <artifactId>hudi-hadoop-mr-bundle</artifactId>
+      <artifactId>hudi-hadoop-mr</artifactId>
       <version>${project.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>com.fasterxml.jackson.core</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>com.fasterxml.jackson.module</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>com.fasterxml.jackson.datatype</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.rocksdb</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.apache.arrow</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.lance</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
     <dependency>
       <groupId>org.apache.hudi</groupId>
@@ -188,12 +284,56 @@
           <artifactId>guava</artifactId>
           <groupId>com.google.guava</groupId>
         </exclusion>
+        <exclusion>
+          <groupId>com.fasterxml.jackson.core</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>com.fasterxml.jackson.module</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>com.fasterxml.jackson.datatype</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+        <!-- hudi-timeline-service pulls Jetty + javax.servlet-api, banned by Trino's enforcer.
+             The Trino connector does not use the timeline service. -->
+        <exclusion>
+          <groupId>org.apache.hudi</groupId>
+          <artifactId>hudi-timeline-service</artifactId>
+        </exclusion>
       </exclusions>
     </dependency>
     <dependency>
       <groupId>org.apache.hudi</groupId>
       <artifactId>hudi-java-client</artifactId>
       <version>${project.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>com.fasterxml.jackson.core</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>com.fasterxml.jackson.module</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>com.fasterxml.jackson.datatype</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.rocksdb</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.apache.arrow</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.lance</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
 
     <!-- Kryo -->
@@ -218,6 +358,16 @@
       <artifactId>avro</artifactId>
       <version>${avro.version}</version>
       <scope>compile</scope>
+      <exclusions>
+        <!-- Jackson is SPI-provided by Trino at runtime. Avro's transitive jackson-core/databind
+             must not leak into consumers (check-spi-dependencies). The shaded avro classes within
+             this bundle reference unrelocated com.fasterxml.jackson.* which the Trino runtime
+             supplies. -->
+        <exclusion>
+          <groupId>com.fasterxml.jackson.core</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
 
     <!--protobuf needs to be shaded because HBase 1.2.3 + native HFile reader needs it at runtime,
@@ -229,6 +379,46 @@
       <scope>${trino.bundle.bootstrap.scope}</scope>
     </dependency>
 
+    <!-- Trino SPI artifacts. Declared here as provided to override the compile-scope
+         transitives pulled in via hudi-trino-plugin -> trino-hive/etc. Trino's server
+         supplies these at runtime; bundling them would cause split-classloader bugs
+         and breaks the trino-maven-plugin:check-spi-dependencies enforcer. -->
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-annotations</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>io.airlift</groupId>
+      <artifactId>slice</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>io.opentelemetry</groupId>
+      <artifactId>opentelemetry-api</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>io.opentelemetry</groupId>
+      <artifactId>opentelemetry-api-incubator</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>io.opentelemetry</groupId>
+      <artifactId>opentelemetry-context</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>io.trino</groupId>
+      <artifactId>trino-spi</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.openjdk.jol</groupId>
+      <artifactId>jol-core</artifactId>
+      <scope>provided</scope>
+    </dependency>
+
   </dependencies>
   <profiles>
     <profile>
diff --git a/pom.xml b/pom.xml
index 75866f586f60..66b57428ee69 100644
--- a/pom.xml
+++ b/pom.xml
@@ -86,7 +86,7 @@
     <maven-surefire-plugin.version>3.5.4</maven-surefire-plugin.version>
     <maven-failsafe-plugin.version>3.5.4</maven-failsafe-plugin.version>
     <!-- bump to 3.5.3 to fix MSHADE-461 -->
-    <maven-shade-plugin.version>3.5.3</maven-shade-plugin.version>
+    <maven-shade-plugin.version>3.6.2</maven-shade-plugin.version>
     <maven-javadoc-plugin.version>3.12.0</maven-javadoc-plugin.version>
     <maven-compiler-plugin.version>3.14.1</maven-compiler-plugin.version>
     <maven-deploy-plugin.version>2.4</maven-deploy-plugin.version>
@@ -129,8 +129,12 @@
     <hive.avro.version>1.11.4</hive.avro.version>
     <presto.version>0.273</presto.version>
     <trino.version>390</trino.version>
-    <!-- Trino SPI version that hudi-trino-plugin (RFC-105) compiles against. -->
+    <!-- Trino SPI version that hudi-trino-plugin main code compiles against. -->
     <trino.connector.version>480</trino.connector.version>
+    <!-- Trino version used only for *-tests.jar classifier deps. Trino does not publish
+         test-jars for tagged releases, so this tracks a snapshot. Built locally via the
+         Trino source tree; consumers running tests need the snapshot in their m2. -->
+    <trino.connector.test.version>480-SNAPSHOT</trino.connector.test.version>
     <hive.exec.classifier>core</hive.exec.classifier>
     <metrics.version>4.1.1</metrics.version>
     <orc.spark.version>1.6.0</orc.spark.version>


(hudi) 32/36: feat(trino): apply LIMIT pushdown into HudiTableHandle

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit a37e4548f3ba58b876d86f4286550ea8da3ee193
Author: voon <vo...@gmail.com>
AuthorDate: Wed May 27 20:04:09 2026 +0800

    feat(trino): apply LIMIT pushdown into HudiTableHandle
    
    Mirrors the IcebergMetadata.applyLimit pattern. The connector now accepts
    a LIMIT hint from the planner and threads it through HudiTableHandle so
    HudiSplitSource can use it later to short-circuit partition / file-slice
    listing once row-count estimates from the Hudi metadata table become
    available.
    
    Changes:
    - HudiTableHandle: add OptionalLong limit to all three constructors plus
      @JsonProperty getter; introduce withLimit(long) for the apply-flow.
      applyPredicates propagates the existing limit through.
    - HudiMetadata.applyLimit: return Optional.empty() when the incoming limit
      is wider than the stored one (no work), otherwise return
      LimitApplicationResult with limitGuaranteed=false. Mirrors Iceberg.
    - Test constructors updated with OptionalLong.empty() for the new param.
    
    SUPPORTS_LIMIT_PUSHDOWN stays false in TestHudiConnectorTest because
    BaseConnectorTest.testLimitPushdown asserts Output -> TableScan with no
    Limit node, which requires limitGuaranteed=true; a multi-split connector
    cannot promise that without coordinator-side row-count coordination.
    Iceberg/Delta Lake/Hive all keep the flag false for the same reason.
---
 .../java/io/trino/plugin/hudi/HudiMetadata.java    | 22 ++++++++++++--
 .../java/io/trino/plugin/hudi/HudiTableHandle.java | 35 +++++++++++++++++++++-
 .../partition/TestHudiPartitionInfoLoader.java     |  1 +
 .../plugin/hudi/split/TestHudiSplitFactory.java    |  1 +
 4 files changed, 55 insertions(+), 4 deletions(-)

diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiMetadata.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiMetadata.java
index b959e6dac679..18ee1799f15c 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiMetadata.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiMetadata.java
@@ -38,6 +38,7 @@ import io.trino.spi.connector.ConnectorTableMetadata;
 import io.trino.spi.connector.ConnectorTableVersion;
 import io.trino.spi.connector.Constraint;
 import io.trino.spi.connector.ConstraintApplicationResult;
+import io.trino.spi.connector.LimitApplicationResult;
 import io.trino.spi.connector.RelationColumnsMetadata;
 import io.trino.spi.connector.SchemaTableName;
 import io.trino.spi.connector.SchemaTablePrefix;
@@ -64,6 +65,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.OptionalLong;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutorService;
@@ -107,9 +109,6 @@ import static org.apache.hudi.common.table.timeline.HoodieTimeline.DELTA_COMMIT_
 import static org.apache.hudi.common.table.timeline.HoodieTimeline.INDEXING_ACTION;
 import static org.apache.hudi.common.table.timeline.HoodieTimeline.REPLACE_COMMIT_ACTION;
 
-// TODO: implement applyLimit(...) to push LIMIT into HudiTableHandle so the split loader can
-//       short-circuit partition/file-slice listing once a row-count estimate covers the limit.
-//       Also flip SUPPORTS_LIMIT_PUSHDOWN to true in TestHudiConnectorTest once implemented.
 public class HudiMetadata
         implements ConnectorMetadata
 {
@@ -181,6 +180,7 @@ public class HudiMetadata
                 ImmutableSet.of(),
                 TupleDomain.all(),
                 TupleDomain.all(),
+                OptionalLong.empty(),
                 hudiTableSchema);
     }
 
@@ -264,6 +264,22 @@ public class HudiMetadata
                 false));
     }
 
+    @Override
+    public Optional<LimitApplicationResult<ConnectorTableHandle>> applyLimit(ConnectorSession session, ConnectorTableHandle handle, long limit)
+    {
+        HudiTableHandle table = (HudiTableHandle) handle;
+
+        if (table.getLimit().isPresent() && table.getLimit().getAsLong() <= limit) {
+            return Optional.empty();
+        }
+
+        // limitGuaranteed=false: the connector can't bound row count across splits without
+        // coordinator-side coordination. Trino keeps the Limit operator above the TableScan.
+        // The stored limit is consumed by HudiSplitSource for split-listing short-circuit when
+        // row-count estimates from the Hudi metadata table become available (TODO).
+        return Optional.of(new LimitApplicationResult<>(table.withLimit(limit), false, false));
+    }
+
     @Override
     public Map<String, ColumnHandle> getColumnHandles(ConnectorSession session, ConnectorTableHandle tableHandle)
     {
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiTableHandle.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiTableHandle.java
index 1b9efd1c6e18..cfe4801b2f38 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiTableHandle.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiTableHandle.java
@@ -33,6 +33,7 @@ import org.apache.hudi.util.Lazy;
 
 import java.util.List;
 import java.util.Optional;
+import java.util.OptionalLong;
 import java.util.Set;
 import java.util.function.Supplier;
 
@@ -54,6 +55,7 @@ public class HudiTableHandle
     private final Set<HiveColumnHandle> constraintColumns;
     private final TupleDomain<HiveColumnHandle> partitionPredicates;
     private final TupleDomain<HiveColumnHandle> regularPredicates;
+    private final OptionalLong limit;
     private final Optional<Lazy<HoodieSchema>> hudiTableSchema;
     // Coordinator-only
     private final transient Optional<Table> table;
@@ -70,11 +72,12 @@ public class HudiTableHandle
             @JsonProperty("orderingColumns") List<HiveColumnHandle> orderingColumns,
             @JsonProperty("partitionPredicates") TupleDomain<HiveColumnHandle> partitionPredicates,
             @JsonProperty("regularPredicates") TupleDomain<HiveColumnHandle> regularPredicates,
+            @JsonProperty("limit") OptionalLong limit,
             @JsonProperty("tableSchemaStr") String tableSchemaStr,
             @JsonProperty("latestCommitTime") String latestCommitTime)
     {
         this(Optional.empty(), Optional.empty(), schemaName, tableName, basePath, tableType, partitionColumns, Lazy.lazily(() -> orderingColumns), ImmutableSet.of(),
-                partitionPredicates, regularPredicates, buildTableSchema(tableSchemaStr), () -> latestCommitTime);
+                partitionPredicates, regularPredicates, limit, buildTableSchema(tableSchemaStr), () -> latestCommitTime);
     }
 
     public HudiTableHandle(
@@ -89,6 +92,7 @@ public class HudiTableHandle
             Set<HiveColumnHandle> constraintColumns,
             TupleDomain<HiveColumnHandle> partitionPredicates,
             TupleDomain<HiveColumnHandle> regularPredicates,
+            OptionalLong limit,
             Optional<Lazy<HoodieSchema>> hudiTableSchema)
     {
         this(
@@ -103,6 +107,7 @@ public class HudiTableHandle
                 constraintColumns,
                 partitionPredicates,
                 regularPredicates,
+                limit,
                 hudiTableSchema,
                 () -> lazyMetaClient
                         .get()
@@ -128,6 +133,7 @@ public class HudiTableHandle
             Set<HiveColumnHandle> constraintColumns,
             TupleDomain<HiveColumnHandle> partitionPredicates,
             TupleDomain<HiveColumnHandle> regularPredicates,
+            OptionalLong limit,
             Optional<Lazy<HoodieSchema>> hudiTableSchema,
             Supplier<String> latestCommitTimeSupplier)
     {
@@ -142,6 +148,7 @@ public class HudiTableHandle
         this.constraintColumns = requireNonNull(constraintColumns, "constraintColumns is null");
         this.partitionPredicates = requireNonNull(partitionPredicates, "partitionPredicates is null");
         this.regularPredicates = requireNonNull(regularPredicates, "regularPredicates is null");
+        this.limit = requireNonNull(limit, "limit is null");
         this.hudiTableSchema = requireNonNull(hudiTableSchema, "hudiTableSchema is null");
         this.lazyLatestCommitTime = Lazy.lazily(latestCommitTimeSupplier);
     }
@@ -254,6 +261,12 @@ public class HudiTableHandle
         return regularPredicates;
     }
 
+    @JsonProperty
+    public OptionalLong getLimit()
+    {
+        return limit;
+    }
+
     @JsonProperty
     public List<HiveColumnHandle> getOrderingColumns()
     {
@@ -282,6 +295,26 @@ public class HudiTableHandle
                 constraintColumns,
                 partitionPredicates.intersect(partitionTupleDomain),
                 regularPredicates.intersect(regularTupleDomain),
+                limit,
+                hudiTableSchema,
+                this::getLatestCommitTime);
+    }
+
+    HudiTableHandle withLimit(long newLimit)
+    {
+        return new HudiTableHandle(
+                table,
+                lazyMetaClient,
+                schemaName,
+                tableName,
+                basePath,
+                tableType,
+                partitionColumns,
+                lazyOrderingColumns,
+                constraintColumns,
+                partitionPredicates,
+                regularPredicates,
+                OptionalLong.of(newLimit),
                 hudiTableSchema,
                 this::getLatestCommitTime);
     }
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/partition/TestHudiPartitionInfoLoader.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/partition/TestHudiPartitionInfoLoader.java
index 765777cf855d..097d0285be7b 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/partition/TestHudiPartitionInfoLoader.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/partition/TestHudiPartitionInfoLoader.java
@@ -163,6 +163,7 @@ public class TestHudiPartitionInfoLoader
                 ImmutableList.of(),
                 TupleDomain.all(),
                 TupleDomain.all(),
+                java.util.OptionalLong.empty(),
                 "",
                 "101");
         HudiSplitWeightProvider weightProvider = new SizeBasedSplitWeightProvider(0.05, DataSize.of(128, MEGABYTE));
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/split/TestHudiSplitFactory.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/split/TestHudiSplitFactory.java
index 01a4208e9758..57937af6b0b3 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/split/TestHudiSplitFactory.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/split/TestHudiSplitFactory.java
@@ -182,6 +182,7 @@ public class TestHudiSplitFactory
                 ImmutableList.of(),
                 TupleDomain.all(),
                 TupleDomain.all(),
+                java.util.OptionalLong.empty(),
                 "",
                 "101");
     }


(hudi) 31/36: todo(trino): mark LIMIT pushdown as a follow-up

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit 0e58d4b79984068724079bb95e921554dc8c2243
Author: voon <vo...@gmail.com>
AuthorDate: Wed May 27 19:47:50 2026 +0800

    todo(trino): mark LIMIT pushdown as a follow-up
    
    Adds TODO markers in TestHudiConnectorTest (next to the
    SUPPORTS_LIMIT_PUSHDOWN=false declaration) and on HudiMetadata so future
    work to support applyLimit and short-circuit split listing in
    HudiSplitSource is discoverable from both ends.
---
 hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiMetadata.java | 3 +++
 .../src/test/java/io/trino/plugin/hudi/TestHudiConnectorTest.java      | 1 +
 2 files changed, 4 insertions(+)

diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiMetadata.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiMetadata.java
index 9f49718f77ba..b959e6dac679 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiMetadata.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiMetadata.java
@@ -107,6 +107,9 @@ import static org.apache.hudi.common.table.timeline.HoodieTimeline.DELTA_COMMIT_
 import static org.apache.hudi.common.table.timeline.HoodieTimeline.INDEXING_ACTION;
 import static org.apache.hudi.common.table.timeline.HoodieTimeline.REPLACE_COMMIT_ACTION;
 
+// TODO: implement applyLimit(...) to push LIMIT into HudiTableHandle so the split loader can
+//       short-circuit partition/file-slice listing once a row-count estimate covers the limit.
+//       Also flip SUPPORTS_LIMIT_PUSHDOWN to true in TestHudiConnectorTest once implemented.
 public class HudiMetadata
         implements ConnectorMetadata
 {
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiConnectorTest.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiConnectorTest.java
index 0aa6e0eaa733..d1a1460a2ed3 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiConnectorTest.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiConnectorTest.java
@@ -49,6 +49,7 @@ public class TestHudiConnectorTest
                  SUPPORTS_DELETE,
                  SUPPORTS_DEREFERENCE_PUSHDOWN,
                  SUPPORTS_INSERT,
+                 // TODO: implement LIMIT pushdown in HudiMetadata.applyLimit and flip this on.
                  SUPPORTS_LIMIT_PUSHDOWN,
                  SUPPORTS_MERGE,
                  SUPPORTS_RENAME_COLUMN,


(hudi) 25/36: fix(trino): add jdk.incubator.vector to surefire argLine

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit b714a5b74b9e7a0d9945c3fe0dffe918001e53ea
Author: voon <vo...@gmail.com>
AuthorDate: Wed May 27 00:15:56 2026 +0800

    fix(trino): add jdk.incubator.vector to surefire argLine
    
    Trino's BlockEncodingSimdSupport invokes the JDK Vector API
    (jdk/incubator/vector/VectorShape) for SIMD-accelerated block encoding.
    Vector is still an incubator module in JDK 25 and must be added to the
    test JVM via --add-modules.
    
    Override the argLine property at the plugin level so surefire's
    @{argLine} expansion picks up --add-modules jdk.incubator.vector
    alongside the parent's existing -Xmx / -Xms / -XX flags. Without this
    TestingTrinoServer fails to wire up Guice during coordinator module
    setup with NoClassDefFoundError.
---
 hudi-trino-plugin/pom.xml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/hudi-trino-plugin/pom.xml b/hudi-trino-plugin/pom.xml
index 3659bc9a7058..8581146761b0 100644
--- a/hudi-trino-plugin/pom.xml
+++ b/hudi-trino-plugin/pom.xml
@@ -41,6 +41,9 @@
         <hudi.trino.java.version>25</hudi.trino.java.version>
         <main.basedir>${project.parent.basedir}</main.basedir>
         <checkstyle.skip>true</checkstyle.skip>
+        <!-- Trino's BlockEncodingSimdSupport uses jdk.incubator.vector for SIMD; the
+             incubator module must be added explicitly on the test JVM command line. -->
+        <argLine>-Xmx4g -Xms128m -XX:-OmitStackTraceInFastThrow --add-modules jdk.incubator.vector</argLine>
     </properties>
 
     <dependencyManagement>


(hudi) 36/36: fix(integ): drop stale trino-coordinator-1 / trinobase refs after module removal

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit 045170cc25420f910b17bb372410a06f7b0a83e3
Author: voon <vo...@gmail.com>
AuthorDate: Thu May 28 21:07:47 2026 +0800

    fix(integ): drop stale trino-coordinator-1 / trinobase refs after module removal
    
    Removing the trino docker modules in 8fa5aba2f547 deleted the
    trino-coordinator-1 / trino-worker-1 services from the compose files
    but left depends_on / links entries on the adhoc-1 and adhoc-2
    spark adhoc services. docker compose now errors with
    
      service "adhoc-1" depends on undefined service "trino-coordinator-1":
      invalid compose project
    
    at integ-test 'up' phase, failing the hudi-integ-test module.
    
    - Drops "trino-coordinator-1" from the links list in both adhoc services
      in the amd64 and arm64 compose files.
    - Drops the unused TRINO_CLI_CMD export from sparkadhoc/adhoc.sh
      (the trino CLI no longer reaches a coordinator at this hostname).
    - Cleans the trinobase example commands and image references out of
      docker/README.md so a fresh reader is pointed at modules that still
      exist (prestobase as the example image).
---
 docker/README.md                                       | 18 +++++++++---------
 ...ocker-compose_hadoop284_hive2310_spark353_amd64.yml |  2 --
 ...ocker-compose_hadoop284_hive2310_spark353_arm64.yml |  2 --
 docker/hoodie/hadoop/sparkadhoc/adhoc.sh               |  2 --
 4 files changed, 9 insertions(+), 15 deletions(-)

diff --git a/docker/README.md b/docker/README.md
index f655f42dca8b..2e5e090af4ca 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -25,7 +25,7 @@ docker demo environment.
 ### Configs for assembling docker images - `/hoodie`
 
 The `/hoodie` folder contains all the configs for assembling necessary docker images. The name and repository of each
-docker image, e.g., `apachehudi/hudi-hadoop_2.8.4-trinobase_368`, is defined in the maven configuration file `pom.xml`.
+docker image, e.g., `apachehudi/hudi-hadoop_2.8.4-prestobase_0.232`, is defined in the maven configuration file `pom.xml`.
 
 ### Base images by Java version
 
@@ -39,9 +39,9 @@ docker image, e.g., `apachehudi/hudi-hadoop_2.8.4-trinobase_368`, is defined in
 The legacy Java 8 `base` module under `/hoodie/hadoop/base` is retained for historical reference only; Spark 2.x is no
 longer supported and `build_docker_images.sh` never selects it.
 
-Downstream Dockerfiles (`datanode`, `historyserver`, `hive_base`, `namenode`, `prestobase`, `trinobase`) pick the base
-via the `BASE_IMAGE_TAG` build arg (default `java11`). `build_docker_images.sh` sets it automatically; bare `docker
-build` invocations targeting the Java 17 base must pass `--build-arg BASE_IMAGE_TAG=java17`.
+Downstream Dockerfiles (`datanode`, `historyserver`, `hive_base`, `namenode`, `prestobase`) pick the base via the
+`BASE_IMAGE_TAG` build arg (default `java11`). `build_docker_images.sh` sets it automatically; bare `docker build`
+invocations targeting the Java 17 base must pass `--build-arg BASE_IMAGE_TAG=java17`.
 
 ### Docker compose config for the Demo - `/compose`
 
@@ -63,8 +63,8 @@ To build a single image target, you can run
 
 ```shell
 mvn clean pre-integration-test -DskipTests -Ddocker.compose.skip=true -Ddocker.build.skip=false -pl :<image_target> -am
-# For example, to build hudi-hadoop-trinobase-docker
-mvn clean pre-integration-test -DskipTests -Ddocker.compose.skip=true -Ddocker.build.skip=false -pl :hudi-hadoop-trinobase-docker -am
+# For example, to build hudi-hadoop-prestobase-docker
+mvn clean pre-integration-test -DskipTests -Ddocker.compose.skip=true -Ddocker.build.skip=false -pl :hudi-hadoop-prestobase-docker -am
 ```
 
 Alternatively, you can use `docker` cli directly under `hoodie/hadoop` to build images in a faster way. If you use this
@@ -84,8 +84,8 @@ steps in the next section).
 ```shell
 # Run under hoodie/hadoop, the <tag> is optional, "latest" by default
 docker build <image_folder_name> -t <hub-user>/<repo-name>[:<tag>]
-# For example, to build trinobase
-docker build trinobase -t apachehudi/hudi-hadoop_2.8.4-trinobase_368
+# For example, to build prestobase
+docker build prestobase -t apachehudi/hudi-hadoop_2.8.4-prestobase_0.232
 ```
 
 After new images are built, you can run the following script to bring up docker demo with your local images:
@@ -102,7 +102,7 @@ Hud registry designated by its name or tag:
 ```shell
 docker push <hub-user>/<repo-name>:<tag>
 # For example
-docker push apachehudi/hudi-hadoop_2.8.4-trinobase_368
+docker push apachehudi/hudi-hadoop_2.8.4-prestobase_0.232
 ```
 
 You can also easily push the image to the Docker Hub using Docker Desktop app: go to `Images`, search for the image by
diff --git a/docker/compose/docker-compose_hadoop284_hive2310_spark353_amd64.yml b/docker/compose/docker-compose_hadoop284_hive2310_spark353_amd64.yml
index 6e7c3c778e77..da887173053a 100644
--- a/docker/compose/docker-compose_hadoop284_hive2310_spark353_amd64.yml
+++ b/docker/compose/docker-compose_hadoop284_hive2310_spark353_amd64.yml
@@ -258,7 +258,6 @@ services:
       - "hive-metastore-postgresql"
       - "namenode"
       - "presto-coordinator-1"
-      - "trino-coordinator-1"
     volumes:
       - ${HUDI_WS}:/var/hoodie/ws
 
@@ -282,7 +281,6 @@ services:
       - "hive-metastore-postgresql"
       - "namenode"
       - "presto-coordinator-1"
-      - "trino-coordinator-1"
     volumes:
       - ${HUDI_WS}:/var/hoodie/ws
 
diff --git a/docker/compose/docker-compose_hadoop284_hive2310_spark353_arm64.yml b/docker/compose/docker-compose_hadoop284_hive2310_spark353_arm64.yml
index 678bc33f0449..e6b7c300e46f 100644
--- a/docker/compose/docker-compose_hadoop284_hive2310_spark353_arm64.yml
+++ b/docker/compose/docker-compose_hadoop284_hive2310_spark353_arm64.yml
@@ -248,7 +248,6 @@ services:
       - "hive-metastore-postgresql"
       - "namenode"
       - "presto-coordinator-1"
-      - "trino-coordinator-1"
     volumes:
       - ${HUDI_WS}:/var/hoodie/ws
 
@@ -271,7 +270,6 @@ services:
       - "hive-metastore-postgresql"
       - "namenode"
       - "presto-coordinator-1"
-      - "trino-coordinator-1"
     volumes:
       - ${HUDI_WS}:/var/hoodie/ws
 
diff --git a/docker/hoodie/hadoop/sparkadhoc/adhoc.sh b/docker/hoodie/hadoop/sparkadhoc/adhoc.sh
index 86fbbf4e775a..d2529e9ce165 100644
--- a/docker/hoodie/hadoop/sparkadhoc/adhoc.sh
+++ b/docker/hoodie/hadoop/sparkadhoc/adhoc.sh
@@ -23,12 +23,10 @@
 
 export SPARK_HOME=/opt/spark
 export PRESTO_CLI_CMD="/usr/local/bin/presto --server presto-coordinator-1:8090"
-export TRINO_CLI_CMD="/usr/local/bin/trino --server trino-coordinator-1:8091"
 
 date
 echo "SPARK HOME is : $SPARK_HOME"
 echo "PRESTO CLI CMD is : $PRESTO_CLI_CMD"
-echo "TRINO CLI CMD is : $TRINO_CLI_CMD"
 
 
 tail -f /dev/null


(hudi) 23/36: fix(trino): pin Jackson to 2.21.3 so Trino's airlift APIs resolve at runtime

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit b47c851a604434950ec032a908b8c322887e4091
Author: voon <vo...@gmail.com>
AuthorDate: Tue May 26 23:39:21 2026 +0800

    fix(trino): pin Jackson to 2.21.3 so Trino's airlift APIs resolve at runtime
    
    Hudi parent pom pins jackson-core / -databind / -annotations individually at
    2.15.2 (set via the Spark 3 fasterxml properties). Trino's airlift JSON
    codec calls StreamReadConstraints.Builder.maxNameLength(int), which was
    added in Jackson 2.16, so tests that exercise the page-source pipeline
    crash with NoSuchMethodError on the very first session builder
    construction.
    
    Direct entries in our plugin's dependencyManagement override the parent's
    individual pins (BOM imports do not -- parent direct entries win). Pin
    jackson-core / -databind to 2.21.3 (matches Trino airbase's
    dep.jackson.version) and jackson-annotations to 2.21 (the annotations
    artifact follows its own cadence and never publishes the .x patch).
---
 hudi-trino-plugin/pom.xml | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/hudi-trino-plugin/pom.xml b/hudi-trino-plugin/pom.xml
index 708daebc0188..c26f0bb6fbc9 100644
--- a/hudi-trino-plugin/pom.xml
+++ b/hudi-trino-plugin/pom.xml
@@ -55,6 +55,25 @@
                 <type>pom</type>
                 <scope>import</scope>
             </dependency>
+            <!-- Hudi parent pins jackson-* individually at 2.15.2, which predates
+                 StreamReadConstraints.Builder.maxNameLength (added in 2.16). Trino airlift needs it.
+                 Direct entries override parent pins; jackson-bom imports do not (parent direct entries win). -->
+            <dependency>
+                <groupId>com.fasterxml.jackson.core</groupId>
+                <artifactId>jackson-core</artifactId>
+                <version>2.21.3</version>
+            </dependency>
+            <dependency>
+                <groupId>com.fasterxml.jackson.core</groupId>
+                <artifactId>jackson-databind</artifactId>
+                <version>2.21.3</version>
+            </dependency>
+            <!-- jackson-annotations follows its own cadence; latest in the 2.21 line is 2.21 (no patch). -->
+            <dependency>
+                <groupId>com.fasterxml.jackson.core</groupId>
+                <artifactId>jackson-annotations</artifactId>
+                <version>2.21</version>
+            </dependency>
             <!-- Airbase manages junit-platform at 6.0.3 (paired with jupiter 6.x). Hudi manages
                  jupiter at 5.14.1 (paired with platform 1.14.1). Pin platform here to keep the
                  pair consistent; without this, surefire fails with OutputDirectoryCreator not found. -->


(hudi) 15/36: fix(trino): pin to released Trino 481 and gate test-jars behind a profile

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit 664e9f11299e6fe7686094b6b0c24367af1dfc74
Author: voon <vo...@gmail.com>
AuthorDate: Mon May 25 22:32:24 2026 +0800

    fix(trino): pin to released Trino 481 and gate test-jars behind a profile
    
    Pins trino.connector.version and trino.connector.test.version to the latest
    released Trino, 481. The previous 482-SNAPSHOT only existed in the developer
    local m2; CI starts with an empty m2 and cannot resolve the BOM, which made
    every version-managed dep in hudi-trino-plugin lose its version and the
    build collapse before any compilation.
    
    Moves the four test-jar dependencies (trino-spi, trino-filesystem,
    trino-hive, trino-main at the tests classifier) into a new
    hudi-trino-tests Maven profile. Trino does not publish three of those
    test-jars to Maven Central, so leaving them in the unconditional
    dependencies block made any reactor build with an empty m2 unresolvable.
    The profile is opt-in for developers who have a matching Trino source
    build in their m2. CI builds keep it off.
    
    hudi_trino_ci.yml switches from -DskipTests to -Dmaven.test.skip=true so
    test sources are not compiled (test imports come from the gated test-jars)
    and the build step resolves cleanly against Maven Central.
    
    README updated with the test profile activation flow.
---
 .github/workflows/hudi_trino_ci.yml |  7 ++--
 hudi-trino-plugin/README.md         | 15 +++++++
 hudi-trino-plugin/pom.xml           | 78 +++++++++++++++++++++----------------
 pom.xml                             | 10 ++---
 4 files changed, 69 insertions(+), 41 deletions(-)

diff --git a/.github/workflows/hudi_trino_ci.yml b/.github/workflows/hudi_trino_ci.yml
index 20464810aa28..28214a815833 100644
--- a/.github/workflows/hudi_trino_ci.yml
+++ b/.github/workflows/hudi_trino_ci.yml
@@ -37,6 +37,7 @@ jobs:
           distribution: 'temurin'
           cache: maven
       - name: Build connector
-        run: mvn $MVN_ARGS -Phudi-trino -pl hudi-trino-plugin -am install -DskipTests
-      - name: Run connector tests
-        run: mvn $MVN_ARGS -Phudi-trino -pl hudi-trino-plugin test
+        # Tests live behind the hudi-trino-tests profile (Trino does not publish the
+        # test-jars we need). -Dmaven.test.skip=true skips test compilation so the build
+        # resolves cleanly against Maven Central.
+        run: mvn $MVN_ARGS -Phudi-trino -pl hudi-trino-plugin -am install -Dmaven.test.skip=true
diff --git a/hudi-trino-plugin/README.md b/hudi-trino-plugin/README.md
index 37f465baea8a..9448986bf401 100644
--- a/hudi-trino-plugin/README.md
+++ b/hudi-trino-plugin/README.md
@@ -14,6 +14,21 @@ mvn -Phudi-trino -pl hudi-trino-plugin install
 
 Requires JDK 25 (enforced via `maven-enforcer-plugin`).
 
+## Running tests
+
+Tests depend on Trino test-jars (`trino-spi`, `trino-filesystem`, `trino-hive`, `trino-main` at the `tests` classifier). Trino does not publish three of those to Maven Central, so the test deps live behind the `hudi-trino-tests` profile, off by default.
+
+To run the tests:
+
+1. Build the matching Trino version locally so its `*-tests.jar` artifacts land in your `~/.m2` (see `trino.connector.test.version` in the root pom for the version to build).
+2. Activate both profiles:
+
+```
+mvn -Phudi-trino,hudi-trino-tests -pl hudi-trino-plugin test
+```
+
+CI keeps `hudi-trino-tests` off so the build resolves cleanly against Maven Central.
+
 ## IDE setup
 
 Only this module needs JDK 25. Leave the rest of Hudi on its native JDK (11 or 17) so you are not toggling the project default.
diff --git a/hudi-trino-plugin/pom.xml b/hudi-trino-plugin/pom.xml
index b76e5b60d774..a73341963b1f 100644
--- a/hudi-trino-plugin/pom.xml
+++ b/hudi-trino-plugin/pom.xml
@@ -367,57 +367,24 @@
             <scope>test</scope>
         </dependency>
 
-        <dependency>
-            <groupId>io.trino</groupId>
-            <artifactId>trino-filesystem</artifactId>
-            <version>${dep.trino.test.version}</version>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
-
         <dependency>
             <groupId>io.trino</groupId>
             <artifactId>trino-hdfs</artifactId>
             <scope>test</scope>
         </dependency>
 
-        <dependency>
-            <groupId>io.trino</groupId>
-            <artifactId>trino-hive</artifactId>
-            <version>${dep.trino.test.version}</version>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
-
         <dependency>
             <groupId>io.trino</groupId>
             <artifactId>trino-main</artifactId>
             <scope>test</scope>
         </dependency>
 
-        <dependency>
-            <groupId>io.trino</groupId>
-            <artifactId>trino-main</artifactId>
-            <version>${dep.trino.test.version}</version>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
-
         <dependency>
             <groupId>io.trino</groupId>
             <artifactId>trino-parser</artifactId>
             <scope>test</scope>
         </dependency>
 
-        <dependency>
-            <!-- BOM does not manage test-jar coordinate; declare the version explicitly. -->
-            <groupId>io.trino</groupId>
-            <artifactId>trino-spi</artifactId>
-            <version>${dep.trino.test.version}</version>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
-
         <dependency>
             <groupId>io.trino</groupId>
             <artifactId>trino-testing</artifactId>
@@ -605,4 +572,49 @@
             </plugin>
         </plugins>
     </build>
+
+    <profiles>
+        <!--
+            Test-only profile. Trino does not publish trino-spi / trino-filesystem /
+            trino-hive test-jars to Maven Central, and the published trino-main test-jar
+            still requires a matching SPI snapshot for the rest of the test classpath.
+            Activate this profile alongside hudi-trino when you have a locally-built
+            Trino snapshot in ~/.m2 (build via the Trino source tree and `mvn install`).
+            CI builds keep it off so the default reactor stays resolvable against
+            Maven Central.
+        -->
+        <profile>
+            <id>hudi-trino-tests</id>
+            <dependencies>
+                <dependency>
+                    <groupId>io.trino</groupId>
+                    <artifactId>trino-filesystem</artifactId>
+                    <version>${dep.trino.test.version}</version>
+                    <type>test-jar</type>
+                    <scope>test</scope>
+                </dependency>
+                <dependency>
+                    <groupId>io.trino</groupId>
+                    <artifactId>trino-hive</artifactId>
+                    <version>${dep.trino.test.version}</version>
+                    <type>test-jar</type>
+                    <scope>test</scope>
+                </dependency>
+                <dependency>
+                    <groupId>io.trino</groupId>
+                    <artifactId>trino-main</artifactId>
+                    <version>${dep.trino.test.version}</version>
+                    <type>test-jar</type>
+                    <scope>test</scope>
+                </dependency>
+                <dependency>
+                    <groupId>io.trino</groupId>
+                    <artifactId>trino-spi</artifactId>
+                    <version>${dep.trino.test.version}</version>
+                    <type>test-jar</type>
+                    <scope>test</scope>
+                </dependency>
+            </dependencies>
+        </profile>
+    </profiles>
 </project>
diff --git a/pom.xml b/pom.xml
index 323525c38e6f..0015f577ae3b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -130,11 +130,11 @@
     <presto.version>0.273</presto.version>
     <trino.version>390</trino.version>
     <!-- Trino SPI version that hudi-trino-plugin main code compiles against. -->
-    <trino.connector.version>482-SNAPSHOT</trino.connector.version>
-    <!-- Trino version used only for *-tests.jar classifier deps. Trino does not publish
-         test-jars for tagged releases, so this tracks a snapshot. Built locally via the
-         Trino source tree; consumers running tests need the snapshot in their m2. -->
-    <trino.connector.test.version>480-SNAPSHOT</trino.connector.test.version>
+    <trino.connector.version>481</trino.connector.version>
+    <!-- Trino version used by the hudi-trino-tests profile for *-tests.jar classifier deps.
+         Trino does not publish trino-spi / trino-filesystem / trino-hive test-jars; the
+         profile is opt-in and assumes a locally-built Trino snapshot in ~/.m2. -->
+    <trino.connector.test.version>481</trino.connector.test.version>
     <hive.exec.classifier>core</hive.exec.classifier>
     <metrics.version>4.1.1</metrics.version>
     <orc.spark.version>1.6.0</orc.spark.version>


(hudi) 33/36: docs(trino): update SUPPORTS_LIMIT_PUSHDOWN comment after applyLimit lands

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit fed1d02718e272cb0cedb4f16c9139c061ea1262
Author: voon <vo...@gmail.com>
AuthorDate: Wed May 27 20:23:06 2026 +0800

    docs(trino): update SUPPORTS_LIMIT_PUSHDOWN comment after applyLimit lands
    
    applyLimit is now implemented but the capability flag still stays false
    because BaseConnectorTest.testLimitPushdown requires limitGuaranteed=true
    (Output->TableScan with no Limit) and a multi-split connector cannot
    promise that. Reword the inline comment so it captures the real
    constraint instead of pointing at a TODO that no longer applies.
---
 .../src/test/java/io/trino/plugin/hudi/TestHudiConnectorTest.java    | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiConnectorTest.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiConnectorTest.java
index d1a1460a2ed3..acb85a2fe25f 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiConnectorTest.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiConnectorTest.java
@@ -49,7 +49,10 @@ public class TestHudiConnectorTest
                  SUPPORTS_DELETE,
                  SUPPORTS_DEREFERENCE_PUSHDOWN,
                  SUPPORTS_INSERT,
-                 // TODO: implement LIMIT pushdown in HudiMetadata.applyLimit and flip this on.
+                 // HudiMetadata.applyLimit returns limitGuaranteed=false (multi-split connector
+                 // cannot bound total rows across workers). BaseConnectorTest.testLimitPushdown
+                 // requires Output->TableScan with no Limit node, which needs guaranteed=true.
+                 // Stays off, matching Iceberg / Delta Lake / Hive.
                  SUPPORTS_LIMIT_PUSHDOWN,
                  SUPPORTS_MERGE,
                  SUPPORTS_RENAME_COLUMN,


(hudi) 11/36: fix(trino): port hudi-trino to Trino 482 SPI and restore metadata table fallback

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit 64baf5d2366537f017df2ad534980d93c4a760c9
Author: voon <vo...@gmail.com>
AuthorDate: Mon May 25 19:12:22 2026 +0800

    fix(trino): port hudi-trino to Trino 482 SPI and restore metadata table fallback
    
    Bumps trino.connector.version to 482-SNAPSHOT and ports the connector for the
    SPI drift since 480:
    
    - CachingHostAddressProvider was deleted upstream; drop its usage from the
      split factory / split manager / split source / background loader and pass
      empty host lists through HudiSplit construction.
    - Wire ConnectorContextModule (from io.trino.plugin.base) in
      HudiConnectorFactory instead of binding Node/NodeVersion/NodeManager/
      OpenTelemetry/Tracer/TypeManager/CatalogName ad-hoc.
    - Add io.airlift:configuration-testing as a test dependency for the
      config-tester used by the Trino-side test scaffolding.
    
    Restores the construction-aware metadata-table fallback in HudiSplitSource.
    The Hudi 1.1.0 bump replaced HoodieTableMetadata.create(...) with an explicit
    ternary keyed on tableConfig.isMetadataTableAvailable(), losing the 1.0.2
    factory's "construct HoodieBackedTableMetadata, check
    isMetadataTableInitialized(), fall back to FileSystemBackedTableMetadata
    otherwise" semantic. Open-codes that logic against the Hudi 1.3 public API so
    tables whose metadata table is configured but not initialized on disk still
    serve queries.
---
 hudi-trino-plugin/pom.xml                          |  6 +++++
 .../io/trino/plugin/hudi/HudiConnectorFactory.java | 18 +++----------
 .../io/trino/plugin/hudi/HudiSplitManager.java     |  9 ++-----
 .../java/io/trino/plugin/hudi/HudiSplitSource.java | 26 ++++++++++++++-----
 .../hudi/split/HudiBackgroundSplitLoader.java      |  4 +--
 .../trino/plugin/hudi/split/HudiSplitFactory.java  | 30 +++++++++-------------
 .../java/io/trino/plugin/hudi/HudiQueryRunner.java |  8 +++---
 .../io/trino/plugin/hudi/TestHudiPageSource.java   |  2 +-
 .../io/trino/plugin/hudi/TestHudiSmokeTest.java    |  2 +-
 pom.xml                                            |  2 +-
 10 files changed, 50 insertions(+), 57 deletions(-)

diff --git a/hudi-trino-plugin/pom.xml b/hudi-trino-plugin/pom.xml
index a2cc55fa1fe8..3dda76c1de18 100644
--- a/hudi-trino-plugin/pom.xml
+++ b/hudi-trino-plugin/pom.xml
@@ -356,6 +356,12 @@
             <scope>runtime</scope>
         </dependency>
 
+        <dependency>
+            <groupId>io.airlift</groupId>
+            <artifactId>configuration-testing</artifactId>
+            <scope>test</scope>
+        </dependency>
+
         <dependency>
             <groupId>io.airlift</groupId>
             <artifactId>junit-extensions</artifactId>
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiConnectorFactory.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiConnectorFactory.java
index 226c7c507b4c..cb5a565691c4 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiConnectorFactory.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiConnectorFactory.java
@@ -22,18 +22,14 @@ import io.airlift.bootstrap.Bootstrap;
 import io.airlift.bootstrap.LifeCycleManager;
 import io.airlift.configuration.AbstractConfigurationAwareModule;
 import io.airlift.json.JsonModule;
-import io.opentelemetry.api.OpenTelemetry;
-import io.opentelemetry.api.trace.Tracer;
 import io.trino.filesystem.manager.FileSystemModule;
+import io.trino.plugin.base.ConnectorContextModule;
 import io.trino.plugin.base.classloader.ClassLoaderSafeConnectorPageSourceProvider;
 import io.trino.plugin.base.classloader.ClassLoaderSafeConnectorSplitManager;
 import io.trino.plugin.base.classloader.ClassLoaderSafeNodePartitioningProvider;
 import io.trino.plugin.base.jmx.MBeanServerModule;
 import io.trino.plugin.base.session.SessionPropertiesProvider;
 import io.trino.plugin.hive.metastore.HiveMetastoreModule;
-import io.trino.spi.NodeManager;
-import io.trino.spi.NodeVersion;
-import io.trino.spi.catalog.CatalogName;
 import io.trino.spi.classloader.ThreadContextClassLoader;
 import io.trino.spi.connector.Connector;
 import io.trino.spi.connector.ConnectorContext;
@@ -41,7 +37,6 @@ import io.trino.spi.connector.ConnectorFactory;
 import io.trino.spi.connector.ConnectorNodePartitioningProvider;
 import io.trino.spi.connector.ConnectorPageSourceProvider;
 import io.trino.spi.connector.ConnectorSplitManager;
-import io.trino.spi.type.TypeManager;
 import org.weakref.jmx.guice.MBeanModule;
 
 import java.util.Map;
@@ -83,15 +78,8 @@ public class HudiConnectorFactory
                     new HiveMetastoreModule(Optional.empty(), false),
                     new HudiFileSystemModule(catalogName, context),
                     new MBeanServerModule(),
-                    module.orElse(EMPTY_MODULE),
-                    binder -> {
-                        binder.bind(OpenTelemetry.class).toInstance(context.getOpenTelemetry());
-                        binder.bind(Tracer.class).toInstance(context.getTracer());
-                        binder.bind(NodeVersion.class).toInstance(new NodeVersion(context.getNodeManager().getCurrentNode().getVersion()));
-                        binder.bind(NodeManager.class).toInstance(context.getNodeManager());
-                        binder.bind(TypeManager.class).toInstance(context.getTypeManager());
-                        binder.bind(CatalogName.class).toInstance(new CatalogName(catalogName));
-                    });
+                    new ConnectorContextModule(catalogName, context),
+                    module.orElse(EMPTY_MODULE));
 
             Injector injector = app
                     .doNotInitializeLogging()
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiSplitManager.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiSplitManager.java
index 79f03ccd07b2..8f774e3f5f15 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiSplitManager.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiSplitManager.java
@@ -17,7 +17,6 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.inject.Inject;
 import io.airlift.log.Logger;
-import io.trino.filesystem.cache.CachingHostAddressProvider;
 import io.trino.metastore.HiveMetastore;
 import io.trino.metastore.Partition;
 import io.trino.metastore.StorageFormat;
@@ -61,19 +60,16 @@ public class HudiSplitManager
     private final BiFunction<ConnectorIdentity, HiveTransactionHandle, HiveMetastore> metastoreProvider;
     private final ExecutorService executor;
     private final ScheduledExecutorService splitLoaderExecutorService;
-    private final CachingHostAddressProvider cachingHostAddressProvider;
 
     @Inject
     public HudiSplitManager(
             BiFunction<ConnectorIdentity, HiveTransactionHandle, HiveMetastore> metastoreProvider,
             @ForHudiSplitManager ExecutorService executor,
-            @ForHudiSplitSource ScheduledExecutorService splitLoaderExecutorService,
-            CachingHostAddressProvider cachingHostAddressProvider)
+            @ForHudiSplitSource ScheduledExecutorService splitLoaderExecutorService)
     {
         this.metastoreProvider = requireNonNull(metastoreProvider, "metastoreProvider is null");
         this.executor = requireNonNull(executor, "executor is null");
         this.splitLoaderExecutorService = requireNonNull(splitLoaderExecutorService, "splitLoaderExecutorService is null");
-        this.cachingHostAddressProvider = requireNonNull(cachingHostAddressProvider, "cachingHostAddressProvider is null");
     }
 
     @Override
@@ -103,8 +99,7 @@ public class HudiSplitManager
                 getMaxOutstandingSplits(session),
                 lazyAllPartitions,
                 dynamicFilter,
-                getDynamicFilteringWaitTimeout(session),
-                cachingHostAddressProvider);
+                getDynamicFilteringWaitTimeout(session));
         return new ClassLoaderSafeConnectorSplitSource(splitSource, HudiSplitManager.class.getClassLoader());
     }
 
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiSplitSource.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiSplitSource.java
index 6ea49d9baaf8..5e1700776b3f 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiSplitSource.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiSplitSource.java
@@ -19,7 +19,6 @@ import com.google.common.util.concurrent.Futures;
 import io.airlift.log.Logger;
 import io.airlift.units.DataSize;
 import io.airlift.units.Duration;
-import io.trino.filesystem.cache.CachingHostAddressProvider;
 import io.trino.metastore.Partition;
 import io.trino.plugin.hive.HiveColumnHandle;
 import io.trino.plugin.hive.HivePartitionKey;
@@ -94,8 +93,7 @@ public class HudiSplitSource
             int maxOutstandingSplits,
             Lazy<Map<String, Partition>> lazyPartitions,
             DynamicFilter dynamicFilter,
-            Duration dynamicFilteringWaitTimeoutMillis,
-            CachingHostAddressProvider cachingHostAddressProvider)
+            Duration dynamicFilteringWaitTimeoutMillis)
     {
         boolean enableMetadataTable = isHudiMetadataTableEnabled(session);
         Lazy<HoodieTableMetadata> lazyTableMetadata = Lazy.lazily(() -> {
@@ -106,9 +104,24 @@ public class HudiSplitSource
             HoodieTableMetaClient metaClient = tableHandle.getMetaClient();
             HoodieEngineContext engineContext = new HoodieLocalEngineContext(metaClient.getStorage().getConf());
 
-            HoodieTableMetadata tableMetadata = enableMetadataTable && tableHandle.getMetaClient().getTableConfig().isMetadataTableAvailable() ?
-                    new HoodieBackedTableMetadata(engineContext, tableHandle.getMetaClient().getStorage(), metadataConfig, metaClient.getBasePath().toString(), true) :
-                    new FileSystemBackedTableMetadata(engineContext, tableHandle.getMetaClient().getStorage(), metaClient.getBasePath().toString());
+            HoodieTableMetadata tableMetadata;
+            if (enableMetadataTable) {
+                HoodieBackedTableMetadata mdt = new HoodieBackedTableMetadata(
+                        engineContext, metaClient.getStorage(), metadataConfig, metaClient.getBasePath().toString(), true);
+                if (mdt.isMetadataTableInitialized()) {
+                    tableMetadata = mdt;
+                }
+                else {
+                    log.warn("Metadata table not initialized on disk for %s; falling back to FileSystemBackedTableMetadata",
+                            tableHandle.getSchemaTableName());
+                    tableMetadata = new FileSystemBackedTableMetadata(
+                            engineContext, metaClient.getStorage(), metaClient.getBasePath().toString());
+                }
+            }
+            else {
+                tableMetadata = new FileSystemBackedTableMetadata(
+                        engineContext, metaClient.getStorage(), metaClient.getBasePath().toString());
+            }
             log.info("Loaded table metadata for table: %s in %s ms", tableHandle.getSchemaTableName(), timer.endTimer());
             return tableMetadata;
         });
@@ -130,7 +143,6 @@ public class HudiSplitSource
                 lazyPartitions,
                 enableMetadataTable,
                 lazyTableMetadata,
-                cachingHostAddressProvider,
                 throwable -> {
                     trinoException.compareAndSet(null, new TrinoException(HUDI_CANNOT_OPEN_SPLIT,
                             "Failed to generate splits for " + tableHandle.getSchemaTableName(), throwable));
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/split/HudiBackgroundSplitLoader.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/split/HudiBackgroundSplitLoader.java
index 999e36f1ea0d..796413beb94f 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/split/HudiBackgroundSplitLoader.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/split/HudiBackgroundSplitLoader.java
@@ -19,7 +19,6 @@ import com.google.common.util.concurrent.ListenableFuture;
 import io.airlift.concurrent.BoundedExecutor;
 import io.airlift.log.Logger;
 import io.trino.filesystem.Location;
-import io.trino.filesystem.cache.CachingHostAddressProvider;
 import io.trino.metastore.Column;
 import io.trino.metastore.Partition;
 import io.trino.metastore.StorageFormat;
@@ -101,14 +100,13 @@ public class HudiBackgroundSplitLoader
             Lazy<Map<String, Partition>> lazyPartitionMap,
             boolean enableMetadataTable,
             Lazy<HoodieTableMetadata> lazyTableMetadata,
-            CachingHostAddressProvider cachingHostAddressProvider,
             Consumer<Throwable> errorListener)
     {
         this.tableHandle = requireNonNull(tableHandle, "tableHandle is null");
         this.hudiDirectoryLister = requireNonNull(hudiDirectoryLister, "hudiDirectoryLister is null");
         this.asyncQueue = requireNonNull(asyncQueue, "asyncQueue is null");
         this.splitGeneratorNumThreads = getSplitGeneratorParallelism(session);
-        this.hudiSplitFactory = new HudiSplitFactory(tableHandle, hudiSplitWeightProvider, getTargetSplitSize(session), cachingHostAddressProvider);
+        this.hudiSplitFactory = new HudiSplitFactory(tableHandle, hudiSplitWeightProvider, getTargetSplitSize(session));
         this.lazyPartitionMap = requireNonNull(lazyPartitionMap, "partitions is null");
         this.enableMetadataTable = enableMetadataTable;
         this.executor = requireNonNull(executor, "executor is null");
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/split/HudiSplitFactory.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/split/HudiSplitFactory.java
index 09dbf5bd5020..71c3f0c814f6 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/split/HudiSplitFactory.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/split/HudiSplitFactory.java
@@ -15,7 +15,6 @@ package io.trino.plugin.hudi.split;
 
 import com.google.common.collect.ImmutableList;
 import io.airlift.units.DataSize;
-import io.trino.filesystem.cache.CachingHostAddressProvider;
 import io.trino.plugin.hive.HivePartitionKey;
 import io.trino.plugin.hudi.HudiSplit;
 import io.trino.plugin.hudi.HudiTableHandle;
@@ -43,23 +42,20 @@ public class HudiSplitFactory
     private final HudiTableHandle hudiTableHandle;
     private final HudiSplitWeightProvider hudiSplitWeightProvider;
     private final DataSize targetSplitSize;
-    private final CachingHostAddressProvider cachingHostAddressProvider;
 
     public HudiSplitFactory(
             HudiTableHandle hudiTableHandle,
             HudiSplitWeightProvider hudiSplitWeightProvider,
-            DataSize targetSplitSize,
-            CachingHostAddressProvider cachingHostAddressProvider)
+            DataSize targetSplitSize)
     {
         this.hudiTableHandle = requireNonNull(hudiTableHandle, "hudiTableHandle is null");
         this.hudiSplitWeightProvider = requireNonNull(hudiSplitWeightProvider, "hudiSplitWeightProvider is null");
         this.targetSplitSize = requireNonNull(targetSplitSize, "targetSplitSize is null");
-        this.cachingHostAddressProvider = requireNonNull(cachingHostAddressProvider, "cachingHostAddressProvider is null");
     }
 
     public List<HudiSplit> createSplits(List<HivePartitionKey> partitionKeys, FileSlice fileSlice, String commitTime)
     {
-        return createHudiSplits(hudiTableHandle, partitionKeys, fileSlice, commitTime, hudiSplitWeightProvider, targetSplitSize, cachingHostAddressProvider);
+        return createHudiSplits(hudiTableHandle, partitionKeys, fileSlice, commitTime, hudiSplitWeightProvider, targetSplitSize);
     }
 
     /**
@@ -75,8 +71,7 @@ public class HudiSplitFactory
             FileSlice fileSlice,
             String commitTime,
             HudiSplitWeightProvider hudiSplitWeightProvider,
-            DataSize targetSplitSize,
-            CachingHostAddressProvider cachingHostAddressProvider)
+            DataSize targetSplitSize)
     {
         if (fileSlice.isEmpty()) {
             throw new TrinoException(HUDI_FILESYSTEM_ERROR, format("Not a valid file slice: %s", fileSlice));
@@ -85,9 +80,9 @@ public class HudiSplitFactory
         if (isCopyOnWriteOrReadOptimized(hudiTableHandle, fileSlice)) {
             // Handle MERGE_ON_READ tables to be read in read_optimized mode
             // IMPORTANT: These tables will have a COPY_ON_WRITE table type due to how `HudiTableTypeUtils#fromInputFormat`
-            return createSplitsForBaseFile(hudiTableHandle, partitionKeys, fileSlice, commitTime, hudiSplitWeightProvider, targetSplitSize, cachingHostAddressProvider);
+            return createSplitsForBaseFile(hudiTableHandle, partitionKeys, fileSlice, commitTime, hudiSplitWeightProvider, targetSplitSize);
         }
-        return createSplitForMergeOnRead(hudiTableHandle, partitionKeys, fileSlice, commitTime, hudiSplitWeightProvider, cachingHostAddressProvider);
+        return createSplitForMergeOnRead(hudiTableHandle, partitionKeys, fileSlice, commitTime, hudiSplitWeightProvider);
     }
 
     /**
@@ -108,15 +103,16 @@ public class HudiSplitFactory
             FileSlice fileSlice,
             String commitTime,
             HudiSplitWeightProvider hudiSplitWeightProvider,
-            DataSize targetSplitSize,
-            CachingHostAddressProvider cachingHostAddressProvider)
+            DataSize targetSplitSize)
     {
         checkArgument(fileSlice.getBaseFile().isPresent(),
                 "Hudi base file must exist if there are no log files in the file slice");
 
         HoodieBaseFile baseFile = fileSlice.getBaseFile().get();
         long fileSize = baseFile.getFileSize();
-        List<HostAddress> addresses = cachingHostAddressProvider.getHosts(baseFile.getPath(), ImmutableList.of());
+        // Trino 482 removed CachingHostAddressProvider; object-storage reads have no host
+        // affinity, so leave the address list empty. Workers are chosen by the scheduler.
+        List<HostAddress> addresses = ImmutableList.of();
 
         // If the file is empty, create a single split to represent it
         if (fileSize == 0) {
@@ -168,14 +164,12 @@ public class HudiSplitFactory
             List<HivePartitionKey> partitionKeys,
             FileSlice fileSlice,
             String commitTime,
-            HudiSplitWeightProvider hudiSplitWeightProvider,
-            CachingHostAddressProvider cachingHostAddressProvider)
+            HudiSplitWeightProvider hudiSplitWeightProvider)
     {
         // NOTE: Some file slices may not have base files
         Option<HoodieBaseFile> baseFileOption = fileSlice.getBaseFile();
-        List<HostAddress> addresses = baseFileOption
-                .map(baseFile -> cachingHostAddressProvider.getHosts(baseFile.getPath(), ImmutableList.of()))
-                .orElse(ImmutableList.of());
+        // Trino 482 removed CachingHostAddressProvider; no host affinity for object-storage reads.
+        List<HostAddress> addresses = ImmutableList.of();
 
         HudiSplit split = new HudiSplit(
                 baseFileOption.map(HudiBaseFile::of).orElse(null),
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/HudiQueryRunner.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/HudiQueryRunner.java
index 0114eb8400a2..e11efbf3a569 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/HudiQueryRunner.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/HudiQueryRunner.java
@@ -35,9 +35,9 @@ import java.util.Map;
 import java.util.Optional;
 
 import static io.trino.testing.TestingSession.testSessionBuilder;
-import static io.trino.testing.containers.Minio.MINIO_ACCESS_KEY;
+import static io.trino.testing.containers.Minio.MINIO_ROOT_USER;
 import static io.trino.testing.containers.Minio.MINIO_REGION;
-import static io.trino.testing.containers.Minio.MINIO_SECRET_KEY;
+import static io.trino.testing.containers.Minio.MINIO_ROOT_PASSWORD;
 import static java.util.Objects.requireNonNull;
 
 public final class HudiQueryRunner
@@ -60,8 +60,8 @@ public final class HudiQueryRunner
     {
         return new Builder("s3://" + hiveMinioDataLake.getBucketName() + "/")
                 .addConnectorProperty("fs.native-s3.enabled", "true")
-                .addConnectorProperty("s3.aws-access-key", MINIO_ACCESS_KEY)
-                .addConnectorProperty("s3.aws-secret-key", MINIO_SECRET_KEY)
+                .addConnectorProperty("s3.aws-access-key", MINIO_ROOT_USER)
+                .addConnectorProperty("s3.aws-secret-key", MINIO_ROOT_PASSWORD)
                 .addConnectorProperty("s3.region", MINIO_REGION)
                 .addConnectorProperty("s3.endpoint", hiveMinioDataLake.getMinio().getMinioAddress())
                 .addConnectorProperty("s3.path-style-access", "true");
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiPageSource.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiPageSource.java
index 8bb46f8fb3f5..9a36e7d38524 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiPageSource.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiPageSource.java
@@ -16,7 +16,7 @@ package io.trino.plugin.hudi;
 import io.trino.spi.connector.ConnectorPageSource;
 import org.junit.jupiter.api.Test;
 
-import static io.trino.spi.testing.InterfaceTestUtils.assertAllMethodsOverridden;
+import static io.trino.testing.InterfaceTestUtils.assertAllMethodsOverridden;
 
 public class TestHudiPageSource
 {
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiSmokeTest.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiSmokeTest.java
index dbb7195d38ef..31402d7fb48e 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiSmokeTest.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiSmokeTest.java
@@ -1305,7 +1305,7 @@ public class TestHudiSmokeTest
                 hudiSplit,
                 new LocalInputFile(parquetFile),
                 new FileFormatDataSourceStats(),
-                new ParquetReaderOptions(),
+                ParquetReaderOptions.builder().build(),
                 DateTimeZone.UTC, DynamicFilter.EMPTY, true)) {
             MaterializedResult result = materializeSourceDataStream(session, pageSource, List.of(columnType)).toTestTypes();
             assertThat(result.getMaterializedRows())
diff --git a/pom.xml b/pom.xml
index b9448e1a940a..9f6d33e1c01f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -130,7 +130,7 @@
     <presto.version>0.273</presto.version>
     <trino.version>390</trino.version>
     <!-- Trino SPI version that hudi-trino-plugin main code compiles against. -->
-    <trino.connector.version>480</trino.connector.version>
+    <trino.connector.version>482-SNAPSHOT</trino.connector.version>
     <!-- Trino version used only for *-tests.jar classifier deps. Trino does not publish
          test-jars for tagged releases, so this tracks a snapshot. Built locally via the
          Trino source tree; consumers running tests need the snapshot in their m2. -->


(hudi) 06/36: docs(trino): add hudi-trino-bundle README covering build and consume flow

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit 7ed8b07983ad55f6646ef9a329b3230641646f77
Author: voon <vo...@gmail.com>
AuthorDate: Fri May 22 18:33:21 2026 +0800

    docs(trino): add hudi-trino-bundle README covering build and consume flow
    
    Documents the two-step build (JDK 17 for base modules, JDK 25 for the
    connector and bundle), jar verification (HudiConnectorFactory present,
    io.trino.spi.Plugin manifest absent), and how the Trino-side trino-hudi
    shim picks up the published bundle.
---
 packaging/hudi-trino-bundle/README.md | 70 +++++++++++++++++++++++++++++++++++
 1 file changed, 70 insertions(+)

diff --git a/packaging/hudi-trino-bundle/README.md b/packaging/hudi-trino-bundle/README.md
new file mode 100644
index 000000000000..8f7d99dad154
--- /dev/null
+++ b/packaging/hudi-trino-bundle/README.md
@@ -0,0 +1,70 @@
+# hudi-trino-bundle
+
+Shaded jar that ships the Trino-Hudi connector. Published as `org.apache.hudi:hudi-trino-bundle` (RFC-105). The Trino-side `HudiPlugin` shim depends on this artifact and loads `io.trino.plugin.hudi.HudiConnectorFactory` from it.
+
+## What is inside
+
+Connector classes (unshaded, canonical FQN preserved):
+- `io.trino.plugin.hudi.*` from `hudi-trino-plugin`
+
+Hudi runtime jars (no relocation):
+- `hudi-common`, `hudi-client-common`, `hudi-java-client`, `hudi-hadoop-common`, `hudi-hadoop-mr`
+
+Shaded third-party libs (relocated under `org.apache.hudi.*` or the `trino.bundle.bootstrap.shade.prefix`):
+- Kryo, parquet-avro, avro, caffeine, commons-io, dropwizard metrics, jol-core, protobuf
+
+What is NOT inside:
+- `META-INF/services/io.trino.spi.Plugin`. That manifest lives only on the Trino-side `trino-hudi` shim; never ship it from this bundle.
+
+## Build
+
+Two-step because `hudi-common` etc. use Lombok 1.18.36 which is not compatible with JDK 25, while `hudi-trino-plugin` requires JDK 25 for the Trino SPI. See `hudi-trino-plugin/README.md` for the why.
+
+```
+# Step 1, on JDK 17: install Hudi base modules into ~/.m2
+JAVA_HOME=$(/usr/libexec/java_home -v 17) \
+  mvn install -DskipTests -pl hudi-common,hudi-io,hudi-hive-sync,hudi-sync-common,hudi-hadoop-common,hudi-client-common,hudi-java-client,packaging/hudi-hadoop-mr-bundle -am
+
+# Step 2, on JDK 25: build the connector and bundle
+JAVA_HOME=$(/usr/libexec/java_home -v 25) \
+  mvn install -Phudi-trino -pl hudi-trino-plugin,packaging/hudi-trino-bundle
+```
+
+The shaded jar lands at `packaging/hudi-trino-bundle/target/hudi-trino-bundle-1.3.0-SNAPSHOT.jar` and is also installed to `~/.m2/repository/org/apache/hudi/hudi-trino-bundle/`.
+
+## Verify the jar
+
+```
+JAR=packaging/hudi-trino-bundle/target/hudi-trino-bundle-1.3.0-SNAPSHOT.jar
+
+# Connector entrypoint must be present at its canonical FQN
+jar tf "$JAR" | grep -E 'io/trino/plugin/hudi/HudiConnectorFactory\.class$'
+
+# Plugin SPI manifest must NOT be present (only the Trino-side shim ships that)
+jar tf "$JAR" | grep -E 'META-INF/services/io\.trino\.spi\.Plugin$' && echo "FAIL: bundle leaks Plugin SPI" || echo "OK"
+```
+
+## Consume from Trino
+
+The Trino-side `plugin/trino-hudi` is already wired:
+- `<dependency>org.apache.hudi:hudi-trino-bundle</dependency>` in `plugin/trino-hudi/pom.xml`.
+- Version property `<dep.hudi-trino.version>` in the root Trino `pom.xml`. Bump this to point at a newer published bundle.
+
+Local development flow:
+```
+# In the Trino repo, after step 2 above has installed the bundle to ~/.m2
+./mvnw -pl :trino-hudi install
+```
+
+The Trino build resolves `hudi-trino-bundle` from your local `~/.m2`. For Hudi snapshots, ensure Apache's snapshot repo is enabled in your Maven settings; otherwise the version property must point at a released version.
+
+## Publish
+
+Follows the standard Hudi `mvn deploy` flow under the `hudi-trino` profile:
+
+```
+JAVA_HOME=$(/usr/libexec/java_home -v 25) \
+  mvn deploy -Phudi-trino -pl hudi-trino-plugin,packaging/hudi-trino-bundle -DskipTests
+```
+
+For release candidates, include this bundle in the RC validation step alongside the other published Hudi bundles.
\ No newline at end of file


(hudi) 26/36: fix(trino): exclude log4j-slf4j-impl from trino-filesystem-manager

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit b4f82bf7327b473fef4f622c882991ad9edcf01d
Author: voon <vo...@gmail.com>
AuthorDate: Wed May 27 01:37:41 2026 +0800

    fix(trino): exclude log4j-slf4j-impl from trino-filesystem-manager
    
    trino-filesystem-manager pulls trino-filesystem-alluxio ->
    alluxio-core-common -> log4j-slf4j-impl. airlift log-manager already
    brings log4j-to-slf4j. Log4j throws
    
      LoggingException: log4j-slf4j-impl cannot be present with log4j-to-slf4j
    
    during its static init when both bridges are on the classpath. That
    makes log4j's clinit fail, which cascades: every class with a logger
    field (avro SchemaBuilder, parquet Types$PrimitiveBuilder, jetty
    SslContextFactory$Client, hudi FSUtils, testcontainers MountableFile and
    DockerClientFactory, etc.) reports
    
      NoClassDefFoundError: Could not initialize class <X>
    
    at the first call site -- 20 of the 93 surefire tests in the run.
    
    Excluding log4j-slf4j-impl from trino-filesystem-manager keeps the
    airlift log-manager bridge as the single log4j route and unblocks the
    test JVM.
---
 hudi-trino-plugin/pom.xml | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/hudi-trino-plugin/pom.xml b/hudi-trino-plugin/pom.xml
index 8581146761b0..76864f3e80ea 100644
--- a/hudi-trino-plugin/pom.xml
+++ b/hudi-trino-plugin/pom.xml
@@ -175,6 +175,15 @@
         <dependency>
             <groupId>io.trino</groupId>
             <artifactId>trino-filesystem-manager</artifactId>
+            <exclusions>
+                <!-- alluxio-core-common pulls log4j-slf4j-impl; airlift log-manager pulls
+                     log4j-to-slf4j. Log4j refuses to start with both bridges present and the
+                     resulting clinit failure cascades through every class with a logger. -->
+                <exclusion>
+                    <groupId>org.apache.logging.log4j</groupId>
+                    <artifactId>log4j-slf4j-impl</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
 
         <dependency>


(hudi) 17/36: fix(trino): use :artifactId form for -pl in two-stage workflows

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit 20034a3e5f11cd20c9f3ffd1ba8c06bbf1e1a8b4
Author: voon <vo...@gmail.com>
AuthorDate: Tue May 26 16:15:41 2026 +0800

    fix(trino): use :artifactId form for -pl in two-stage workflows
    
    hudi-hive-sync and hudi-sync-common live under hudi-sync/, not at the top
    level, so `mvn -pl hudi-hive-sync` cannot resolve them. Switches to the
    `:artifactId` form, which lets Maven find each module by name regardless
    of directory layout.
---
 .github/workflows/hudi_trino_ci.yml     | 2 +-
 .github/workflows/hudi_trino_compat.yml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/hudi_trino_ci.yml b/.github/workflows/hudi_trino_ci.yml
index 477619a84431..7153b25c0734 100644
--- a/.github/workflows/hudi_trino_ci.yml
+++ b/.github/workflows/hudi_trino_ci.yml
@@ -40,7 +40,7 @@ jobs:
           distribution: 'temurin'
           cache: maven
       - name: Install upstream Hudi modules (JDK 17)
-        run: mvn $MVN_ARGS install -pl hudi-common,hudi-hive-sync,hudi-io,hudi-sync-common -am -Dmaven.test.skip=true -Drat.skip -Dcheckstyle.skip
+        run: mvn $MVN_ARGS install -pl :hudi-common,:hudi-hive-sync,:hudi-io,:hudi-sync-common -am -Dmaven.test.skip=true -Drat.skip -Dcheckstyle.skip
       - name: Set up JDK 25
         uses: actions/setup-java@v5
         with:
diff --git a/.github/workflows/hudi_trino_compat.yml b/.github/workflows/hudi_trino_compat.yml
index 51c6a3d01973..631465d6c794 100644
--- a/.github/workflows/hudi_trino_compat.yml
+++ b/.github/workflows/hudi_trino_compat.yml
@@ -34,7 +34,7 @@ jobs:
           cache: maven
       - name: Install upstream Hudi modules (JDK 17)
         working-directory: hudi
-        run: mvn $MVN_ARGS install -pl hudi-common,hudi-hive-sync,hudi-io,hudi-sync-common -am -Dmaven.test.skip=true -Drat.skip -Dcheckstyle.skip
+        run: mvn $MVN_ARGS install -pl :hudi-common,:hudi-hive-sync,:hudi-io,:hudi-sync-common -am -Dmaven.test.skip=true -Drat.skip -Dcheckstyle.skip
       - name: Set up JDK 25
         uses: actions/setup-java@v5
         with:


(hudi) 05/36: chore: Bump hudi-trino-plugin to 1.1.0

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit a775758e87b1c2bd07b915d6583c6d9de573f255
Author: voon <vo...@gmail.com>
AuthorDate: Wed May 13 12:17:55 2026 +0800

    chore: Bump hudi-trino-plugin to 1.1.0
---
 hudi-trino-plugin/pom.xml                          |  34 +++-
 .../java/io/trino/plugin/hudi/HudiMetadata.java    |   2 +
 .../java/io/trino/plugin/hudi/HudiPageSource.java  |  76 ++++++---
 .../trino/plugin/hudi/HudiPageSourceProvider.java  |  37 ++---
 .../java/io/trino/plugin/hudi/HudiSplitSource.java |   8 +-
 .../java/io/trino/plugin/hudi/HudiTableHandle.java |  15 +-
 .../main/java/io/trino/plugin/hudi/HudiUtil.java   | 121 +++++++++++---
 .../plugin/hudi/io/HudiTrinoFileReaderFactory.java |  25 ++-
 .../hudi/io/InlineSeekableDataInputStream.java     |   2 +-
 .../query/index/HudiColumnStatsIndexSupport.java   |  10 +-
 .../index/HudiPartitionStatsIndexSupport.java      |   9 +-
 .../query/index/HudiRecordLevelIndexSupport.java   |   4 +-
 .../query/index/HudiSecondaryIndexSupport.java     |   4 +-
 .../plugin/hudi/reader/HudiTrinoReaderContext.java | 126 ++++----------
 .../trino/plugin/hudi/reader/HudiTrinoRecord.java  | 183 ---------------------
 .../plugin/hudi/stats/TableMetadataReader.java     |  86 +++-------
 .../plugin/hudi/stats/TableStatisticsReader.java   |   4 +-
 .../hudi/TestHudiAlluxioCacheFileOperations.java   | 102 +++---------
 .../hudi/TestHudiMemoryCacheFileOperations.java    | 101 +++---------
 .../plugin/hudi/TestHudiNoCacheFileOperations.java | 101 +++---------
 .../io/trino/plugin/hudi/TestHudiSmokeTest.java    |   2 +-
 .../partition/TestHudiPartitionInfoLoader.java     |   1 +
 .../plugin/hudi/split/TestHudiSplitFactory.java    |   1 +
 .../hudi/testing/TpchHudiTablesInitializer.java    |  10 +-
 .../plugin/hudi/util/FileOperationAssertions.java  | 166 +++++++++++++++++++
 25 files changed, 558 insertions(+), 672 deletions(-)

diff --git a/hudi-trino-plugin/pom.xml b/hudi-trino-plugin/pom.xml
index be6f3a324369..9670f8a3e43d 100644
--- a/hudi-trino-plugin/pom.xml
+++ b/hudi-trino-plugin/pom.xml
@@ -57,7 +57,9 @@
 
     <dependencies>
         <dependency>
-            <!-- Used to test execution in task executor after de-serializing -->
+            <!-- Required for compilation: HoodieRecord implements KryoSerializable,
+                 so the compiler needs Kryo on classpath to verify the class hierarchy
+                 when loading HoodieRecord for static imports -->
             <groupId>com.esotericsoftware</groupId>
             <artifactId>kryo</artifactId>
             <version>4.0.2</version>
@@ -204,6 +206,7 @@
             <groupId>org.apache.hudi</groupId>
             <artifactId>hudi-io</artifactId>
             <version>${project.version}</version>
+            <classifier>shaded</classifier>
             <exclusions>
                 <exclusion>
                     <groupId>com.google.protobuf</groupId>
@@ -497,6 +500,23 @@
 
     <build>
         <plugins>
+            <plugin>
+                <groupId>org.basepom.maven</groupId>
+                <artifactId>duplicate-finder-maven-plugin</artifactId>
+                <configuration>
+                    <ignoredResourcePatterns>
+                        <!-- org.apache.hudi:hudi-client-common and org.apache.hudi:hudi-java-client log4j.properties duplicates -->
+                        <ignoredResourcePattern>log4j.properties</ignoredResourcePattern>
+                        <ignoredResourcePattern>log4j-surefire.properties</ignoredResourcePattern>
+                        <ignoredResource>google/protobuf/.*</ignoredResource>
+                    </ignoredResourcePatterns>
+                    <ignoredClassPatterns>
+                        <!-- org.apache.hudi:hudi-hadoop-common bundles parquet classes that conflict with org.apache.parquet:parquet-common.
+                             ParquetConfiguration is shaded/bundled inside hudi-hadoop-common, not a transitive dep, so Maven exclusions won't work. -->
+                        <ignoredClassPattern>org.apache.parquet.conf.ParquetConfiguration</ignoredClassPattern>
+                    </ignoredClassPatterns>
+                </configuration>
+            </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
@@ -527,6 +547,18 @@
                     </execution>
                 </executions>
             </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <configuration>
+                    <ignoredUnusedDeclaredDependencies>
+                        <!-- Kryo is not directly used but required for compilation:
+                             HoodieRecord implements KryoSerializable, so the compiler
+                             needs Kryo to verify the class hierarchy -->
+                        <ignoredUnusedDeclaredDependency>com.esotericsoftware:kryo</ignoredUnusedDeclaredDependency>
+                    </ignoredUnusedDeclaredDependencies>
+                </configuration>
+            </plugin>
         </plugins>
     </build>
 </project>
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiMetadata.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiMetadata.java
index 917c94ea43d9..2613be54ff09 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiMetadata.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiMetadata.java
@@ -91,6 +91,7 @@ import static io.trino.plugin.hudi.HudiTableProperties.LOCATION_PROPERTY;
 import static io.trino.plugin.hudi.HudiTableProperties.PARTITIONED_BY_PROPERTY;
 import static io.trino.plugin.hudi.HudiUtil.buildTableMetaClient;
 import static io.trino.plugin.hudi.HudiUtil.getLatestTableSchema;
+import static io.trino.plugin.hudi.HudiUtil.getOrderingColumnHandles;
 import static io.trino.spi.StandardErrorCode.NOT_SUPPORTED;
 import static io.trino.spi.StandardErrorCode.QUERY_REJECTED;
 import static io.trino.spi.StandardErrorCode.UNSUPPORTED_TABLE_TYPE;
@@ -173,6 +174,7 @@ public class HudiMetadata
                 table.getStorage().getLocation(),
                 hoodieTableType,
                 getPartitionKeyColumnHandles(table, typeManager),
+                Lazy.lazily(() -> getOrderingColumnHandles(table, typeManager, lazyMetaClient, NANOSECONDS)),
                 ImmutableSet.of(),
                 TupleDomain.all(),
                 TupleDomain.all(),
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSource.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSource.java
index e81887414425..5186341b0a50 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSource.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSource.java
@@ -23,6 +23,7 @@ import io.trino.spi.connector.ConnectorPageSource;
 import io.trino.spi.metrics.Metrics;
 import org.apache.avro.generic.IndexedRecord;
 import org.apache.hudi.common.table.read.HoodieFileGroupReader;
+import org.apache.hudi.common.util.collection.ClosableIterator;
 
 import java.io.IOException;
 import java.util.List;
@@ -41,6 +42,7 @@ public class HudiPageSource
     PageBuilder pageBuilder;
     HudiAvroSerializer avroSerializer;
     List<HiveColumnHandle> columnHandles;
+    ClosableIterator<IndexedRecord> recordIterator;
 
     public HudiPageSource(
             ConnectorPageSource pageSource,
@@ -51,11 +53,29 @@ public class HudiPageSource
     {
         this.pageSource = pageSource;
         this.fileGroupReader = fileGroupReader;
-        this.initFileGroupReader();
         this.readerContext = readerContext;
         this.columnHandles = columnHandles;
         this.pageBuilder = new PageBuilder(columnHandles.stream().map(HiveColumnHandle::getType).toList());
         this.avroSerializer = new HudiAvroSerializer(columnHandles, synthesizedColumnHandler);
+        try {
+            this.recordIterator = fileGroupReader.getClosableIterator();
+        }
+        catch (IOException e) {
+            // Clean up resources on initialization failure
+            try {
+                fileGroupReader.close();
+            }
+            catch (IOException closeException) {
+                e.addSuppressed(closeException);
+            }
+            try {
+                pageSource.close();
+            }
+            catch (IOException closeException) {
+                e.addSuppressed(closeException);
+            }
+            throw new RuntimeException("Failed to initialize file group reader!", e);
+        }
     }
 
     @Override
@@ -79,25 +99,15 @@ public class HudiPageSource
     @Override
     public boolean isFinished()
     {
-        try {
-            return !fileGroupReader.hasNext();
-        }
-        catch (IOException e) {
-            throw new RuntimeException(e);
-        }
+        return !recordIterator.hasNext();
     }
 
     @Override
     public Page getNextPage()
     {
         checkState(pageBuilder.isEmpty(), "PageBuilder is not empty at the beginning of a new page");
-        try {
-            while (fileGroupReader.hasNext()) {
-                avroSerializer.buildRecordInPage(pageBuilder, fileGroupReader.next());
-            }
-        }
-        catch (IOException e) {
-            throw new RuntimeException(e);
+        while (recordIterator.hasNext()) {
+            avroSerializer.buildRecordInPage(pageBuilder, recordIterator.next());
         }
 
         Page newPage = pageBuilder.build();
@@ -115,8 +125,32 @@ public class HudiPageSource
     public void close()
             throws IOException
     {
-        fileGroupReader.close();
-        pageSource.close();
+        IOException closeException = null;
+
+        recordIterator.close();
+
+        try {
+            fileGroupReader.close();
+        }
+        catch (IOException e) {
+            closeException = e;
+        }
+
+        try {
+            pageSource.close();
+        }
+        catch (IOException e) {
+            if (closeException == null) {
+                closeException = e;
+            }
+            else {
+                closeException.addSuppressed(e);
+            }
+        }
+
+        if (closeException != null) {
+            throw closeException;
+        }
     }
 
     @Override
@@ -130,14 +164,4 @@ public class HudiPageSource
     {
         return pageSource.getMetrics();
     }
-
-    protected void initFileGroupReader()
-    {
-        try {
-            this.fileGroupReader.initRecordIterators();
-        }
-        catch (IOException e) {
-            throw new RuntimeException("Failed to initialize file group reader!", e);
-        }
-    }
 }
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSourceProvider.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSourceProvider.java
index 9b8411fdf907..1553b8389a0b 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSourceProvider.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSourceProvider.java
@@ -38,8 +38,6 @@ import io.trino.plugin.hive.ReaderColumns;
 import io.trino.plugin.hive.parquet.ParquetReaderConfig;
 import io.trino.plugin.hudi.file.HudiBaseFile;
 import io.trino.plugin.hudi.reader.HudiTrinoReaderContext;
-import io.trino.plugin.hudi.storage.HudiTrinoStorage;
-import io.trino.plugin.hudi.storage.TrinoStorageConfiguration;
 import io.trino.plugin.hudi.util.SynthesizedColumnHandler;
 import io.trino.spi.TrinoException;
 import io.trino.spi.connector.ColumnHandle;
@@ -57,7 +55,6 @@ import org.apache.avro.generic.IndexedRecord;
 import org.apache.hudi.common.model.HoodieTableType;
 import org.apache.hudi.common.table.HoodieTableMetaClient;
 import org.apache.hudi.common.table.read.HoodieFileGroupReader;
-import org.apache.hudi.common.util.Option;
 import org.apache.hudi.common.util.ValidationUtils;
 import org.apache.hudi.storage.StoragePath;
 import org.apache.parquet.column.ColumnDescriptor;
@@ -104,7 +101,7 @@ import static io.trino.plugin.hudi.HudiUtil.buildTableMetaClient;
 import static io.trino.plugin.hudi.HudiUtil.constructSchema;
 import static io.trino.plugin.hudi.HudiUtil.convertToFileSlice;
 import static io.trino.plugin.hudi.HudiUtil.getLatestTableSchema;
-import static io.trino.plugin.hudi.HudiUtil.prependHudiMetaColumns;
+import static io.trino.plugin.hudi.HudiUtil.prependHudiMetaAndOrderingColumns;
 import static java.lang.String.format;
 import static java.util.Objects.requireNonNull;
 import static java.util.stream.Collectors.toUnmodifiableList;
@@ -184,7 +181,7 @@ public class HudiPageSourceProvider
         // The `columns` list could be empty when count(*) is issued,
         // prepending hoodie meta columns for Hudi split with log files
         // to allow a non-empty dataPageSource to be returned
-        List<HiveColumnHandle> hudiMetaAndDataColumnHandles = prependHudiMetaColumns(dataColumnHandles);
+        List<HiveColumnHandle> hudiMetaAndDataColumnHandles = prependHudiMetaAndOrderingColumns(hudiTableHandle, dataColumnHandles);
 
         TrinoFileSystem fileSystem = fileSystemFactory.create(session);
         ConnectorPageSource dataPageSource = createPageSource(
@@ -219,8 +216,9 @@ public class HudiPageSourceProvider
         // TODO: Move this into HudiTableHandle
         HoodieTableMetaClient metaClient = buildTableMetaClient(
                 fileSystemFactory.create(session), hudiTableHandle.getSchemaTableName().toString(), hudiTableHandle.getBasePath());
-
         HudiTrinoReaderContext readerContext = new HudiTrinoReaderContext(
+                metaClient.getStorageConf(),
+                metaClient.getTableConfig(),
                 dataPageSource,
                 dataColumnHandles,
                 hudiMetaAndDataColumnHandles,
@@ -232,21 +230,18 @@ public class HudiPageSourceProvider
         // Construct an Avro schema for log file reader
         Schema requestedSchema = constructSchema(dataSchema, hudiMetaAndDataColumnHandles.stream().map(HiveColumnHandle::getName).toList());
         HoodieFileGroupReader<IndexedRecord> fileGroupReader =
-                new HoodieFileGroupReader<>(
-                        readerContext,
-                        new HudiTrinoStorage(fileSystemFactory.create(session), new TrinoStorageConfiguration()),
-                        hudiTableHandle.getBasePath(),
-                        hudiTableHandle.getLatestCommitTime(),
-                        convertToFileSlice(hudiSplit, hudiTableHandle.getBasePath()),
-                        dataSchema,
-                        requestedSchema,
-                        Option.empty(),
-                        metaClient,
-                        metaClient.getTableConfig().getProps(),
-                        start,
-                        length,
-                        false);
-
+                HoodieFileGroupReader.<IndexedRecord>newBuilder()
+                        .withReaderContext(readerContext)
+                        .withHoodieTableMetaClient(metaClient)
+                        .withFileSlice(convertToFileSlice(hudiSplit, hudiTableHandle.getBasePath()))
+                        .withDataSchema(dataSchema)
+                        .withRequestedSchema(requestedSchema)
+                        .withLatestCommitTime(hudiTableHandle.getLatestCommitTime())
+                        .withProps(metaClient.getTableConfig().getProps())
+                        .withShouldUseRecordPosition(false)
+                        .withStart(start)
+                        .withLength(length)
+                        .build();
         return new HudiPageSource(
                 dataPageSource,
                 fileGroupReader,
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiSplitSource.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiSplitSource.java
index 278ca2e463c7..6ea49d9baaf8 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiSplitSource.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiSplitSource.java
@@ -44,6 +44,8 @@ import org.apache.hudi.common.engine.HoodieEngineContext;
 import org.apache.hudi.common.engine.HoodieLocalEngineContext;
 import org.apache.hudi.common.table.HoodieTableMetaClient;
 import org.apache.hudi.common.util.HoodieTimer;
+import org.apache.hudi.metadata.FileSystemBackedTableMetadata;
+import org.apache.hudi.metadata.HoodieBackedTableMetadata;
 import org.apache.hudi.metadata.HoodieTableMetadata;
 import org.apache.hudi.util.Lazy;
 
@@ -104,9 +106,9 @@ public class HudiSplitSource
             HoodieTableMetaClient metaClient = tableHandle.getMetaClient();
             HoodieEngineContext engineContext = new HoodieLocalEngineContext(metaClient.getStorage().getConf());
 
-            HoodieTableMetadata tableMetadata = HoodieTableMetadata.create(
-                    engineContext,
-                    tableHandle.getMetaClient().getStorage(), metadataConfig, metaClient.getBasePath().toString(), true);
+            HoodieTableMetadata tableMetadata = enableMetadataTable && tableHandle.getMetaClient().getTableConfig().isMetadataTableAvailable() ?
+                    new HoodieBackedTableMetadata(engineContext, tableHandle.getMetaClient().getStorage(), metadataConfig, metaClient.getBasePath().toString(), true) :
+                    new FileSystemBackedTableMetadata(engineContext, tableHandle.getMetaClient().getStorage(), metaClient.getBasePath().toString());
             log.info("Loaded table metadata for table: %s in %s ms", tableHandle.getSchemaTableName(), timer.endTimer());
             return tableMetadata;
         });
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiTableHandle.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiTableHandle.java
index 75ae962286a4..f9f828bcca55 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiTableHandle.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiTableHandle.java
@@ -49,6 +49,7 @@ public class HudiTableHandle
     private final String basePath;
     private final HoodieTableType tableType;
     private final List<HiveColumnHandle> partitionColumns;
+    private final Lazy<List<HiveColumnHandle>> lazyOrderingColumns;
     // Used only for validation when config property hudi.query-partition-filter-required is enabled
     private final Set<HiveColumnHandle> constraintColumns;
     private final TupleDomain<HiveColumnHandle> partitionPredicates;
@@ -66,12 +67,13 @@ public class HudiTableHandle
             @JsonProperty("basePath") String basePath,
             @JsonProperty("tableType") HoodieTableType tableType,
             @JsonProperty("partitionColumns") List<HiveColumnHandle> partitionColumns,
+            @JsonProperty("orderingColumns") List<HiveColumnHandle> orderingColumns,
             @JsonProperty("partitionPredicates") TupleDomain<HiveColumnHandle> partitionPredicates,
             @JsonProperty("regularPredicates") TupleDomain<HiveColumnHandle> regularPredicates,
             @JsonProperty("tableSchemaStr") String tableSchemaStr,
             @JsonProperty("latestCommitTime") String latestCommitTime)
     {
-        this(Optional.empty(), Optional.empty(), schemaName, tableName, basePath, tableType, partitionColumns, ImmutableSet.of(),
+        this(Optional.empty(), Optional.empty(), schemaName, tableName, basePath, tableType, partitionColumns, Lazy.lazily(() -> orderingColumns), ImmutableSet.of(),
                 partitionPredicates, regularPredicates, buildTableSchema(tableSchemaStr), () -> latestCommitTime);
     }
 
@@ -83,6 +85,7 @@ public class HudiTableHandle
             String basePath,
             HoodieTableType tableType,
             List<HiveColumnHandle> partitionColumns,
+            Lazy<List<HiveColumnHandle>> lazyOrderingColumns,
             Set<HiveColumnHandle> constraintColumns,
             TupleDomain<HiveColumnHandle> partitionPredicates,
             TupleDomain<HiveColumnHandle> regularPredicates,
@@ -96,6 +99,7 @@ public class HudiTableHandle
                 basePath,
                 tableType,
                 partitionColumns,
+                lazyOrderingColumns,
                 constraintColumns,
                 partitionPredicates,
                 regularPredicates,
@@ -120,6 +124,7 @@ public class HudiTableHandle
             String basePath,
             HoodieTableType tableType,
             List<HiveColumnHandle> partitionColumns,
+            Lazy<List<HiveColumnHandle>> lazyOrderingColumns,
             Set<HiveColumnHandle> constraintColumns,
             TupleDomain<HiveColumnHandle> partitionPredicates,
             TupleDomain<HiveColumnHandle> regularPredicates,
@@ -133,6 +138,7 @@ public class HudiTableHandle
         this.basePath = requireNonNull(basePath, "basePath is null");
         this.tableType = requireNonNull(tableType, "tableType is null");
         this.partitionColumns = requireNonNull(partitionColumns, "partitionColumns is null");
+        this.lazyOrderingColumns = requireNonNull(lazyOrderingColumns, "lazyOrderingColumns is null");
         this.constraintColumns = requireNonNull(constraintColumns, "constraintColumns is null");
         this.partitionPredicates = requireNonNull(partitionPredicates, "partitionPredicates is null");
         this.regularPredicates = requireNonNull(regularPredicates, "regularPredicates is null");
@@ -248,6 +254,12 @@ public class HudiTableHandle
         return regularPredicates;
     }
 
+    @JsonProperty
+    public List<HiveColumnHandle> getOrderingColumns()
+    {
+        return lazyOrderingColumns.get();
+    }
+
     public SchemaTableName getSchemaTableName()
     {
         return schemaTableName(schemaName, tableName);
@@ -266,6 +278,7 @@ public class HudiTableHandle
                 basePath,
                 tableType,
                 partitionColumns,
+                lazyOrderingColumns,
                 constraintColumns,
                 partitionPredicates.intersect(partitionTupleDomain),
                 regularPredicates.intersect(regularTupleDomain),
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiUtil.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiUtil.java
index 8eb10de4cc4c..52e594bbc4be 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiUtil.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiUtil.java
@@ -22,10 +22,13 @@ import io.trino.cache.EvictableCacheBuilder;
 import io.trino.filesystem.FileIterator;
 import io.trino.filesystem.Location;
 import io.trino.filesystem.TrinoFileSystem;
+import io.trino.metastore.Column;
 import io.trino.metastore.HivePartition;
 import io.trino.metastore.HiveType;
+import io.trino.metastore.Table;
 import io.trino.plugin.hive.HiveColumnHandle;
 import io.trino.plugin.hive.HivePartitionKey;
+import io.trino.plugin.hive.HiveTimestampPrecision;
 import io.trino.plugin.hive.avro.AvroHiveFileUtils;
 import io.trino.plugin.hudi.storage.HudiTrinoStorage;
 import io.trino.plugin.hudi.storage.TrinoStorageConfiguration;
@@ -35,9 +38,12 @@ import io.trino.spi.connector.SchemaTableName;
 import io.trino.spi.predicate.Domain;
 import io.trino.spi.predicate.NullableValue;
 import io.trino.spi.predicate.TupleDomain;
+import io.trino.spi.type.TypeManager;
 import io.trino.spi.type.VarcharType;
 import org.apache.avro.Schema;
 import org.apache.avro.SchemaBuilder;
+import org.apache.hudi.common.config.RecordMergeMode;
+import org.apache.hudi.common.data.HoodiePairData;
 import org.apache.hudi.common.fs.FSUtils;
 import org.apache.hudi.common.model.FileSlice;
 import org.apache.hudi.common.model.HoodieBaseFile;
@@ -47,18 +53,25 @@ import org.apache.hudi.common.model.HoodieLogFile;
 import org.apache.hudi.common.table.HoodieTableMetaClient;
 import org.apache.hudi.common.table.TableSchemaResolver;
 import org.apache.hudi.common.table.view.HoodieTableFileSystemView;
+import org.apache.hudi.common.util.CollectionUtils;
 import org.apache.hudi.common.util.HoodieTimer;
+import org.apache.hudi.common.util.Option;
+import org.apache.hudi.common.util.collection.Pair;
 import org.apache.hudi.exception.TableNotFoundException;
 import org.apache.hudi.metadata.HoodieTableMetadata;
 import org.apache.hudi.storage.StoragePath;
+import org.apache.hudi.util.Lazy;
 
 import java.io.IOException;
 import java.io.UncheckedIOException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
@@ -66,7 +79,11 @@ import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 import static io.airlift.slice.SizeOf.estimatedSizeOf;
+import static io.trino.plugin.hive.HiveColumnHandle.ColumnType.REGULAR;
+import static io.trino.plugin.hive.HiveColumnHandle.createBaseColumn;
 import static io.trino.plugin.hive.HiveErrorCode.HIVE_INVALID_METADATA;
+import static io.trino.plugin.hive.util.HiveTypeUtil.getType;
+import static io.trino.plugin.hive.util.HiveTypeUtil.typeSupported;
 import static io.trino.plugin.hive.util.HiveUtil.checkCondition;
 import static io.trino.plugin.hive.util.HiveUtil.parsePartitionValue;
 import static io.trino.plugin.hive.util.SerdeConstants.LIST_COLUMNS;
@@ -77,11 +94,14 @@ import static io.trino.plugin.hudi.HudiErrorCode.HUDI_META_CLIENT_ERROR;
 import static io.trino.plugin.hudi.HudiErrorCode.HUDI_SCHEMA_ERROR;
 import static io.trino.plugin.hudi.HudiErrorCode.HUDI_UNSUPPORTED_FILE_FORMAT;
 import static java.lang.Math.toIntExact;
+import static org.apache.hudi.common.model.HoodieRecord.PARTITION_PATH_METADATA_FIELD;
 import static org.apache.hudi.common.model.HoodieRecord.RECORD_KEY_METADATA_FIELD;
-import static org.apache.hudi.common.model.HoodieRecord.RECORD_KEY_META_FIELD_ORD;
 
 public final class HudiUtil
 {
+    public static final List<String> HOODIE_META_COLUMNS =
+            CollectionUtils.createImmutableList(RECORD_KEY_METADATA_FIELD, PARTITION_PATH_METADATA_FIELD);
+
     private static final Logger log = Logger.get(HudiUtil.class);
     private static final Cache<Schema, Map<String, Schema.Field>> SCHEMA_FIELD_CACHE =
             EvictableCacheBuilder.newBuilder()
@@ -291,7 +311,6 @@ public final class HudiUtil
      *   <li>First, attempts an exact match on the column name.</li>
      *   <li>If not found, falls back to a case-insensitive match using a cached lookup table</li>
      * </ul>
-     * <p>
      *
      * @param columnName Column name to search for.
      * @param schema Avro {@link Schema} in which to search.
@@ -321,29 +340,33 @@ public final class HudiUtil
                 "Failed to get column " + columnName + " from table schema");
     }
 
-    public static List<HiveColumnHandle> prependHudiMetaColumns(List<HiveColumnHandle> dataColumns)
+    public static List<HiveColumnHandle> prependHudiMetaAndOrderingColumns(HudiTableHandle tableHandle, List<HiveColumnHandle> dataColumns)
     {
-        //For efficient lookup
-        Set<String> dataColumnNames = dataColumns.stream()
+        Set<String> existingColumns = dataColumns.stream()
                 .map(HiveColumnHandle::getName)
-                .collect(Collectors.toSet());
-
-        // If Hudi record key meta column is already present, return the original list
-        if (dataColumnNames.contains(RECORD_KEY_METADATA_FIELD)) {
-            return dataColumns;
-        }
+                .collect(Collectors.toCollection(HashSet::new));
 
         List<HiveColumnHandle> columns = new ArrayList<>();
 
-        // Create and prepend the new HiveColumnHandle for the record key column
-        columns.add(new HiveColumnHandle(
-                RECORD_KEY_METADATA_FIELD,
-                RECORD_KEY_META_FIELD_ORD,
-                HiveType.HIVE_STRING,
-                VarcharType.VARCHAR,
-                Optional.empty(),
-                HiveColumnHandle.ColumnType.REGULAR,
-                Optional.empty()));
+        // Add missing Hudi meta columns first
+        for (int i = 0; i < HOODIE_META_COLUMNS.size(); i++) {
+            String metaColumn = HOODIE_META_COLUMNS.get(i);
+            if (existingColumns.add(metaColumn)) { // add() returns false if already present
+                columns.add(new HiveColumnHandle(
+                        metaColumn,
+                        i,
+                        HiveType.HIVE_STRING,
+                        VarcharType.VARCHAR,
+                        Optional.empty(),
+                        HiveColumnHandle.ColumnType.REGULAR,
+                        Optional.empty()));
+            }
+        }
+
+        // Add missing ordering columns next
+        tableHandle.getOrderingColumns().stream()
+                .filter(col -> existingColumns.add(col.getName()))
+                .forEach(columns::add);
 
         // Add all the original data columns after the new meta columns
         columns.addAll(dataColumns);
@@ -389,4 +412,62 @@ public final class HudiUtil
             throw new TrinoException(HUDI_FILESYSTEM_ERROR, e);
         }
     }
+
+    public static List<HiveColumnHandle> getOrderingColumnHandles(Table table, TypeManager typeManager, Lazy<HoodieTableMetaClient> lazyMetaClient, HiveTimestampPrecision timestampPrecision)
+    {
+        RecordMergeMode recordMergeMode = lazyMetaClient.get().getTableConfig().getRecordMergeMode();
+        if (Objects.isNull(recordMergeMode) || recordMergeMode.equals(RecordMergeMode.COMMIT_TIME_ORDERING)) {
+            // if commit time ordering is enabled, return empty list
+            return Collections.emptyList();
+        }
+
+        ImmutableList.Builder<HiveColumnHandle> columns = ImmutableList.builder();
+        List<String> orderingColumnNames = lazyMetaClient.get().getTableConfig().getOrderingFields();
+
+        int hiveColumnIndex = 0;
+        for (Column field : table.getDataColumns()) {
+            // ignore unsupported types rather than failing
+            if (orderingColumnNames.contains(field.getName())) {
+                HiveType hiveType = field.getType();
+                if (typeSupported(hiveType.getTypeInfo(), table.getStorage().getStorageFormat())) {
+                    columns.add(createBaseColumn(field.getName(), hiveColumnIndex, hiveType, getType(hiveType, typeManager, timestampPrecision), REGULAR, field.getComment()));
+                }
+            }
+            hiveColumnIndex++;
+        }
+
+        return columns.build();
+    }
+
+    /**
+     * Converts the given {@link HoodiePairData} into a {@link Map}.
+     * <p>
+     * Special handling is applied for null keys:
+     * <ul>
+     *   <li>If a key is null, it is stored in the map as a {@code null} entry.</li>
+     *   <li>If multiple entries share the same key (including null), the latest value overwrites the previous one.</li>
+     * </ul>
+     *
+     * @param pairData the HoodiePairData containing key-value pairs
+     * @param <K> the type of keys maintained by the resulting map
+     * @param <V> the type of mapped values
+     * @return a {@link Map} containing all key-value pairs from the input data
+     */
+    public static <K, V> Map<K, V> collectAsMap(HoodiePairData<K, V> pairData)
+    {
+        // Map each pair to (Option<Pair.key>, V) to handle null keys uniformly
+        // If there are multiple entries sharing the same key, use the incoming one
+        return pairData.mapToPair(pair ->
+                        Pair.of(
+                                Option.ofNullable(pair.getKey()),
+                                pair.getValue()))
+                .collectAsList()
+                .stream()
+                .collect(HashMap::new,
+                        (map, pair) -> {
+                            K key = pair.getKey().orElse(null);
+                            map.put(key, pair.getValue());
+                        },
+                        HashMap::putAll);
+    }
 }
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/io/HudiTrinoFileReaderFactory.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/io/HudiTrinoFileReaderFactory.java
index 7e8bb967ffc7..3571de43d79e 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/io/HudiTrinoFileReaderFactory.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/io/HudiTrinoFileReaderFactory.java
@@ -16,12 +16,14 @@ package io.trino.plugin.hudi.io;
 import org.apache.avro.Schema;
 import org.apache.hudi.common.config.HoodieConfig;
 import org.apache.hudi.common.util.Option;
+import org.apache.hudi.io.storage.HFileReaderFactory;
 import org.apache.hudi.io.storage.HoodieAvroBootstrapFileReader;
 import org.apache.hudi.io.storage.HoodieFileReader;
 import org.apache.hudi.io.storage.HoodieFileReaderFactory;
 import org.apache.hudi.io.storage.HoodieNativeAvroHFileReader;
 import org.apache.hudi.storage.HoodieStorage;
 import org.apache.hudi.storage.StoragePath;
+import org.apache.hudi.storage.StoragePathInfo;
 
 import java.io.IOException;
 
@@ -45,7 +47,11 @@ public class HudiTrinoFileReaderFactory
             Option<Schema> schemaOption)
             throws IOException
     {
-        return new HoodieNativeAvroHFileReader(storage, path, schemaOption);
+        HFileReaderFactory readerFactory = HFileReaderFactory.builder()
+                .withStorage(storage).withProps(hoodieConfig.getProps())
+                .withPath(path).build();
+        return HoodieNativeAvroHFileReader.builder()
+                .readerFactory(readerFactory).path(path).schema(schemaOption).build();
     }
 
     @Override
@@ -56,7 +62,22 @@ public class HudiTrinoFileReaderFactory
             Option<Schema> schemaOption)
             throws IOException
     {
-        return new HoodieNativeAvroHFileReader(this.storage, content, schemaOption);
+        HFileReaderFactory readerFactory = HFileReaderFactory.builder()
+                .withStorage(storage).withProps(hoodieConfig.getProps())
+                .withContent(content).build();
+        return HoodieNativeAvroHFileReader.builder()
+                .readerFactory(readerFactory).path(path).schema(schemaOption).build();
+    }
+
+    @Override
+    protected HoodieFileReader newHFileFileReader(HoodieConfig hoodieConfig, StoragePathInfo pathInfo, Option<Schema> schemaOption)
+            throws IOException
+    {
+        HFileReaderFactory readerFactory = HFileReaderFactory.builder()
+                .withStorage(storage).withProps(hoodieConfig.getProps())
+                .withPath(pathInfo.getPath()).build();
+        return HoodieNativeAvroHFileReader.builder()
+                .readerFactory(readerFactory).path(pathInfo.getPath()).schema(schemaOption).build();
     }
 
     @Override
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/io/InlineSeekableDataInputStream.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/io/InlineSeekableDataInputStream.java
index f75ec7a55f90..b67b0012905b 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/io/InlineSeekableDataInputStream.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/io/InlineSeekableDataInputStream.java
@@ -26,7 +26,7 @@ import java.io.IOException;
  * Example InlineFS URL:
  * <pre>
  * inlinefs://tests_7af7f087-c807-4f5e-a759-65fd9c21063b/hudi_multi_fg_pt_v8_mor/.hoodie/metadata/column_stats/
- * .col-stats-0001-0_20250429145946675.log.1_1-120-382/local/?start_offset=8036&length=6959
+ * .col-stats-0001-0_20250429145946675.log.1_1-120-382/local/?start_offset=8036&amp;length=6959
  * </pre>
  * <p>
  * Key behaviors:
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/query/index/HudiColumnStatsIndexSupport.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/query/index/HudiColumnStatsIndexSupport.java
index 0d1c9eaa6cd0..7626272db612 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/query/index/HudiColumnStatsIndexSupport.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/query/index/HudiColumnStatsIndexSupport.java
@@ -30,13 +30,14 @@ import io.trino.spi.type.Type;
 import io.trino.spi.type.VarcharType;
 import org.apache.avro.generic.GenericRecord;
 import org.apache.hudi.avro.model.HoodieMetadataColumnStats;
+import org.apache.hudi.common.data.HoodieListData;
 import org.apache.hudi.common.model.BaseFile;
 import org.apache.hudi.common.model.FileSlice;
 import org.apache.hudi.common.model.HoodieIndexDefinition;
 import org.apache.hudi.common.table.HoodieTableMetaClient;
 import org.apache.hudi.common.table.HoodieTableVersion;
 import org.apache.hudi.common.util.HoodieTimer;
-import org.apache.hudi.common.util.hash.ColumnIndexID;
+import org.apache.hudi.metadata.ColumnStatsIndexPrefixRawKey;
 import org.apache.hudi.metadata.HoodieTableMetadata;
 import org.apache.hudi.metadata.HoodieTableMetadataUtil;
 import org.apache.hudi.util.Lazy;
@@ -92,9 +93,9 @@ public class HudiColumnStatsIndexSupport
         }
         else {
             // Get filter columns
-            List<String> encodedTargetColumnNames = regularColumns
+            List<ColumnStatsIndexPrefixRawKey> rawKeys = regularColumns
                     .stream()
-                    .map(col -> new ColumnIndexID(col).asBase64EncodedString()).collect(Collectors.toList());
+                    .map(ColumnStatsIndexPrefixRawKey::new).toList();
 
             Map<String, Type> columnTypes = regularColumnPredicates.getDomains().get().entrySet().stream()
                     .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().getType()));
@@ -107,7 +108,8 @@ public class HudiColumnStatsIndexSupport
                 }
 
                 Map<String, Map<String, Domain>> domainsWithStats =
-                        lazyTableMetadata.get().getRecordsByKeyPrefixes(encodedTargetColumnNames,
+                        lazyTableMetadata.get().getRecordsByKeyPrefixes(
+                                        HoodieListData.lazy(rawKeys),
                                         HoodieTableMetadataUtil.PARTITION_NAME_COLUMN_STATS, true)
                                 .collectAsList()
                                 .stream()
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/query/index/HudiPartitionStatsIndexSupport.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/query/index/HudiPartitionStatsIndexSupport.java
index 3491d10cccfe..7d1e6907d976 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/query/index/HudiPartitionStatsIndexSupport.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/query/index/HudiPartitionStatsIndexSupport.java
@@ -21,10 +21,11 @@ import io.trino.spi.predicate.Domain;
 import io.trino.spi.predicate.TupleDomain;
 import io.trino.spi.type.Type;
 import org.apache.hudi.avro.model.HoodieMetadataColumnStats;
+import org.apache.hudi.common.data.HoodieListData;
 import org.apache.hudi.common.model.HoodieIndexDefinition;
 import org.apache.hudi.common.table.HoodieTableMetaClient;
 import org.apache.hudi.common.util.HoodieTimer;
-import org.apache.hudi.common.util.hash.ColumnIndexID;
+import org.apache.hudi.metadata.ColumnStatsIndexPrefixRawKey;
 import org.apache.hudi.metadata.HoodieTableMetadata;
 import org.apache.hudi.metadata.HoodieTableMetadataUtil;
 import org.apache.hudi.util.Lazy;
@@ -66,15 +67,15 @@ public class HudiPartitionStatsIndexSupport
         List<String> regularColumns = new ArrayList<>(filteredRegularPredicates.getDomains().get().keySet());
 
         // Get columns to filter on
-        List<String> encodedTargetColumnNames = regularColumns.stream()
-                .map(col -> new ColumnIndexID(col).asBase64EncodedString()).toList();
+        List<ColumnStatsIndexPrefixRawKey> columnStatsIndexPrefixRawKeys = regularColumns.stream()
+                .map(ColumnStatsIndexPrefixRawKey::new).toList();
 
         Map<String, Type> columnTypes = regularColumnPredicates.getDomains().get().entrySet().stream()
                 .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().getType()));
 
         // Map of domains with partition stats keyed by partition name and column name
         Map<String, Map<String, Domain>> domainsWithStats = lazyMetadataTable.get().getRecordsByKeyPrefixes(
-                        encodedTargetColumnNames,
+                        HoodieListData.eager(columnStatsIndexPrefixRawKeys),
                         HoodieTableMetadataUtil.PARTITION_NAME_PARTITION_STATS, true)
                 .collectAsList()
                 .stream()
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/query/index/HudiRecordLevelIndexSupport.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/query/index/HudiRecordLevelIndexSupport.java
index 78f503f4b21e..e438e5686ebb 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/query/index/HudiRecordLevelIndexSupport.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/query/index/HudiRecordLevelIndexSupport.java
@@ -22,6 +22,7 @@ import io.trino.spi.connector.ConnectorSession;
 import io.trino.spi.connector.SchemaTableName;
 import io.trino.spi.predicate.Domain;
 import io.trino.spi.predicate.TupleDomain;
+import org.apache.hudi.common.data.HoodieListData;
 import org.apache.hudi.common.model.FileSlice;
 import org.apache.hudi.common.model.HoodieRecordGlobalLocation;
 import org.apache.hudi.common.table.HoodieTableMetaClient;
@@ -47,6 +48,7 @@ import java.util.stream.Collectors;
 
 import static io.trino.plugin.hudi.HudiErrorCode.HUDI_BAD_DATA;
 import static io.trino.plugin.hudi.HudiSessionProperties.getRecordIndexWaitTimeout;
+import static io.trino.plugin.hudi.HudiUtil.collectAsMap;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 
 public class HudiRecordLevelIndexSupport
@@ -94,7 +96,7 @@ public class HudiRecordLevelIndexSupport
 
                 // Perform index lookup in metadataTable
                 // TODO: document here what this map is keyed by
-                Map<String, HoodieRecordGlobalLocation> recordIndex = lazyTableMetadata.get().readRecordIndex(recordKeys);
+                Map<String, HoodieRecordGlobalLocation> recordIndex = collectAsMap(lazyTableMetadata.get().readRecordIndexLocationsWithKeys(HoodieListData.eager(recordKeys)));
                 if (recordIndex.isEmpty()) {
                     log.debug("Record level index lookup took %s ms but returned no locations for the given keys %s for table %s",
                             timer.endTimer(), recordKeys, schemaTableName);
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/query/index/HudiSecondaryIndexSupport.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/query/index/HudiSecondaryIndexSupport.java
index 23121902f72c..eddf4d48f547 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/query/index/HudiSecondaryIndexSupport.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/query/index/HudiSecondaryIndexSupport.java
@@ -19,10 +19,12 @@ import io.trino.plugin.hudi.util.TupleDomainUtils;
 import io.trino.spi.connector.ConnectorSession;
 import io.trino.spi.connector.SchemaTableName;
 import io.trino.spi.predicate.TupleDomain;
+import org.apache.hudi.common.data.HoodieListData;
 import org.apache.hudi.common.model.FileSlice;
 import org.apache.hudi.common.model.HoodieIndexDefinition;
 import org.apache.hudi.common.model.HoodieRecordGlobalLocation;
 import org.apache.hudi.common.table.HoodieTableMetaClient;
+import org.apache.hudi.common.util.HoodieDataUtils;
 import org.apache.hudi.common.util.HoodieTimer;
 import org.apache.hudi.metadata.HoodieTableMetadata;
 import org.apache.hudi.metadata.HoodieTableMetadataUtil;
@@ -85,7 +87,7 @@ public class HudiSecondaryIndexSupport
 
             // Perform index lookup in metadataTable
             // TODO: document here what this map is keyed by
-            Map<String, HoodieRecordGlobalLocation> recordKeyLocationsMap = lazyTableMetadata.get().readSecondaryIndex(secondaryKeys, indexName);
+            Map<String, HoodieRecordGlobalLocation> recordKeyLocationsMap = HoodieDataUtils.dedupeAndCollectAsMap(lazyTableMetadata.get().readSecondaryIndexLocationsWithKeys(HoodieListData.eager(secondaryKeys), indexName));
             if (recordKeyLocationsMap.isEmpty()) {
                 log.debug("Took %s ms, but secondary index lookup returned no locations for the given keys for table %s", timer.endTimer(), schemaTableName);
                 // Return all original fileSlices
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/reader/HudiTrinoReaderContext.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/reader/HudiTrinoReaderContext.java
index 36c5342920f4..1f7584c3c168 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/reader/HudiTrinoReaderContext.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/reader/HudiTrinoReaderContext.java
@@ -19,29 +19,25 @@ import io.trino.plugin.hudi.util.SynthesizedColumnHandler;
 import io.trino.spi.Page;
 import io.trino.spi.connector.ConnectorPageSource;
 import org.apache.avro.Schema;
-import org.apache.avro.generic.GenericData;
-import org.apache.avro.generic.GenericData.Record;
-import org.apache.avro.generic.GenericRecord;
 import org.apache.avro.generic.IndexedRecord;
+import org.apache.hudi.avro.AvroRecordContext;
 import org.apache.hudi.common.config.RecordMergeMode;
 import org.apache.hudi.common.engine.HoodieReaderContext;
-import org.apache.hudi.common.model.HoodieAvroIndexedRecord;
-import org.apache.hudi.common.model.HoodieAvroRecordMerger;
-import org.apache.hudi.common.model.HoodieEmptyRecord;
-import org.apache.hudi.common.model.HoodieKey;
-import org.apache.hudi.common.model.HoodieRecord;
+import org.apache.hudi.common.model.HoodiePreCombineAvroRecordMerger;
 import org.apache.hudi.common.model.HoodieRecordMerger;
-import org.apache.hudi.common.table.read.BufferedRecord;
+import org.apache.hudi.common.table.HoodieTableConfig;
 import org.apache.hudi.common.util.Option;
 import org.apache.hudi.common.util.collection.ClosableIterator;
+import org.apache.hudi.common.util.collection.Pair;
 import org.apache.hudi.storage.HoodieStorage;
+import org.apache.hudi.storage.StorageConfiguration;
 import org.apache.hudi.storage.StoragePath;
+import org.apache.hudi.storage.StoragePathInfo;
 
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.function.UnaryOperator;
 
 public class HudiTrinoReaderContext
         extends HoodieReaderContext<IndexedRecord>
@@ -53,11 +49,14 @@ public class HudiTrinoReaderContext
     List<HiveColumnHandle> columnHandles;
 
     public HudiTrinoReaderContext(
+            StorageConfiguration storageConfiguration,
+            HoodieTableConfig tableConfig,
             ConnectorPageSource pageSource,
             List<HiveColumnHandle> dataHandles,
             List<HiveColumnHandle> columnHandles,
             SynthesizedColumnHandler synthesizedColumnHandler)
     {
+        super(storageConfiguration, tableConfig, Option.empty(), Option.empty(), new AvroRecordContext(tableConfig, tableConfig.getPayloadClass()));
         this.pageSource = pageSource;
         this.avroSerializer = new HudiAvroSerializer(columnHandles, synthesizedColumnHandler);
         this.dataHandles = dataHandles;
@@ -77,6 +76,23 @@ public class HudiTrinoReaderContext
             Schema dataSchema,
             Schema requiredSchema,
             HoodieStorage storage)
+    {
+        return createRecordIterator();
+    }
+
+    @Override
+    public ClosableIterator<IndexedRecord> getFileRecordIterator(
+            StoragePathInfo storagePathInfo,
+            long start,
+            long length,
+            Schema dataSchema,
+            Schema requiredSchema,
+            HoodieStorage storage)
+    {
+        return createRecordIterator();
+    }
+
+    private ClosableIterator<IndexedRecord> createRecordIterator()
     {
         return new ClosableIterator<>()
         {
@@ -130,98 +146,14 @@ public class HudiTrinoReaderContext
     }
 
     @Override
-    public IndexedRecord convertAvroRecord(IndexedRecord record)
+    protected Option<HoodieRecordMerger> getRecordMerger(RecordMergeMode mergeMode, String mergeStrategyId, String mergeImplClasses)
     {
-        return record;
+        return Option.of(new HoodiePreCombineAvroRecordMerger());
     }
 
     @Override
-    public GenericRecord convertToAvroRecord(IndexedRecord record, Schema schema)
-    {
-        GenericRecord ret = new GenericData.Record(schema);
-        for (Schema.Field field : schema.getFields()) {
-            ret.put(field.name(), record.get(field.pos()));
-        }
-        return ret;
-    }
-
-    @Override
-    public Option<HoodieRecordMerger> getRecordMerger(RecordMergeMode mergeMode, String mergeStrategyId, String mergeImplClasses)
-    {
-        return Option.of(HoodieAvroRecordMerger.INSTANCE);
-    }
-
-    @Override
-    public Object getValue(IndexedRecord record, Schema schema, String fieldName)
-    {
-        if (colToPosMap.containsKey(fieldName)) {
-            return record.get(colToPosMap.get(fieldName));
-        }
-        else {
-            // record doesn't have the queried field, return null
-            return null;
-        }
-    }
-
-    @Override
-    public IndexedRecord seal(IndexedRecord record)
-    {
-        // TODO: this can rely on colToPos map directly instead of schema
-        Schema schema = record.getSchema();
-        IndexedRecord newRecord = new Record(schema);
-        List<Schema.Field> fields = schema.getFields();
-        for (Schema.Field field : fields) {
-            int pos = schema.getField(field.name()).pos();
-            newRecord.put(pos, record.get(pos));
-        }
-        return newRecord;
-    }
-
-    @Override
-    public IndexedRecord toBinaryRow(Schema schema, IndexedRecord record)
-    {
-        return record;
-    }
-
-    @Override
-    public ClosableIterator<IndexedRecord> mergeBootstrapReaders(
-            ClosableIterator closableIterator, Schema schema,
-            ClosableIterator closableIterator1, Schema schema1)
+    public ClosableIterator<IndexedRecord> mergeBootstrapReaders(ClosableIterator<IndexedRecord> skeletonFileIterator, Schema skeletonRequiredSchema, ClosableIterator<IndexedRecord> dataFileIterator, Schema dataRequiredSchema, List<Pair<String, Object>> requiredPartitionFieldAndValues)
     {
         return null;
     }
-
-    @Override
-    public UnaryOperator<IndexedRecord> projectRecord(
-            Schema from,
-            Schema to,
-            Map<String, String> renamedColumns)
-    {
-        List<Schema.Field> toFields = to.getFields();
-        int[] projection = new int[toFields.size()];
-        for (int i = 0; i < projection.length; i++) {
-            projection[i] = from.getField(toFields.get(i).name()).pos();
-        }
-
-        return fromRecord -> {
-            IndexedRecord toRecord = new Record(to);
-            for (int i = 0; i < projection.length; i++) {
-                toRecord.put(i, fromRecord.get(projection[i]));
-            }
-            return toRecord;
-        };
-    }
-
-    @Override
-    public HoodieRecord<IndexedRecord> constructHoodieRecord(
-            BufferedRecord<IndexedRecord> bufferedRecord)
-    {
-        if (bufferedRecord.isDelete()) {
-            return new HoodieEmptyRecord<>(
-                    new HoodieKey(bufferedRecord.getRecordKey(), null),
-                    HoodieRecord.HoodieRecordType.AVRO);
-        }
-
-        return new HoodieAvroIndexedRecord(bufferedRecord.getRecord());
-    }
 }
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/reader/HudiTrinoRecord.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/reader/HudiTrinoRecord.java
deleted file mode 100644
index 7fa0f71399ed..000000000000
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/reader/HudiTrinoRecord.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package io.trino.plugin.hudi.reader;
-
-import com.esotericsoftware.kryo.Kryo;
-import com.esotericsoftware.kryo.io.Input;
-import com.esotericsoftware.kryo.io.Output;
-import org.apache.avro.Schema;
-import org.apache.avro.generic.IndexedRecord;
-import org.apache.hudi.common.model.HoodieAvroIndexedRecord;
-import org.apache.hudi.common.model.HoodieKey;
-import org.apache.hudi.common.model.HoodieOperation;
-import org.apache.hudi.common.model.HoodieRecord;
-import org.apache.hudi.common.model.MetadataValues;
-import org.apache.hudi.common.util.Option;
-import org.apache.hudi.common.util.collection.Pair;
-import org.apache.hudi.keygen.BaseKeyGenerator;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Map;
-import java.util.Properties;
-
-public class HudiTrinoRecord
-        extends HoodieRecord<IndexedRecord>
-{
-    public HudiTrinoRecord()
-    {
-    }
-
-    @Override
-    public HoodieRecord<IndexedRecord> newInstance()
-    {
-        return null;
-    }
-
-    @Override
-    public HoodieRecord<IndexedRecord> newInstance(HoodieKey hoodieKey, HoodieOperation hoodieOperation)
-    {
-        return null;
-    }
-
-    @Override
-    public HoodieRecord<IndexedRecord> newInstance(HoodieKey hoodieKey)
-    {
-        return null;
-    }
-
-    @Override
-    public Comparable<?> doGetOrderingValue(Schema schema, Properties properties)
-    {
-        return null;
-    }
-
-    @Override
-    public HoodieRecordType getRecordType()
-    {
-        return null;
-    }
-
-    @Override
-    public String getRecordKey(Schema schema, Option<BaseKeyGenerator> option)
-    {
-        return "";
-    }
-
-    @Override
-    public String getRecordKey(Schema schema, String s)
-    {
-        return "";
-    }
-
-    @Override
-    protected void writeRecordPayload(IndexedRecord page, Kryo kryo, Output output)
-    {
-    }
-
-    @Override
-    protected IndexedRecord readRecordPayload(Kryo kryo, Input input)
-    {
-        return null;
-    }
-
-    @Override
-    public Object[] getColumnValues(Schema schema, String[] strings, boolean b)
-    {
-        return new Object[0];
-    }
-
-    @Override
-    public HoodieRecord joinWith(HoodieRecord hoodieRecord, Schema schema)
-    {
-        return null;
-    }
-
-    @Override
-    public HoodieRecord prependMetaFields(Schema schema, Schema schema1,
-            MetadataValues metadataValues, Properties properties)
-    {
-        return null;
-    }
-
-    @Override
-    public HoodieRecord rewriteRecordWithNewSchema(Schema schema, Properties properties,
-            Schema schema1, Map<String, String> map)
-    {
-        return null;
-    }
-
-    @Override
-    public boolean isDelete(Schema schema, Properties properties)
-            throws IOException
-    {
-        return false;
-    }
-
-    @Override
-    public boolean shouldIgnore(Schema schema, Properties properties)
-            throws IOException
-    {
-        return false;
-    }
-
-    @Override
-    public HoodieRecord<IndexedRecord> copy()
-    {
-        return null;
-    }
-
-    @Override
-    public Option<Map<String, String>> getMetadata()
-    {
-        return null;
-    }
-
-    @Override
-    public HoodieRecord wrapIntoHoodieRecordPayloadWithParams(Schema schema, Properties properties,
-            Option<Pair<String, String>> option, Boolean aBoolean, Option<String> option1,
-            Boolean aBoolean1, Option<Schema> option2)
-            throws IOException
-    {
-        return null;
-    }
-
-    @Override
-    public HoodieRecord wrapIntoHoodieRecordPayloadWithKeyGen(Schema schema, Properties properties,
-            Option<BaseKeyGenerator> option)
-    {
-        return null;
-    }
-
-    @Override
-    public HoodieRecord truncateRecordKey(Schema schema, Properties properties, String s)
-            throws IOException
-    {
-        return null;
-    }
-
-    @Override
-    public Option<HoodieAvroIndexedRecord> toIndexedRecord(Schema schema, Properties properties)
-            throws IOException
-    {
-        return null;
-    }
-
-    @Override
-    public ByteArrayOutputStream getAvroBytes(Schema schema, Properties properties)
-            throws IOException
-    {
-        return null;
-    }
-}
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/stats/TableMetadataReader.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/stats/TableMetadataReader.java
index e87122de0795..a431465d938a 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/stats/TableMetadataReader.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/stats/TableMetadataReader.java
@@ -16,21 +16,14 @@ package io.trino.plugin.hudi.stats;
 import org.apache.hudi.avro.model.HoodieMetadataColumnStats;
 import org.apache.hudi.common.config.HoodieMetadataConfig;
 import org.apache.hudi.common.engine.HoodieEngineContext;
-import org.apache.hudi.common.model.HoodieColumnRangeMetadata;
-import org.apache.hudi.common.model.HoodieRecord;
-import org.apache.hudi.common.util.HoodieTimer;
 import org.apache.hudi.common.util.collection.Pair;
-import org.apache.hudi.common.util.hash.ColumnIndexID;
-import org.apache.hudi.common.util.hash.FileIndexID;
-import org.apache.hudi.common.util.hash.PartitionIndexID;
 import org.apache.hudi.exception.HoodieMetadataException;
 import org.apache.hudi.metadata.HoodieBackedTableMetadata;
-import org.apache.hudi.metadata.HoodieMetadataMetrics;
-import org.apache.hudi.metadata.HoodieMetadataPayload;
-import org.apache.hudi.metadata.HoodieTableMetadataUtil;
-import org.apache.hudi.metadata.MetadataPartitionType;
+import org.apache.hudi.stats.HoodieColumnRangeMetadata;
+import org.apache.hudi.stats.ValueMetadata;
 import org.apache.hudi.storage.HoodieStorage;
 
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
@@ -55,60 +48,29 @@ public class TableMetadataReader
      * @return a map from column name to their corresponding {@link HoodieColumnRangeMetadata}
      * @throws HoodieMetadataException if an error occurs while fetching the column statistics
      */
-    Map<String, HoodieColumnRangeMetadata> getColumnStats(List<Pair<String, String>> partitionNameFileNameList, List<String> columnNames)
+    public Map<String, HoodieColumnRangeMetadata> getColumnsRange(List<Pair<String, String>> partitionNameFileNameList, List<String> columnNames)
             throws HoodieMetadataException
     {
-        return computeFileToColumnStatsMap(computeColumnStatsLookupKeys(partitionNameFileNameList, columnNames));
-    }
-
-    /**
-     * @param partitionNameFileNameList a list of partition and file name pairs for which column stats need to be retrieved
-     * @param columnNames list of column names for which stats are needed
-     * @return a list of column stats keys to look up in the metadata table col_stats partition.
-     */
-    private List<String> computeColumnStatsLookupKeys(
-            final List<Pair<String, String>> partitionNameFileNameList,
-            final List<String> columnNames)
-    {
-        return columnNames.stream()
-                .flatMap(columnName -> partitionNameFileNameList.stream()
-                        .map(partitionNameFileNamePair -> HoodieMetadataPayload.getColumnStatsIndexKey(
-                                new PartitionIndexID(HoodieTableMetadataUtil.getColumnStatsIndexPartitionIdentifier(partitionNameFileNamePair.getLeft())),
-                                new FileIndexID(partitionNameFileNamePair.getRight()),
-                                new ColumnIndexID(columnName))))
-                .toList();
-    }
-
-    /**
-     * @param columnStatsLookupKeys a map from column stats key to partition and file name pair
-     * @return a map from column name to merged HoodieMetadataColumnStats
-     */
-    private Map<String, HoodieColumnRangeMetadata> computeFileToColumnStatsMap(List<String> columnStatsLookupKeys)
-    {
-        HoodieTimer timer = HoodieTimer.start();
-        Map<String, HoodieRecord<HoodieMetadataPayload>> hoodieRecords =
-                getRecordsByKeys(columnStatsLookupKeys, MetadataPartitionType.COLUMN_STATS.getPartitionPath());
-        metrics.ifPresent(m -> m.updateMetrics(HoodieMetadataMetrics.LOOKUP_COLUMN_STATS_METADATA_STR, timer.endTimer()));
-        return hoodieRecords.values().stream()
-                .collect(Collectors.groupingBy(
-                        r -> r.getData().getColumnStatMetadata().get().getColumnName(),
-                        Collectors.mapping(r -> r.getData().getColumnStatMetadata().get(), Collectors.toList())))
+        Map<Pair<String, String>, List<HoodieMetadataColumnStats>> columnStatsMap = getColumnStats(partitionNameFileNameList, columnNames);
+        return columnStatsMap.values().stream().flatMap(Collection::stream).collect(Collectors.groupingBy(
+                HoodieMetadataColumnStats::getColumnName,
+                Collectors.mapping(colStats -> colStats, Collectors.toList())))
                 .entrySet().stream()
-                .collect(Collectors.toMap(
-                        Map.Entry::getKey,
-                        e -> {
-                            long valueCount = 0L;
-                            long nullCount = 0L;
-                            long totalSize = 0L;
-                            long totalUncompressedSize = 0L;
-                            for (HoodieMetadataColumnStats stats : e.getValue()) {
-                                valueCount += stats.getValueCount();
-                                nullCount += stats.getNullCount();
-                                totalSize += stats.getTotalSize();
-                                totalUncompressedSize += stats.getTotalUncompressedSize();
-                            }
-                            return HoodieColumnRangeMetadata.create(
-                                    "", e.getKey(), null, null, nullCount, valueCount, totalSize, totalUncompressedSize);
-                        }));
+            .collect(Collectors.toMap(
+                    Map.Entry::getKey,
+                    e -> {
+                        long valueCount = 0L;
+                        long nullCount = 0L;
+                        long totalSize = 0L;
+                        long totalUncompressedSize = 0L;
+                        for (HoodieMetadataColumnStats stats : e.getValue()) {
+                            valueCount += stats.getValueCount();
+                            nullCount += stats.getNullCount();
+                            totalSize += stats.getTotalSize();
+                            totalUncompressedSize += stats.getTotalUncompressedSize();
+                        }
+                        return HoodieColumnRangeMetadata.create(
+                                "", e.getKey(), null, null, nullCount, valueCount, totalSize, totalUncompressedSize, ValueMetadata.NULL_METADATA);
+                    }));
     }
 }
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/stats/TableStatisticsReader.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/stats/TableStatisticsReader.java
index 55d424db40ca..5501905dcd00 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/stats/TableStatisticsReader.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/stats/TableStatisticsReader.java
@@ -24,11 +24,11 @@ import io.trino.spi.statistics.TableStatistics;
 import org.apache.hudi.common.config.HoodieMetadataConfig;
 import org.apache.hudi.common.engine.HoodieEngineContext;
 import org.apache.hudi.common.engine.HoodieLocalEngineContext;
-import org.apache.hudi.common.model.HoodieColumnRangeMetadata;
 import org.apache.hudi.common.table.HoodieTableMetaClient;
 import org.apache.hudi.common.table.timeline.HoodieInstant;
 import org.apache.hudi.common.table.view.HoodieTableFileSystemView;
 import org.apache.hudi.common.util.collection.Pair;
+import org.apache.hudi.stats.HoodieColumnRangeMetadata;
 
 import java.util.List;
 import java.util.Map;
@@ -113,6 +113,6 @@ public class TableStatisticsReader
                 .stream().flatMap(entry -> entry.getValue()
                         .map(baseFile -> Pair.of(entry.getKey(), baseFile.getFileName())))
                 .toList();
-        return tableMetadata.getColumnStats(filePaths, columnNames);
+        return tableMetadata.getColumnsRange(filePaths, columnNames);
     }
 }
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiAlluxioCacheFileOperations.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiAlluxioCacheFileOperations.java
index 8ad6b416220c..5fe42eb55a46 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiAlluxioCacheFileOperations.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiAlluxioCacheFileOperations.java
@@ -13,7 +13,6 @@
  */
 package io.trino.plugin.hudi;
 
-import com.google.common.collect.HashMultiset;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableMultiset;
 import com.google.common.collect.Multiset;
@@ -21,7 +20,6 @@ import io.trino.plugin.hudi.testing.ResourceHudiTablesInitializer;
 import io.trino.plugin.hudi.util.FileOperationUtils.FileOperation;
 import io.trino.testing.AbstractTestQueryFramework;
 import io.trino.testing.DistributedQueryRunner;
-import io.trino.testing.QueryRunner;
 import org.intellij.lang.annotations.Language;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.parallel.Execution;
@@ -34,15 +32,13 @@ import java.util.Map;
 
 import static com.google.common.io.MoreFiles.deleteRecursively;
 import static com.google.common.io.RecursiveDeleteOption.ALLOW_INSECURE;
-import static io.trino.filesystem.tracing.CacheFileSystemTraceUtils.getCacheOperationSpans;
 import static io.trino.plugin.hudi.testing.ResourceHudiTablesInitializer.TestingTable.HUDI_MULTI_FG_PT_V8_MOR;
+import static io.trino.plugin.hudi.util.FileOperationAssertions.assertAlluxioFileSystemAccesses;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.DATA;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.INDEX_DEFINITION;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.METADATA_TABLE;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.METADATA_TABLE_PROPERTIES;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.TABLE_PROPERTIES;
-import static io.trino.testing.MultisetAssertions.assertMultisetsEqual;
-import static java.util.stream.Collectors.toCollection;
 
 @ResourceLock("HUDI_CACHE_SYSTEM")
 @Execution(ExecutionMode.SAME_THREAD)
@@ -78,29 +74,18 @@ public class TestHudiAlluxioCacheFileOperations
             throws InterruptedException
     {
         @Language("SQL") String query = "SELECT * FROM " + HUDI_MULTI_FG_PT_V8_MOR + " WHERE country='SG'";
-        assertFileSystemAccesses(
-                query,
-                ImmutableMultiset.<FileOperation>builder()
-                        .addCopies(new FileOperation("Alluxio.readCached", DATA), 2)
-                        .addCopies(new FileOperation("Alluxio.readCached", METADATA_TABLE), 27)
-                        .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 4)
-                        .addCopies(new FileOperation("InputFile.length", METADATA_TABLE), 10)
-                        .addCopies(new FileOperation("InputFile.newStream", INDEX_DEFINITION), 2)
-                        .add(new FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES))
-                        .addCopies(new FileOperation("InputFile.newStream", TABLE_PROPERTIES), 2)
-                        .build());
+        Multiset<FileOperation> expectedFileOperations = ImmutableMultiset.<FileOperation>builder()
+                .addCopies(new FileOperation("Alluxio.readCached", DATA), 2)
+                .addCopies(new FileOperation("Alluxio.readCached", METADATA_TABLE), 20)
+                .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 5)
+                .addCopies(new FileOperation("InputFile.length", METADATA_TABLE), 11)
+                .addCopies(new FileOperation("InputFile.newStream", INDEX_DEFINITION), 2)
+                .add(new FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES))
+                .addCopies(new FileOperation("InputFile.newStream", TABLE_PROPERTIES), 2)
+                .build();
+        assertAlluxioFileSystemAccesses(getDistributedQueryRunner(), query, expectedFileOperations);
 
-        assertFileSystemAccesses(
-                query,
-                ImmutableMultiset.<FileOperation>builder()
-                        .addCopies(new FileOperation("Alluxio.readCached", DATA), 2)
-                        .addCopies(new FileOperation("Alluxio.readCached", METADATA_TABLE), 27)
-                        .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 4)
-                        .addCopies(new FileOperation("InputFile.length", METADATA_TABLE), 10)
-                        .addCopies(new FileOperation("InputFile.newStream", INDEX_DEFINITION), 2)
-                        .add(new FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES))
-                        .addCopies(new FileOperation("InputFile.newStream", TABLE_PROPERTIES), 2)
-                        .build());
+        assertAlluxioFileSystemAccesses(getDistributedQueryRunner(), query, expectedFileOperations);
     }
 
     @Test
@@ -112,69 +97,30 @@ public class TestHudiAlluxioCacheFileOperations
                 "INNER JOIN " + HUDI_MULTI_FG_PT_V8_MOR + " t2 ON t1.id = t2.id " +
                 "WHERE t2.price <= 102";
 
-        assertFileSystemAccesses(query,
+        assertAlluxioFileSystemAccesses(
+                getDistributedQueryRunner(),
+                query,
                 ImmutableMultiset.<FileOperation>builder()
                         .addCopies(new FileOperation("Alluxio.readCached", DATA), 6)
-                        .addCopies(new FileOperation("Alluxio.readCached", METADATA_TABLE), 288)
-                        .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 39)
-                        .addCopies(new FileOperation("InputFile.length", METADATA_TABLE), 93)
+                        .addCopies(new FileOperation("Alluxio.readCached", METADATA_TABLE), 222)
+                        .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 60)
+                        .addCopies(new FileOperation("InputFile.length", METADATA_TABLE), 114)
                         .addCopies(new FileOperation("InputFile.newStream", INDEX_DEFINITION), 5)
                         .addCopies(new FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES), 3)
                         .addCopies(new FileOperation("InputFile.newStream", TABLE_PROPERTIES), 5)
                         .build());
 
-        assertFileSystemAccesses(query,
+        assertAlluxioFileSystemAccesses(
+                getDistributedQueryRunner(),
+                query,
                 ImmutableMultiset.<FileOperation>builder()
                         .addCopies(new FileOperation("Alluxio.readCached", DATA), 6)
-                        .addCopies(new FileOperation("Alluxio.readCached", METADATA_TABLE), 215)
-                        .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 29)
-                        .addCopies(new FileOperation("InputFile.length", METADATA_TABLE), 69)
+                        .addCopies(new FileOperation("Alluxio.readCached", METADATA_TABLE), 166)
+                        .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 45)
+                        .addCopies(new FileOperation("InputFile.length", METADATA_TABLE), 85)
                         .addCopies(new FileOperation("InputFile.newStream", INDEX_DEFINITION), 4)
                         .addCopies(new FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES), 2)
                         .addCopies(new FileOperation("InputFile.newStream", TABLE_PROPERTIES), 4)
                         .build());
     }
-
-    private void assertFileSystemAccesses(@Language("SQL") String query, Multiset<FileOperation> expectedCacheAccesses)
-            throws InterruptedException
-    {
-        DistributedQueryRunner queryRunner = getDistributedQueryRunner();
-        queryRunner.executeWithPlan(queryRunner.getDefaultSession(), query);
-        // Async table-stats computation can outlive the synchronous query and emit spans into
-        // the exporter after execute returns. A fixed Thread.sleep races with this — when
-        // stats from query N is still running while query N+1's measurement happens, spans
-        // leak across the boundary and counts get scrambled (the symmetric off-by-N failure
-        // across paired tests). Poll until the span set is stable for two consecutive reads.
-        Multiset<FileOperation> actual = waitForStableSpans(queryRunner);
-        assertMultisetsEqual(actual, expectedCacheAccesses);
-    }
-
-    /**
-     * Returns the file-operation span set once two consecutive reads (200ms apart) agree.
-     * Bounded by a 30-second ceiling so a runaway test fails loudly instead of hanging.
-     */
-    private static Multiset<FileOperation> waitForStableSpans(QueryRunner queryRunner)
-            throws InterruptedException
-    {
-        long deadlineMillis = System.currentTimeMillis() + 30_000L;
-        Multiset<FileOperation> previous = null;
-        while (System.currentTimeMillis() < deadlineMillis) {
-            Thread.sleep(200L);
-            Multiset<FileOperation> current = getFileOperations(queryRunner);
-            if (previous != null && current.equals(previous)) {
-                return current;
-            }
-            previous = current;
-        }
-        return previous != null ? previous : getFileOperations(queryRunner);
-    }
-
-    public static Multiset<FileOperation> getFileOperations(QueryRunner queryRunner)
-    {
-        return getCacheOperationSpans(queryRunner)
-                .stream()
-                .filter(span -> !span.getName().startsWith("InputFile.exists"))
-                .map(FileOperation::create)
-                .collect(toCollection(HashMultiset::create));
-    }
 }
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiMemoryCacheFileOperations.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiMemoryCacheFileOperations.java
index b23f0c4f5441..7c61d260cab5 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiMemoryCacheFileOperations.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiMemoryCacheFileOperations.java
@@ -13,7 +13,6 @@
  */
 package io.trino.plugin.hudi;
 
-import com.google.common.collect.HashMultiset;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableMultiset;
 import com.google.common.collect.Multiset;
@@ -21,7 +20,6 @@ import io.trino.plugin.hudi.testing.ResourceHudiTablesInitializer;
 import io.trino.plugin.hudi.util.FileOperationUtils.FileOperation;
 import io.trino.testing.AbstractTestQueryFramework;
 import io.trino.testing.DistributedQueryRunner;
-import io.trino.testing.QueryRunner;
 import org.intellij.lang.annotations.Language;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.parallel.Execution;
@@ -30,16 +28,13 @@ import org.junit.jupiter.api.parallel.ResourceLock;
 
 import java.util.Map;
 
-import static io.trino.filesystem.tracing.CacheFileSystemTraceUtils.getFileLocation;
-import static io.trino.filesystem.tracing.CacheFileSystemTraceUtils.isTrinoSchemaOrPermissions;
 import static io.trino.plugin.hudi.testing.ResourceHudiTablesInitializer.TestingTable.HUDI_MULTI_FG_PT_V8_MOR;
+import static io.trino.plugin.hudi.util.FileOperationAssertions.assertFileSystemAccesses;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.DATA;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.INDEX_DEFINITION;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.METADATA_TABLE;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.METADATA_TABLE_PROPERTIES;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.TABLE_PROPERTIES;
-import static io.trino.testing.MultisetAssertions.assertMultisetsEqual;
-import static java.util.stream.Collectors.toCollection;
 
 @ResourceLock("HUDI_CACHE_SYSTEM")
 @Execution(ExecutionMode.SAME_THREAD)
@@ -68,29 +63,18 @@ public class TestHudiMemoryCacheFileOperations
             throws InterruptedException
     {
         @Language("SQL") String query = "SELECT * FROM " + HUDI_MULTI_FG_PT_V8_MOR + " WHERE country='SG'";
-        assertFileSystemAccesses(
-                query,
-                ImmutableMultiset.<FileOperation>builder()
-                        .addCopies(new FileOperation("FileSystemCache.cacheInput", DATA), 2)
-                        .addCopies(new FileOperation("FileSystemCache.cacheLength", METADATA_TABLE), 4)
-                        .addCopies(new FileOperation("FileSystemCache.cacheStream", METADATA_TABLE), 6)
-                        .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 4)
-                        .addCopies(new FileOperation("InputFile.newStream", INDEX_DEFINITION), 2)
-                        .add(new FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES))
-                        .addCopies(new FileOperation("InputFile.newStream", TABLE_PROPERTIES), 2)
-                        .build());
+        Multiset<FileOperation> expectedFileOperations = ImmutableMultiset.<FileOperation>builder()
+                .addCopies(new FileOperation("FileSystemCache.cacheInput", DATA), 2)
+                .addCopies(new FileOperation("FileSystemCache.cacheLength", METADATA_TABLE), 5)
+                .addCopies(new FileOperation("FileSystemCache.cacheStream", METADATA_TABLE), 6)
+                .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 5)
+                .addCopies(new FileOperation("InputFile.newStream", INDEX_DEFINITION), 2)
+                .add(new FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES))
+                .addCopies(new FileOperation("InputFile.newStream", TABLE_PROPERTIES), 2)
+                .build();
+        assertFileSystemAccesses(getDistributedQueryRunner(), query, expectedFileOperations);
 
-        assertFileSystemAccesses(
-                query,
-                ImmutableMultiset.<FileOperation>builder()
-                        .addCopies(new FileOperation("FileSystemCache.cacheInput", DATA), 2)
-                        .addCopies(new FileOperation("FileSystemCache.cacheLength", METADATA_TABLE), 4)
-                        .addCopies(new FileOperation("FileSystemCache.cacheStream", METADATA_TABLE), 6)
-                        .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 4)
-                        .addCopies(new FileOperation("InputFile.newStream", INDEX_DEFINITION), 2)
-                        .add(new FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES))
-                        .addCopies(new FileOperation("InputFile.newStream", TABLE_PROPERTIES), 2)
-                        .build());
+        assertFileSystemAccesses(getDistributedQueryRunner(), query, expectedFileOperations);
     }
 
     @Test
@@ -102,71 +86,30 @@ public class TestHudiMemoryCacheFileOperations
                 "INNER JOIN " + HUDI_MULTI_FG_PT_V8_MOR + " t2 ON t1.id = t2.id " +
                 "WHERE t2.price <= 102";
 
-        assertFileSystemAccesses(query,
+        assertFileSystemAccesses(
+                getDistributedQueryRunner(),
+                query,
                 ImmutableMultiset.<FileOperation>builder()
                         .addCopies(new FileOperation("FileSystemCache.cacheInput", DATA), 6)
-                        .addCopies(new FileOperation("FileSystemCache.cacheLength", METADATA_TABLE), 39)
+                        .addCopies(new FileOperation("FileSystemCache.cacheLength", METADATA_TABLE), 60)
                         .addCopies(new FileOperation("FileSystemCache.cacheStream", METADATA_TABLE), 54)
-                        .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 39)
+                        .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 60)
                         .addCopies(new FileOperation("InputFile.newStream", INDEX_DEFINITION), 5)
                         .addCopies(new FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES), 3)
                         .addCopies(new FileOperation("InputFile.newStream", TABLE_PROPERTIES), 5)
                         .build());
 
-        assertFileSystemAccesses(query,
+        assertFileSystemAccesses(
+                getDistributedQueryRunner(),
+                query,
                 ImmutableMultiset.<FileOperation>builder()
                         .addCopies(new FileOperation("FileSystemCache.cacheInput", DATA), 6)
-                        .addCopies(new FileOperation("FileSystemCache.cacheLength", METADATA_TABLE), 29)
+                        .addCopies(new FileOperation("FileSystemCache.cacheLength", METADATA_TABLE), 45)
                         .addCopies(new FileOperation("FileSystemCache.cacheStream", METADATA_TABLE), 40)
-                        .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 29)
+                        .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 45)
                         .addCopies(new FileOperation("InputFile.newStream", INDEX_DEFINITION), 4)
                         .addCopies(new FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES), 2)
                         .addCopies(new FileOperation("InputFile.newStream", TABLE_PROPERTIES), 4)
                         .build());
     }
-
-    private void assertFileSystemAccesses(@Language("SQL") String query, Multiset<FileOperation> expectedCacheAccesses)
-            throws InterruptedException
-    {
-        DistributedQueryRunner queryRunner = getDistributedQueryRunner();
-        queryRunner.executeWithPlan(queryRunner.getDefaultSession(), query);
-        // Async table-stats computation can outlive the synchronous query and emit spans into
-        // the exporter after execute returns. A fixed Thread.sleep races with this — when
-        // stats from query N is still running while query N+1's measurement happens, spans
-        // leak across the boundary and counts get scrambled (the symmetric off-by-N failure
-        // across paired tests). Poll until the span set is stable for two consecutive reads.
-        Multiset<FileOperation> actual = waitForStableSpans(queryRunner);
-        assertMultisetsEqual(actual, expectedCacheAccesses);
-    }
-
-    /**
-     * Returns the file-operation span set once two consecutive reads (200ms apart) agree.
-     * Bounded by a 30-second ceiling so a runaway test fails loudly instead of hanging.
-     */
-    private static Multiset<FileOperation> waitForStableSpans(QueryRunner queryRunner)
-            throws InterruptedException
-    {
-        long deadlineMillis = System.currentTimeMillis() + 30_000L;
-        Multiset<FileOperation> previous = null;
-        while (System.currentTimeMillis() < deadlineMillis) {
-            Thread.sleep(200L);
-            Multiset<FileOperation> current = getFileOperations(queryRunner);
-            if (previous != null && current.equals(previous)) {
-                return current;
-            }
-            previous = current;
-        }
-        return previous != null ? previous : getFileOperations(queryRunner);
-    }
-
-    private static Multiset<FileOperation> getFileOperations(QueryRunner queryRunner)
-    {
-        return queryRunner.getSpans().stream()
-                .filter(span -> span.getName().startsWith("Input.") || span.getName().startsWith("InputFile.") || span.getName().startsWith("FileSystemCache."))
-                .filter(span -> !span.getName().startsWith("InputFile.newInput"))
-                .filter(span -> !span.getName().startsWith("InputFile.exists"))
-                .filter(span -> !isTrinoSchemaOrPermissions(getFileLocation(span)))
-                .map(FileOperation::create)
-                .collect(toCollection(HashMultiset::create));
-    }
 }
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiNoCacheFileOperations.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiNoCacheFileOperations.java
index 7271dde44f0d..c2fa041a99bd 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiNoCacheFileOperations.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiNoCacheFileOperations.java
@@ -13,7 +13,6 @@
  */
 package io.trino.plugin.hudi;
 
-import com.google.common.collect.HashMultiset;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableMultiset;
 import com.google.common.collect.Multiset;
@@ -21,7 +20,6 @@ import io.trino.plugin.hudi.testing.ResourceHudiTablesInitializer;
 import io.trino.plugin.hudi.util.FileOperationUtils;
 import io.trino.testing.AbstractTestQueryFramework;
 import io.trino.testing.DistributedQueryRunner;
-import io.trino.testing.QueryRunner;
 import org.intellij.lang.annotations.Language;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.parallel.Execution;
@@ -30,16 +28,13 @@ import org.junit.jupiter.api.parallel.ResourceLock;
 
 import java.util.Map;
 
-import static io.trino.filesystem.tracing.CacheFileSystemTraceUtils.getFileLocation;
-import static io.trino.filesystem.tracing.CacheFileSystemTraceUtils.isTrinoSchemaOrPermissions;
 import static io.trino.plugin.hudi.testing.ResourceHudiTablesInitializer.TestingTable.HUDI_MULTI_FG_PT_V8_MOR;
+import static io.trino.plugin.hudi.util.FileOperationAssertions.assertFileSystemAccesses;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.DATA;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.INDEX_DEFINITION;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.METADATA_TABLE;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.METADATA_TABLE_PROPERTIES;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.TABLE_PROPERTIES;
-import static io.trino.testing.MultisetAssertions.assertMultisetsEqual;
-import static java.util.stream.Collectors.toCollection;
 
 @ResourceLock("HUDI_CACHE_SYSTEM")
 @Execution(ExecutionMode.SAME_THREAD)
@@ -68,29 +63,18 @@ public class TestHudiNoCacheFileOperations
             throws InterruptedException
     {
         @Language("SQL") String query = "SELECT * FROM " + HUDI_MULTI_FG_PT_V8_MOR + " WHERE country='SG'";
-        assertFileSystemAccesses(
-                query,
-                ImmutableMultiset.<FileOperationUtils.FileOperation>builder()
-                        .addCopies(new FileOperationUtils.FileOperation("Input.readTail", DATA), 2)
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.lastModified", METADATA_TABLE), 4)
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.length", METADATA_TABLE), 4)
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", METADATA_TABLE), 6)
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", INDEX_DEFINITION), 2)
-                        .add(new FileOperationUtils.FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES))
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", TABLE_PROPERTIES), 2)
-                        .build());
+        Multiset<FileOperationUtils.FileOperation> expectedFileOperations = ImmutableMultiset.<FileOperationUtils.FileOperation>builder()
+                .addCopies(new FileOperationUtils.FileOperation("Input.readTail", DATA), 2)
+                .addCopies(new FileOperationUtils.FileOperation("InputFile.lastModified", METADATA_TABLE), 5)
+                .addCopies(new FileOperationUtils.FileOperation("InputFile.length", METADATA_TABLE), 5)
+                .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", METADATA_TABLE), 6)
+                .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", INDEX_DEFINITION), 2)
+                .add(new FileOperationUtils.FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES))
+                .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", TABLE_PROPERTIES), 2)
+                .build();
+        assertFileSystemAccesses(getDistributedQueryRunner(), query, expectedFileOperations);
 
-        assertFileSystemAccesses(
-                query,
-                ImmutableMultiset.<FileOperationUtils.FileOperation>builder()
-                        .addCopies(new FileOperationUtils.FileOperation("Input.readTail", DATA), 2)
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.lastModified", METADATA_TABLE), 4)
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.length", METADATA_TABLE), 4)
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", INDEX_DEFINITION), 2)
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", METADATA_TABLE), 6)
-                        .add(new FileOperationUtils.FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES))
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", TABLE_PROPERTIES), 2)
-                        .build());
+        assertFileSystemAccesses(getDistributedQueryRunner(), query, expectedFileOperations);
     }
 
     @Test
@@ -102,71 +86,30 @@ public class TestHudiNoCacheFileOperations
                 "INNER JOIN " + HUDI_MULTI_FG_PT_V8_MOR + " t2 ON t1.id = t2.id " +
                 "WHERE t2.price <= 102";
 
-        assertFileSystemAccesses(query,
+        assertFileSystemAccesses(
+                getDistributedQueryRunner(),
+                query,
                 ImmutableMultiset.<FileOperationUtils.FileOperation>builder()
                         .addCopies(new FileOperationUtils.FileOperation("Input.readTail", DATA), 6)
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.lastModified", METADATA_TABLE), 39)
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.length", METADATA_TABLE), 39)
+                        .addCopies(new FileOperationUtils.FileOperation("InputFile.lastModified", METADATA_TABLE), 60)
+                        .addCopies(new FileOperationUtils.FileOperation("InputFile.length", METADATA_TABLE), 60)
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", INDEX_DEFINITION), 5)
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", METADATA_TABLE), 54)
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES), 3)
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", TABLE_PROPERTIES), 5)
                         .build());
 
-        assertFileSystemAccesses(query,
+        assertFileSystemAccesses(
+                getDistributedQueryRunner(),
+                query,
                 ImmutableMultiset.<FileOperationUtils.FileOperation>builder()
                         .addCopies(new FileOperationUtils.FileOperation("Input.readTail", DATA), 6)
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.lastModified", METADATA_TABLE), 29)
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.length", METADATA_TABLE), 29)
+                        .addCopies(new FileOperationUtils.FileOperation("InputFile.lastModified", METADATA_TABLE), 45)
+                        .addCopies(new FileOperationUtils.FileOperation("InputFile.length", METADATA_TABLE), 45)
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", INDEX_DEFINITION), 4)
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", METADATA_TABLE), 40)
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES), 2)
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", TABLE_PROPERTIES), 4)
                         .build());
     }
-
-    private void assertFileSystemAccesses(@Language("SQL") String query, Multiset<FileOperationUtils.FileOperation> expectedCacheAccesses)
-               throws InterruptedException
-    {
-        DistributedQueryRunner queryRunner = getDistributedQueryRunner();
-        queryRunner.executeWithPlan(queryRunner.getDefaultSession(), query);
-        // Async table-stats computation can outlive the synchronous query and emit spans into
-        // the exporter after execute returns. A fixed Thread.sleep races with this — when
-        // stats from query N is still running while query N+1's measurement happens, spans
-        // leak across the boundary and counts get scrambled (the symmetric off-by-N failure
-        // across paired tests). Poll until the span set is stable for two consecutive reads.
-        Multiset<FileOperationUtils.FileOperation> actual = waitForStableSpans(queryRunner);
-        assertMultisetsEqual(actual, expectedCacheAccesses);
-    }
-
-    /**
-     * Returns the file-operation span set once two consecutive reads (200ms apart) agree.
-     * Bounded by a 30-second ceiling so a runaway test fails loudly instead of hanging.
-     */
-    private static Multiset<FileOperationUtils.FileOperation> waitForStableSpans(QueryRunner queryRunner)
-            throws InterruptedException
-    {
-        long deadlineMillis = System.currentTimeMillis() + 30_000L;
-        Multiset<FileOperationUtils.FileOperation> previous = null;
-        while (System.currentTimeMillis() < deadlineMillis) {
-            Thread.sleep(200L);
-            Multiset<FileOperationUtils.FileOperation> current = getFileOperations(queryRunner);
-            if (previous != null && current.equals(previous)) {
-                return current;
-            }
-            previous = current;
-        }
-        return previous != null ? previous : getFileOperations(queryRunner);
-    }
-
-    private static Multiset<FileOperationUtils.FileOperation> getFileOperations(QueryRunner queryRunner)
-    {
-        return queryRunner.getSpans().stream()
-                .filter(span -> span.getName().startsWith("Input.") || span.getName().startsWith("InputFile.") || span.getName().startsWith("FileSystemCache."))
-                .filter(span -> !span.getName().startsWith("InputFile.newInput"))
-                .filter(span -> !span.getName().startsWith("InputFile.exists"))
-                .filter(span -> !isTrinoSchemaOrPermissions(getFileLocation(span)))
-                .map(FileOperationUtils.FileOperation::create)
-                .collect(toCollection(HashMultiset::create));
-    }
 }
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiSmokeTest.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiSmokeTest.java
index d1c26fbf5edd..dbb7195d38ef 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiSmokeTest.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiSmokeTest.java
@@ -754,8 +754,8 @@ public class TestHudiSmokeTest
                 .withPartitionStatsIndexEnabled(false)
                 .withResolveColumnNameCasingEnabled(true)
                 .build();
-        MaterializedResult totalRes = getQueryRunner().execute(session, "SELECT * FROM " + HUDI_COW_TABLE_WITH_FIELD_NAMES_IN_CAPS);
         MaterializedResult prunedRes = getQueryRunner().execute(session, "SELECT * FROM  " + HUDI_COW_TABLE_WITH_FIELD_NAMES_IN_CAPS + " WHERE id='1'");
+        MaterializedResult totalRes = getQueryRunner().execute(session, "SELECT * FROM " + HUDI_COW_TABLE_WITH_FIELD_NAMES_IN_CAPS);
         int totalSplits = totalRes.getStatementStats().get().getTotalSplits();
         int totalRows = totalRes.getRowCount();
         int prunedSplits = prunedRes.getStatementStats().get().getTotalSplits();
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/partition/TestHudiPartitionInfoLoader.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/partition/TestHudiPartitionInfoLoader.java
index 24c1b16dff5f..78f565dcaa2d 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/partition/TestHudiPartitionInfoLoader.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/partition/TestHudiPartitionInfoLoader.java
@@ -161,6 +161,7 @@ public class TestHudiPartitionInfoLoader
                 TABLE_PATH,
                 HoodieTableType.COPY_ON_WRITE,
                 ImmutableList.of(),
+                ImmutableList.of(),
                 TupleDomain.all(),
                 TupleDomain.all(),
                 "",
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/split/TestHudiSplitFactory.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/split/TestHudiSplitFactory.java
index 9c4f4a6176fc..266a5397af41 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/split/TestHudiSplitFactory.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/split/TestHudiSplitFactory.java
@@ -181,6 +181,7 @@ public class TestHudiSplitFactory
                 "/test/path",
                 HoodieTableType.MERGE_ON_READ,
                 ImmutableList.of(),
+                ImmutableList.of(),
                 TupleDomain.all(),
                 TupleDomain.all(),
                 "",
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/testing/TpchHudiTablesInitializer.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/testing/TpchHudiTablesInitializer.java
index 10d1b9873ad3..640980c41936 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/testing/TpchHudiTablesInitializer.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/testing/TpchHudiTablesInitializer.java
@@ -45,6 +45,7 @@ import org.apache.avro.generic.GenericRecord;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.Path;
 import org.apache.hudi.client.HoodieJavaWriteClient;
+import org.apache.hudi.client.WriteStatus;
 import org.apache.hudi.client.common.HoodieJavaEngineContext;
 import org.apache.hudi.common.bootstrap.index.NoOpBootstrapIndex;
 import org.apache.hudi.common.config.HoodieMetadataConfig;
@@ -54,7 +55,6 @@ import org.apache.hudi.common.model.HoodieKey;
 import org.apache.hudi.common.model.HoodieRecord;
 import org.apache.hudi.common.table.HoodieTableMetaClient;
 import org.apache.hudi.common.table.marker.MarkerType;
-import org.apache.hudi.common.table.timeline.HoodieInstantTimeGenerator;
 import org.apache.hudi.common.util.Option;
 import org.apache.hudi.config.HoodieArchivalConfig;
 import org.apache.hudi.config.HoodieIndexConfig;
@@ -64,12 +64,10 @@ import org.apache.hudi.storage.hadoop.HadoopStorageConfiguration;
 import org.intellij.lang.annotations.Language;
 
 import java.io.IOException;
-import java.time.Instant;
 import java.time.LocalDate;
 import java.time.temporal.ChronoField;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -168,9 +166,9 @@ public class TpchHudiTablesInitializer
                     .map(MaterializedRow::getFields)
                     .map(recordConverter::toRecord)
                     .collect(Collectors.toList());
-            String timestamp = HoodieInstantTimeGenerator.formatDate(Date.from(Instant.now()));
-            writeClient.startCommitWithTime(timestamp);
-            writeClient.insert(records, timestamp);
+            String instantTime = writeClient.startCommit();
+            List<WriteStatus> writeStatuses = writeClient.insert(records, instantTime);
+            writeClient.commit(instantTime, writeStatuses);
         }
     }
 
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/util/FileOperationAssertions.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/util/FileOperationAssertions.java
new file mode 100644
index 000000000000..2c4af15574f7
--- /dev/null
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/util/FileOperationAssertions.java
@@ -0,0 +1,166 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.trino.plugin.hudi.util;
+
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
+import io.airlift.log.Logger;
+import io.trino.plugin.hudi.util.FileOperationUtils.FileOperation;
+import io.trino.testing.QueryRunner;
+import org.intellij.lang.annotations.Language;
+
+import java.util.Comparator;
+import java.util.function.Supplier;
+
+import static io.trino.filesystem.tracing.CacheFileSystemTraceUtils.getCacheOperationSpans;
+import static io.trino.filesystem.tracing.CacheFileSystemTraceUtils.getFileLocation;
+import static io.trino.filesystem.tracing.CacheFileSystemTraceUtils.isTrinoSchemaOrPermissions;
+import static io.trino.testing.MultisetAssertions.assertMultisetsEqual;
+import static java.util.stream.Collectors.toCollection;
+
+public final class FileOperationAssertions
+{
+    private static final Logger log = Logger.get(FileOperationAssertions.class);
+
+    private FileOperationAssertions() {}
+
+    /**
+     * Asserts that file system accesses match expected operations.
+     * This version uses manual filtering for Input/InputFile operations.
+     * Logs detailed comparison at WARN level for debugging test failures.
+     */
+    public static void assertFileSystemAccesses(
+            QueryRunner queryRunner,
+            @Language("SQL") String query,
+            Multiset<FileOperation> expectedCacheAccesses)
+            throws InterruptedException
+    {
+        queryRunner.executeWithPlan(queryRunner.getDefaultSession(), query);
+        // Async table-stats computation can outlive the synchronous query and emit spans into
+        // the exporter after execute returns. A fixed Thread.sleep races with this: when stats
+        // from query N is still running while query N+1's measurement happens, spans leak
+        // across the boundary and counts get scrambled. Poll until the span set is stable for
+        // two consecutive reads.
+        Multiset<FileOperation> actualCacheAccesses = waitForStableSpans(() -> getFileOperations(queryRunner));
+        printFileAccessDebugInfo(queryRunner, actualCacheAccesses, expectedCacheAccesses);
+        assertMultisetsEqual(actualCacheAccesses, expectedCacheAccesses);
+    }
+
+    /**
+     * Asserts that file system accesses match expected operations for Alluxio cache tests.
+     * This version uses getCacheOperationSpans for filtering.
+     * Logs detailed comparison at WARN level for debugging test failures.
+     */
+    public static void assertAlluxioFileSystemAccesses(
+            QueryRunner queryRunner,
+            @Language("SQL") String query,
+            Multiset<FileOperation> expectedCacheAccesses)
+            throws InterruptedException
+    {
+        queryRunner.executeWithPlan(queryRunner.getDefaultSession(), query);
+        // See assertFileSystemAccesses for the rationale behind polling instead of a fixed sleep.
+        Multiset<FileOperation> actualCacheAccesses = waitForStableSpans(() -> getAlluxioFileOperations(queryRunner));
+        printFileAccessDebugInfo(queryRunner, actualCacheAccesses, expectedCacheAccesses);
+        assertMultisetsEqual(actualCacheAccesses, expectedCacheAccesses);
+    }
+
+    /**
+     * Returns the span set once two consecutive reads (200ms apart) agree. Bounded by a
+     * 30-second ceiling so a runaway test fails loudly instead of hanging.
+     */
+    private static Multiset<FileOperation> waitForStableSpans(Supplier<Multiset<FileOperation>> reader)
+            throws InterruptedException
+    {
+        long deadlineMillis = System.currentTimeMillis() + 30_000L;
+        Multiset<FileOperation> previous = null;
+        while (System.currentTimeMillis() < deadlineMillis) {
+            Thread.sleep(200L);
+            Multiset<FileOperation> current = reader.get();
+            if (previous != null && current.equals(previous)) {
+                return current;
+            }
+            previous = current;
+        }
+        return previous != null ? previous : reader.get();
+    }
+
+    /**
+     * Gets file operations from query runner spans using manual filtering.
+     */
+    public static Multiset<FileOperation> getFileOperations(QueryRunner queryRunner)
+    {
+        return queryRunner.getSpans().stream()
+                .filter(span -> span.getName().startsWith("Input.") || span.getName().startsWith("InputFile.") || span.getName().startsWith("FileSystemCache."))
+                .filter(span -> !span.getName().startsWith("InputFile.newInput"))
+                .filter(span -> !span.getName().startsWith("InputFile.exists"))
+                .filter(span -> !isTrinoSchemaOrPermissions(getFileLocation(span)))
+                .map(FileOperation::create)
+                .collect(toCollection(HashMultiset::create));
+    }
+
+    /**
+     * Gets file operations for Alluxio cache tests using getCacheOperationSpans.
+     */
+    public static Multiset<FileOperation> getAlluxioFileOperations(QueryRunner queryRunner)
+    {
+        return getCacheOperationSpans(queryRunner)
+                .stream()
+                .filter(span -> !span.getName().startsWith("InputFile.exists"))
+                .map(FileOperation::create)
+                .collect(toCollection(HashMultiset::create));
+    }
+
+    private static void printFileAccessDebugInfo(
+            QueryRunner queryRunner,
+            Multiset<FileOperation> actualCacheAccesses,
+            Multiset<FileOperation> expectedCacheAccesses)
+    {
+        // Log all file paths accessed for debugging
+        log.warn("=== All File Paths Accessed ===");
+        queryRunner.getSpans().stream()
+                .filter(span -> span.getName().equals("InputFile.lastModified") || span.getName().equals("InputFile.length"))
+                .forEach(span -> log.warn("%s: %s", span.getName(), getFileLocation(span)));
+
+        // Log actual and expected cache accesses
+        log.warn("=== Actual Cache Accesses ===");
+        logSortedMultiset(actualCacheAccesses);
+
+        log.warn("=== Expected Cache Accesses ===");
+        logSortedMultiset(expectedCacheAccesses);
+
+        // Calculate and log differences
+        Multiset<FileOperation> extraInActual = HashMultiset.create(actualCacheAccesses);
+        extraInActual.removeAll(expectedCacheAccesses);
+
+        Multiset<FileOperation> missingFromActual = HashMultiset.create(expectedCacheAccesses);
+        missingFromActual.removeAll(actualCacheAccesses);
+
+        if (!extraInActual.isEmpty()) {
+            log.warn("=== Extra in Actual (not expected) ===");
+            logSortedMultiset(extraInActual);
+        }
+
+        if (!missingFromActual.isEmpty()) {
+            log.warn("=== Missing from Actual (expected but not found) ===");
+            logSortedMultiset(missingFromActual);
+        }
+    }
+
+    private static void logSortedMultiset(Multiset<FileOperation> multiset)
+    {
+        multiset.entrySet().stream()
+                .sorted(Comparator.comparing(a -> a.getElement().toString()))
+                .forEach(entry -> log.warn("%s: %s", entry.getElement(), entry.getCount()));
+    }
+}


(hudi) 07/36: fix(trino): port hudi-trino-plugin to Hudi 1.3 HoodieSchema APIs

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit 2b67d23daea8d02661d1a70cd20b15dc067ea3d0
Author: voon <vo...@gmail.com>
AuthorDate: Fri May 22 20:16:21 2026 +0800

    fix(trino): port hudi-trino-plugin to Hudi 1.3 HoodieSchema APIs
    
    Hudi 1.3 introduces org.apache.hudi.common.schema.HoodieSchema as a
    wrapper that replaces direct org.apache.avro.Schema use across
    HoodieReaderContext, HoodieFileReaderFactory, TableSchemaResolver, and
    HoodieFileGroupReader.Builder. The cherry-picked bump landed the source
    at Hudi 1.1.0 APIs, so a clean compile against 1.3.0-SNAPSHOT failed in
    four files plus a kryo classpath issue.
    
    - HudiTrinoFileReaderFactory: switch all three newHFileFileReader
      overrides to Option<HoodieSchema>.
    - HudiTrinoReaderContext: switch getFileRecordIterator overrides and
      mergeBootstrapReaders to HoodieSchema; stub mergeBootstrapReaders with
      UnsupportedOperationException since the Trino connector does not use
      bootstrap merge.
    - HudiUtil.getLatestTableSchema: return HoodieSchema directly (drop the
      wasteful HoodieSchema -> Avro -> HoodieSchema round-trip via
      toAvroSchema/fromAvroSchema at the page-source-provider boundary).
    - HudiTableHandle: propagate HoodieSchema through the field, ctors, and
      buildTableSchema (now HoodieSchema.parse(...)); getTableSchemaStr uses
      HoodieSchema::toString.
    - HudiMetadata: align the Lazy<HoodieSchema> wrapper.
    - HudiPageSourceProvider / IndexSupportFactory: convert to Avro only at
      the genuine Avro boundaries (constructSchema and getFieldFromSchema).
    - pom.xml: declare the kryo dep at compile scope explicitly. The Trino
      BOM manages kryo at test scope, which left HoodieRecord's
      KryoSerializable superinterface unresolvable at compile time.
---
 hudi-trino-plugin/pom.xml                              |  4 +++-
 .../main/java/io/trino/plugin/hudi/HudiMetadata.java   |  4 ++--
 .../io/trino/plugin/hudi/HudiPageSourceProvider.java   |  9 +++++----
 .../java/io/trino/plugin/hudi/HudiTableHandle.java     | 18 +++++++++---------
 .../src/main/java/io/trino/plugin/hudi/HudiUtil.java   |  5 +++--
 .../plugin/hudi/io/HudiTrinoFileReaderFactory.java     |  8 ++++----
 .../plugin/hudi/query/index/IndexSupportFactory.java   |  2 +-
 .../plugin/hudi/reader/HudiTrinoReaderContext.java     | 16 +++++++++-------
 8 files changed, 36 insertions(+), 30 deletions(-)

diff --git a/hudi-trino-plugin/pom.xml b/hudi-trino-plugin/pom.xml
index 9670f8a3e43d..a526e593637d 100644
--- a/hudi-trino-plugin/pom.xml
+++ b/hudi-trino-plugin/pom.xml
@@ -59,10 +59,12 @@
         <dependency>
             <!-- Required for compilation: HoodieRecord implements KryoSerializable,
                  so the compiler needs Kryo on classpath to verify the class hierarchy
-                 when loading HoodieRecord for static imports -->
+                 when loading HoodieRecord for static imports.
+                 Explicit compile scope overrides the Trino BOM, which manages kryo at test scope. -->
             <groupId>com.esotericsoftware</groupId>
             <artifactId>kryo</artifactId>
             <version>4.0.2</version>
+            <scope>compile</scope>
         </dependency>
 
         <dependency>
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiMetadata.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiMetadata.java
index 2613be54ff09..90bdd2c6e2fd 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiMetadata.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiMetadata.java
@@ -47,8 +47,8 @@ import io.trino.spi.predicate.TupleDomain;
 import io.trino.spi.statistics.Estimate;
 import io.trino.spi.statistics.TableStatistics;
 import io.trino.spi.type.TypeManager;
-import org.apache.avro.Schema;
 import org.apache.hudi.common.model.HoodieTableType;
+import org.apache.hudi.common.schema.HoodieSchema;
 import org.apache.hudi.common.table.HoodieTableMetaClient;
 import org.apache.hudi.common.table.timeline.HoodieInstant;
 import org.apache.hudi.common.table.timeline.versioning.v2.InstantComparatorV2;
@@ -163,7 +163,7 @@ public class HudiMetadata
         String inputFormat = table.getStorage().getStorageFormat().getInputFormat();
         HoodieTableType hoodieTableType = HudiTableTypeUtils.fromInputFormat(inputFormat);
         Lazy<HoodieTableMetaClient> lazyMetaClient = Lazy.lazily(() -> buildTableMetaClient(fileSystem, tableName.toString(), basePath));
-        Optional<Lazy<Schema>> hudiTableSchema = isResolveColumnNameCasingEnabled(session) ?
+        Optional<Lazy<HoodieSchema>> hudiTableSchema = isResolveColumnNameCasingEnabled(session) ?
                 Optional.of(Lazy.lazily(() -> getLatestTableSchema(lazyMetaClient.get(), tableName.getTableName()))) : Optional.empty();
 
         return new HudiTableHandle(
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSourceProvider.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSourceProvider.java
index 1553b8389a0b..980739af6dcd 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSourceProvider.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiPageSourceProvider.java
@@ -53,6 +53,7 @@ import io.trino.spi.predicate.TupleDomain;
 import org.apache.avro.Schema;
 import org.apache.avro.generic.IndexedRecord;
 import org.apache.hudi.common.model.HoodieTableType;
+import org.apache.hudi.common.schema.HoodieSchema;
 import org.apache.hudi.common.table.HoodieTableMetaClient;
 import org.apache.hudi.common.table.read.HoodieFileGroupReader;
 import org.apache.hudi.common.util.ValidationUtils;
@@ -223,19 +224,19 @@ public class HudiPageSourceProvider
                 dataColumnHandles,
                 hudiMetaAndDataColumnHandles,
                 synthesizedColumnHandler);
-        Schema dataSchema =
+        HoodieSchema dataSchema =
                 Optional.ofNullable(hudiTableHandle.getTableSchema())
                         .orElseGet(() -> getLatestTableSchema(metaClient, hudiTableHandle.getTableName()));
 
-        // Construct an Avro schema for log file reader
-        Schema requestedSchema = constructSchema(dataSchema, hudiMetaAndDataColumnHandles.stream().map(HiveColumnHandle::getName).toList());
+        // constructSchema operates on Avro schema to assemble the requested schema for the log file reader.
+        Schema requestedSchema = constructSchema(dataSchema.toAvroSchema(), hudiMetaAndDataColumnHandles.stream().map(HiveColumnHandle::getName).toList());
         HoodieFileGroupReader<IndexedRecord> fileGroupReader =
                 HoodieFileGroupReader.<IndexedRecord>newBuilder()
                         .withReaderContext(readerContext)
                         .withHoodieTableMetaClient(metaClient)
                         .withFileSlice(convertToFileSlice(hudiSplit, hudiTableHandle.getBasePath()))
                         .withDataSchema(dataSchema)
-                        .withRequestedSchema(requestedSchema)
+                        .withRequestedSchema(HoodieSchema.fromAvroSchema(requestedSchema))
                         .withLatestCommitTime(hudiTableHandle.getLatestCommitTime())
                         .withProps(metaClient.getTableConfig().getProps())
                         .withShouldUseRecordPosition(false)
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiTableHandle.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiTableHandle.java
index f9f828bcca55..1b9efd1c6e18 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiTableHandle.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiTableHandle.java
@@ -24,8 +24,8 @@ import io.trino.spi.TrinoException;
 import io.trino.spi.connector.ConnectorTableHandle;
 import io.trino.spi.connector.SchemaTableName;
 import io.trino.spi.predicate.TupleDomain;
-import org.apache.avro.Schema;
 import org.apache.hudi.common.model.HoodieTableType;
+import org.apache.hudi.common.schema.HoodieSchema;
 import org.apache.hudi.common.table.HoodieTableMetaClient;
 import org.apache.hudi.common.table.timeline.HoodieInstant;
 import org.apache.hudi.common.util.StringUtils;
@@ -54,7 +54,7 @@ public class HudiTableHandle
     private final Set<HiveColumnHandle> constraintColumns;
     private final TupleDomain<HiveColumnHandle> partitionPredicates;
     private final TupleDomain<HiveColumnHandle> regularPredicates;
-    private final Optional<Lazy<Schema>> hudiTableSchema;
+    private final Optional<Lazy<HoodieSchema>> hudiTableSchema;
     // Coordinator-only
     private final transient Optional<Table> table;
     private final transient Optional<Lazy<HoodieTableMetaClient>> lazyMetaClient;
@@ -89,7 +89,7 @@ public class HudiTableHandle
             Set<HiveColumnHandle> constraintColumns,
             TupleDomain<HiveColumnHandle> partitionPredicates,
             TupleDomain<HiveColumnHandle> regularPredicates,
-            Optional<Lazy<Schema>> hudiTableSchema)
+            Optional<Lazy<HoodieSchema>> hudiTableSchema)
     {
         this(
                 Optional.of(table),
@@ -128,7 +128,7 @@ public class HudiTableHandle
             Set<HiveColumnHandle> constraintColumns,
             TupleDomain<HiveColumnHandle> partitionPredicates,
             TupleDomain<HiveColumnHandle> regularPredicates,
-            Optional<Lazy<Schema>> hudiTableSchema,
+            Optional<Lazy<HoodieSchema>> hudiTableSchema,
             Supplier<String> latestCommitTimeSupplier)
     {
         this.table = requireNonNull(table, "table is null");
@@ -147,19 +147,19 @@ public class HudiTableHandle
     }
 
     /**
-     * Builds a lazily-parsed Avro schema from the given schema string.
+     * Builds a lazily-parsed schema from the given Avro schema JSON string.
      * <p>
      * Returns {@code Optional.empty()} if the input string is null/empty
      * or if parsing the schema fails.
      */
-    private static Optional<Lazy<Schema>> buildTableSchema(String tableSchemaStr)
+    private static Optional<Lazy<HoodieSchema>> buildTableSchema(String tableSchemaStr)
     {
         if (StringUtils.isNullOrEmpty(tableSchemaStr)) {
             return Optional.empty();
         }
 
         try {
-            Lazy<Schema> lazySchema = Lazy.lazily(() -> new Schema.Parser().parse(tableSchemaStr));
+            Lazy<HoodieSchema> lazySchema = Lazy.lazily(() -> HoodieSchema.parse(tableSchemaStr));
             return Optional.of(lazySchema);
         }
         catch (Exception e) {
@@ -231,12 +231,12 @@ public class HudiTableHandle
     {
         return hudiTableSchema
                 .map(Lazy::get)
-                .map(Schema::toString)
+                .map(HoodieSchema::toString)
                 .orElse("");
     }
 
     @JsonIgnore
-    public Schema getTableSchema()
+    public HoodieSchema getTableSchema()
     {
         return hudiTableSchema.map(Lazy::get).orElse(null);
     }
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiUtil.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiUtil.java
index 52e594bbc4be..1eb84c2fc88e 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiUtil.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiUtil.java
@@ -50,6 +50,7 @@ import org.apache.hudi.common.model.HoodieBaseFile;
 import org.apache.hudi.common.model.HoodieFileFormat;
 import org.apache.hudi.common.model.HoodieFileGroupId;
 import org.apache.hudi.common.model.HoodieLogFile;
+import org.apache.hudi.common.schema.HoodieSchema;
 import org.apache.hudi.common.table.HoodieTableMetaClient;
 import org.apache.hudi.common.table.TableSchemaResolver;
 import org.apache.hudi.common.table.view.HoodieTableFileSystemView;
@@ -399,11 +400,11 @@ public final class HudiUtil
                 tableMetadata, metaClient, metaClient.getActiveTimeline().getCommitsTimeline().filterCompletedInstants());
     }
 
-    public static Schema getLatestTableSchema(HoodieTableMetaClient metaClient, String tableName)
+    public static HoodieSchema getLatestTableSchema(HoodieTableMetaClient metaClient, String tableName)
     {
         try {
             HoodieTimer timer = HoodieTimer.start();
-            Schema schema = new TableSchemaResolver(metaClient).getTableAvroSchema();
+            HoodieSchema schema = new TableSchemaResolver(metaClient).getTableSchema();
             log.info("Fetched table schema for table %s in %s ms", tableName, timer.endTimer());
             return schema;
         }
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/io/HudiTrinoFileReaderFactory.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/io/HudiTrinoFileReaderFactory.java
index 3571de43d79e..699992cefc8e 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/io/HudiTrinoFileReaderFactory.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/io/HudiTrinoFileReaderFactory.java
@@ -13,8 +13,8 @@
  */
 package io.trino.plugin.hudi.io;
 
-import org.apache.avro.Schema;
 import org.apache.hudi.common.config.HoodieConfig;
+import org.apache.hudi.common.schema.HoodieSchema;
 import org.apache.hudi.common.util.Option;
 import org.apache.hudi.io.storage.HFileReaderFactory;
 import org.apache.hudi.io.storage.HoodieAvroBootstrapFileReader;
@@ -44,7 +44,7 @@ public class HudiTrinoFileReaderFactory
     @Override
     protected HoodieFileReader newHFileFileReader(HoodieConfig hoodieConfig,
             StoragePath path,
-            Option<Schema> schemaOption)
+            Option<HoodieSchema> schemaOption)
             throws IOException
     {
         HFileReaderFactory readerFactory = HFileReaderFactory.builder()
@@ -59,7 +59,7 @@ public class HudiTrinoFileReaderFactory
             StoragePath path,
             HoodieStorage storage,
             byte[] content,
-            Option<Schema> schemaOption)
+            Option<HoodieSchema> schemaOption)
             throws IOException
     {
         HFileReaderFactory readerFactory = HFileReaderFactory.builder()
@@ -70,7 +70,7 @@ public class HudiTrinoFileReaderFactory
     }
 
     @Override
-    protected HoodieFileReader newHFileFileReader(HoodieConfig hoodieConfig, StoragePathInfo pathInfo, Option<Schema> schemaOption)
+    protected HoodieFileReader newHFileFileReader(HoodieConfig hoodieConfig, StoragePathInfo pathInfo, Option<HoodieSchema> schemaOption)
             throws IOException
     {
         HFileReaderFactory readerFactory = HFileReaderFactory.builder()
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/query/index/IndexSupportFactory.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/query/index/IndexSupportFactory.java
index 5d98177896c4..e31f3202a76e 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/query/index/IndexSupportFactory.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/query/index/IndexSupportFactory.java
@@ -131,7 +131,7 @@ public class IndexSupportFactory
         if (isResolveColumnNameCasingEnabled(session)) {
             // if column case reconciliation is enabled, transform the tuple domain keys to match the column names from the Hudi table.
             return tupleDomain.transformKeys(hiveColumnHandle ->
-                    getFieldFromSchema(hiveColumnHandle.getName(), hudiTableHandle.getTableSchema()).name());
+                    getFieldFromSchema(hiveColumnHandle.getName(), hudiTableHandle.getTableSchema().toAvroSchema()).name());
         }
         return tupleDomain.transformKeys(HiveColumnHandle::getName);
     }
diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/reader/HudiTrinoReaderContext.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/reader/HudiTrinoReaderContext.java
index 1f7584c3c168..cb1bc2e09a83 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/reader/HudiTrinoReaderContext.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/reader/HudiTrinoReaderContext.java
@@ -18,11 +18,11 @@ import io.trino.plugin.hudi.util.HudiAvroSerializer;
 import io.trino.plugin.hudi.util.SynthesizedColumnHandler;
 import io.trino.spi.Page;
 import io.trino.spi.connector.ConnectorPageSource;
-import org.apache.avro.Schema;
 import org.apache.avro.generic.IndexedRecord;
 import org.apache.hudi.avro.AvroRecordContext;
 import org.apache.hudi.common.config.RecordMergeMode;
 import org.apache.hudi.common.engine.HoodieReaderContext;
+import org.apache.hudi.common.schema.HoodieSchema;
 import org.apache.hudi.common.model.HoodiePreCombineAvroRecordMerger;
 import org.apache.hudi.common.model.HoodieRecordMerger;
 import org.apache.hudi.common.table.HoodieTableConfig;
@@ -73,8 +73,8 @@ public class HudiTrinoReaderContext
             StoragePath storagePath,
             long start,
             long length,
-            Schema dataSchema,
-            Schema requiredSchema,
+            HoodieSchema dataSchema,
+            HoodieSchema requiredSchema,
             HoodieStorage storage)
     {
         return createRecordIterator();
@@ -85,8 +85,8 @@ public class HudiTrinoReaderContext
             StoragePathInfo storagePathInfo,
             long start,
             long length,
-            Schema dataSchema,
-            Schema requiredSchema,
+            HoodieSchema dataSchema,
+            HoodieSchema requiredSchema,
             HoodieStorage storage)
     {
         return createRecordIterator();
@@ -152,8 +152,10 @@ public class HudiTrinoReaderContext
     }
 
     @Override
-    public ClosableIterator<IndexedRecord> mergeBootstrapReaders(ClosableIterator<IndexedRecord> skeletonFileIterator, Schema skeletonRequiredSchema, ClosableIterator<IndexedRecord> dataFileIterator, Schema dataRequiredSchema, List<Pair<String, Object>> requiredPartitionFieldAndValues)
+    public ClosableIterator<IndexedRecord> mergeBootstrapReaders(ClosableIterator<IndexedRecord> skeletonFileIterator, HoodieSchema skeletonRequiredSchema, ClosableIterator<IndexedRecord> dataFileIterator, HoodieSchema dataRequiredSchema, List<Pair<String, Object>> requiredPartitionFieldAndValues)
     {
-        return null;
+        // Bootstrap merge is not exercised by the Trino connector; reads of bootstrap tables go
+        // through the regular page-source path. Throwing surfaces accidental use loudly.
+        throw new UnsupportedOperationException("HudiTrinoReaderContext does not support bootstrap merge");
     }
 }


(hudi) 03/36: fix: Append Only Required Hudi Meta Fields for MOR Tables

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit 91a7324929e5f578ac0dd03e558611602110f0b8
Author: vamsikarnika <va...@gmail.com>
AuthorDate: Wed Sep 24 16:50:28 2025 +0530

    fix: Append Only Required Hudi Meta Fields for MOR Tables
    
    * fix test data
    
    * Add support for Column stats index
---
 .../main/java/io/trino/plugin/hudi/HudiUtil.java   |  34 ++++++++-------------
 .../hudi-testing-data/hudi_cow_pt_tbl.zip          | Bin 11750 -> 11752 bytes
 .../hudi-testing-data/hudi_non_part_cow.zip        | Bin 5980 -> 5966 bytes
 3 files changed, 13 insertions(+), 21 deletions(-)

diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiUtil.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiUtil.java
index 5389e80f5718..8eb10de4cc4c 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiUtil.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiUtil.java
@@ -64,7 +64,6 @@ import java.util.Set;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
-import java.util.stream.IntStream;
 
 import static io.airlift.slice.SizeOf.estimatedSizeOf;
 import static io.trino.plugin.hive.HiveErrorCode.HIVE_INVALID_METADATA;
@@ -78,7 +77,8 @@ import static io.trino.plugin.hudi.HudiErrorCode.HUDI_META_CLIENT_ERROR;
 import static io.trino.plugin.hudi.HudiErrorCode.HUDI_SCHEMA_ERROR;
 import static io.trino.plugin.hudi.HudiErrorCode.HUDI_UNSUPPORTED_FILE_FORMAT;
 import static java.lang.Math.toIntExact;
-import static org.apache.hudi.common.model.HoodieRecord.HOODIE_META_COLUMNS;
+import static org.apache.hudi.common.model.HoodieRecord.RECORD_KEY_METADATA_FIELD;
+import static org.apache.hudi.common.model.HoodieRecord.RECORD_KEY_META_FIELD_ORD;
 
 public final class HudiUtil
 {
@@ -328,30 +328,22 @@ public final class HudiUtil
                 .map(HiveColumnHandle::getName)
                 .collect(Collectors.toSet());
 
-        // If all Hudi meta columns are already present, return the original list
-        if (dataColumnNames.containsAll(HOODIE_META_COLUMNS)) {
+        // If Hudi record key meta column is already present, return the original list
+        if (dataColumnNames.contains(RECORD_KEY_METADATA_FIELD)) {
             return dataColumns;
         }
 
-        // Identify only the meta columns that are missing from dataColumns to avoid duplicates
-        List<String> missingMetaColumns = HOODIE_META_COLUMNS.stream()
-                .filter(metaColumn -> !dataColumnNames.contains(metaColumn))
-                .toList();
-
         List<HiveColumnHandle> columns = new ArrayList<>();
 
-        // Create and prepend the new HiveColumnHandles for the missing meta columns
-        columns.addAll(IntStream.range(0, missingMetaColumns.size())
-                .boxed()
-                .map(i -> new HiveColumnHandle(
-                        missingMetaColumns.get(i),
-                        i,
-                        HiveType.HIVE_STRING,
-                        VarcharType.VARCHAR,
-                        Optional.empty(),
-                        HiveColumnHandle.ColumnType.REGULAR,
-                        Optional.empty()))
-                .toList());
+        // Create and prepend the new HiveColumnHandle for the record key column
+        columns.add(new HiveColumnHandle(
+                RECORD_KEY_METADATA_FIELD,
+                RECORD_KEY_META_FIELD_ORD,
+                HiveType.HIVE_STRING,
+                VarcharType.VARCHAR,
+                Optional.empty(),
+                HiveColumnHandle.ColumnType.REGULAR,
+                Optional.empty()));
 
         // Add all the original data columns after the new meta columns
         columns.addAll(dataColumns);
diff --git a/hudi-trino-plugin/src/test/resources/hudi-testing-data/hudi_cow_pt_tbl.zip b/hudi-trino-plugin/src/test/resources/hudi-testing-data/hudi_cow_pt_tbl.zip
index 2f2238b22339..47c0532a9369 100644
Binary files a/hudi-trino-plugin/src/test/resources/hudi-testing-data/hudi_cow_pt_tbl.zip and b/hudi-trino-plugin/src/test/resources/hudi-testing-data/hudi_cow_pt_tbl.zip differ
diff --git a/hudi-trino-plugin/src/test/resources/hudi-testing-data/hudi_non_part_cow.zip b/hudi-trino-plugin/src/test/resources/hudi-testing-data/hudi_non_part_cow.zip
index 019860e88cff..55632f95ca9f 100644
Binary files a/hudi-trino-plugin/src/test/resources/hudi-testing-data/hudi_non_part_cow.zip and b/hudi-trino-plugin/src/test/resources/hudi-testing-data/hudi_non_part_cow.zip differ


(hudi) 01/36: feat(trino): wire hudi-trino-plugin and bundle for RFC-105 shim split

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit 72b78687d6bac3a37141ebc44229c4f6515cb994
Author: voon <vo...@gmail.com>
AuthorDate: Thu May 21 19:24:38 2026 +0800

    feat(trino): wire hudi-trino-plugin and bundle for RFC-105 shim split
    
    Configures the Hudi-side build to publish org.apache.hudi:hudi-trino-bundle
    as the artifact consumed by the Trino-side HudiPlugin shim:
    
    - Rewrite hudi-trino-plugin/pom.xml as a regular Hudi module (parent
      org.apache.hudi:hudi, packaging jar, ${project.version} for hudi-* deps);
      import io.trino:trino-root:472 as a BOM for Trino/Airlift version mgmt;
      enforce JDK 25 for compile and runtime.
    - Add -Phudi-trino profile gating both hudi-trino-plugin and
      packaging/hudi-trino-bundle so default builds are unaffected; remove the
      obsolete RAT exclusion for hudi-trino-plugin/**; add trino.connector.version
      property to the root pom.
    - Update hudi-trino-bundle to depend on hudi-trino-plugin and shade its
      classes into the published jar (io.trino.plugin.hudi.* stays at its
      canonical FQN).
    - Add hudi_trino_ci.yml (build + test under JDK 25, asserts
      HudiConnectorFactory is present in the bundle jar) and
      hudi_trino_compat.yml (nightly SPI-drift compile against trinodb/trino
      master).
    
    Connector source porting to Hudi 1.3.0-SNAPSHOT APIs is a separate follow-up.
---
 .github/workflows/hudi_trino_ci.yml     |  50 +++++++++++++++
 .github/workflows/hudi_trino_compat.yml |  55 +++++++++++++++++
 hudi-trino-plugin/pom.xml               | 104 +++++++++++++++++++++++---------
 packaging/hudi-trino-bundle/pom.xml     |   6 ++
 pom.xml                                 |  13 +++-
 5 files changed, 199 insertions(+), 29 deletions(-)

diff --git a/.github/workflows/hudi_trino_ci.yml b/.github/workflows/hudi_trino_ci.yml
new file mode 100644
index 000000000000..82910688c81e
--- /dev/null
+++ b/.github/workflows/hudi_trino_ci.yml
@@ -0,0 +1,50 @@
+name: Hudi Trino Connector CI
+
+on:
+  push:
+    branches:
+      - master
+      - 'release-*'
+    paths:
+      - 'hudi-trino-plugin/**'
+      - 'packaging/hudi-trino-bundle/**'
+      - '.github/workflows/hudi_trino_ci.yml'
+  pull_request:
+    branches:
+      - master
+      - 'release-*'
+    paths:
+      - 'hudi-trino-plugin/**'
+      - 'packaging/hudi-trino-bundle/**'
+      - '.github/workflows/hudi_trino_ci.yml'
+  workflow_dispatch:
+
+concurrency:
+  group: hudi-trino-ci-${{ github.ref }}
+  cancel-in-progress: ${{ !contains(github.ref, 'master') && !contains(github.ref, 'release-') }}
+
+env:
+  MVN_ARGS: -e -ntp -B -V -Dgpg.skip -Djacoco.skip -Pwarn-log
+
+jobs:
+  build-and-test:
+    name: Build and Test (JDK 25)
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v5
+      - name: Set up JDK 25
+        uses: actions/setup-java@v5
+        with:
+          java-version: '25'
+          distribution: 'temurin'
+          cache: maven
+      - name: Build connector and bundle
+        run: ./mvnw $MVN_ARGS -Phudi-trino -pl hudi-trino-plugin,packaging/hudi-trino-bundle -am install -DskipTests
+      - name: Verify bundle contains connector classes
+        run: |
+          BUNDLE_JAR=$(ls packaging/hudi-trino-bundle/target/hudi-trino-bundle-*.jar | grep -v sources | head -n 1)
+          echo "Inspecting $BUNDLE_JAR"
+          jar tf "$BUNDLE_JAR" | grep -E 'io/trino/plugin/hudi/HudiConnectorFactory\.class$' \
+            || (echo "ERROR: HudiConnectorFactory not present in bundle"; exit 1)
+      - name: Run connector tests
+        run: ./mvnw $MVN_ARGS -Phudi-trino -pl hudi-trino-plugin test
diff --git a/.github/workflows/hudi_trino_compat.yml b/.github/workflows/hudi_trino_compat.yml
new file mode 100644
index 000000000000..97162d2fe214
--- /dev/null
+++ b/.github/workflows/hudi_trino_compat.yml
@@ -0,0 +1,55 @@
+name: Hudi Trino SPI Compatibility
+
+on:
+  schedule:
+    - cron: '17 4 * * *'
+  workflow_dispatch:
+
+env:
+  MVN_ARGS: -e -ntp -B -V -Dgpg.skip -Djacoco.skip
+
+jobs:
+  compile-against-trino-master:
+    name: Compile hudi-trino-plugin against trinodb/trino master
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout Hudi
+        uses: actions/checkout@v5
+        with:
+          path: hudi
+      - name: Checkout trinodb/trino master
+        uses: actions/checkout@v5
+        with:
+          repository: trinodb/trino
+          ref: master
+          path: trino
+      - name: Set up JDK 25
+        uses: actions/setup-java@v5
+        with:
+          java-version: '25'
+          distribution: 'temurin'
+          cache: maven
+      - name: Read Trino SPI version
+        id: trino-version
+        run: |
+          # trinodb/trino's root pom declares <version>NNN-SNAPSHOT</version>; strip the suffix.
+          VERSION=$(grep -m1 '<version>' trino/pom.xml | sed -E 's|.*<version>([0-9]+)(-SNAPSHOT)?</version>.*|\1|')
+          echo "trino_version=$VERSION" >> "$GITHUB_OUTPUT"
+          echo "Detected Trino version: $VERSION"
+      - name: Compile hudi-trino-plugin against current Trino SPI
+        working-directory: hudi
+        run: |
+          ./mvnw $MVN_ARGS -Phudi-trino \
+            -Dtrino.connector.version=${{ steps.trino-version.outputs.trino_version }} \
+            -pl hudi-trino-plugin -am compile
+      - name: Open issue on failure
+        if: failure()
+        uses: actions/github-script@v7
+        with:
+          script: |
+            github.rest.issues.create({
+              owner: context.repo.owner,
+              repo: context.repo.repo,
+              title: `hudi-trino-plugin SPI drift detected against Trino ${{ steps.trino-version.outputs.trino_version }}`,
+              body: `Nightly compatibility build failed. See run ${context.runId}.`
+            });
diff --git a/hudi-trino-plugin/pom.xml b/hudi-trino-plugin/pom.xml
index c67ab6a07f51..be6f3a324369 100644
--- a/hudi-trino-plugin/pom.xml
+++ b/hudi-trino-plugin/pom.xml
@@ -1,28 +1,63 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
 
     <parent>
-        <groupId>io.trino</groupId>
-        <artifactId>trino-root</artifactId>
-        <version>472</version>
-        <!-- Stop looking for the parent on local file system -->
-        <relativePath />
+        <groupId>org.apache.hudi</groupId>
+        <artifactId>hudi</artifactId>
+        <version>1.3.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
     </parent>
 
-    <artifactId>trino-hudi</artifactId>
-    <packaging>trino-plugin</packaging>
-    <description>Trino - Hudi connector</description>
+    <artifactId>hudi-trino-plugin</artifactId>
+    <packaging>jar</packaging>
+    <description>Hudi connector for Trino (RFC-105)</description>
 
     <properties>
-        <air.compiler.fail-warnings>true</air.compiler.fail-warnings>
-        <dep.hudi.version>1.0.2</dep.hudi.version>
+        <!-- Trino SPI / library version this connector compiles against. Bumped via root pom. -->
+        <dep.trino.version>${trino.connector.version}</dep.trino.version>
         <trino.parquet.version>1.15.2</trino.parquet.version>
+        <!-- Connector requires JDK 25 to compile and run (matches Trino runtime requirement). -->
+        <hudi.trino.java.version>25</hudi.trino.java.version>
+        <main.basedir>${project.parent.basedir}</main.basedir>
+        <checkstyle.skip>true</checkstyle.skip>
     </properties>
 
+    <dependencyManagement>
+        <dependencies>
+            <!-- Import Trino's parent POM as a BOM. This pulls in version mgmt for io.trino:*,
+                 io.airlift:*, jackson, opentelemetry, slice, guice, jakarta.validation, etc.
+                 Per RFC-105, Trino versions are authoritative for shared deps. -->
+            <dependency>
+                <groupId>io.trino</groupId>
+                <artifactId>trino-root</artifactId>
+                <version>${dep.trino.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
     <dependencies>
         <dependency>
-            <!--Used to test execution in task executor after de-serializing-->
+            <!-- Used to test execution in task executor after de-serializing -->
             <groupId>com.esotericsoftware</groupId>
             <artifactId>kryo</artifactId>
             <version>4.0.2</version>
@@ -132,7 +167,7 @@
         <dependency>
             <groupId>org.apache.hudi</groupId>
             <artifactId>hudi-common</artifactId>
-            <version>${dep.hudi.version}</version>
+            <version>${project.version}</version>
             <exclusions>
                 <exclusion>
                     <groupId>io.dropwizard.metrics</groupId>
@@ -156,7 +191,7 @@
         <dependency>
             <groupId>org.apache.hudi</groupId>
             <artifactId>hudi-hive-sync</artifactId>
-            <version>${dep.hudi.version}</version>
+            <version>${project.version}</version>
             <exclusions>
                 <exclusion>
                     <groupId>org.apache.hudi</groupId>
@@ -168,7 +203,7 @@
         <dependency>
             <groupId>org.apache.hudi</groupId>
             <artifactId>hudi-io</artifactId>
-            <version>${dep.hudi.version}</version>
+            <version>${project.version}</version>
             <exclusions>
                 <exclusion>
                     <groupId>com.google.protobuf</groupId>
@@ -180,7 +215,7 @@
         <dependency>
             <groupId>org.apache.hudi</groupId>
             <artifactId>hudi-sync-common</artifactId>
-            <version>${dep.hudi.version}</version>
+            <version>${project.version}</version>
             <exclusions>
                 <exclusion>
                     <groupId>org.apache.hudi</groupId>
@@ -380,7 +415,7 @@
         <dependency>
             <groupId>org.apache.hudi</groupId>
             <artifactId>hudi-client-common</artifactId>
-            <version>${dep.hudi.version}</version>
+            <version>${project.version}</version>
             <scope>test</scope>
             <exclusions>
                 <exclusion>
@@ -393,7 +428,7 @@
         <dependency>
             <groupId>org.apache.hudi</groupId>
             <artifactId>hudi-hadoop-common</artifactId>
-            <version>${dep.hudi.version}</version>
+            <version>${project.version}</version>
             <scope>test</scope>
             <exclusions>
                 <exclusion>
@@ -406,7 +441,7 @@
         <dependency>
             <groupId>org.apache.hudi</groupId>
             <artifactId>hudi-java-client</artifactId>
-            <version>${dep.hudi.version}</version>
+            <version>${project.version}</version>
             <scope>test</scope>
             <exclusions>
                 <exclusion>
@@ -463,19 +498,34 @@
     <build>
         <plugins>
             <plugin>
-                <groupId>org.basepom.maven</groupId>
-                <artifactId>duplicate-finder-maven-plugin</artifactId>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
                 <configuration>
-                    <ignoredResourcePatterns>
-                        <!-- org.apache.hudi:hudi-client-common and org.apache.hudi:hudi-java-client log4j.properties duplicates -->
-                        <ignoredResourcePattern>log4j.properties</ignoredResourcePattern>
-                        <ignoredResourcePattern>log4j-surefire.properties</ignoredResourcePattern>
-                    </ignoredResourcePatterns>
+                    <!-- Override Hudi parent's Java 11 target. Trino SPI requires recent JDK. -->
+                    <source>${hudi.trino.java.version}</source>
+                    <target>${hudi.trino.java.version}</target>
+                    <release>${hudi.trino.java.version}</release>
                 </configuration>
             </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
+                <artifactId>maven-enforcer-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>enforce-jdk25</id>
+                        <goals>
+                            <goal>enforce</goal>
+                        </goals>
+                        <configuration>
+                            <rules>
+                                <requireJavaVersion>
+                                    <version>[${hudi.trino.java.version},)</version>
+                                    <message>hudi-trino-plugin requires JDK ${hudi.trino.java.version} or newer.</message>
+                                </requireJavaVersion>
+                            </rules>
+                        </configuration>
+                    </execution>
+                </executions>
             </plugin>
         </plugins>
     </build>
diff --git a/packaging/hudi-trino-bundle/pom.xml b/packaging/hudi-trino-bundle/pom.xml
index 691e2cce38e2..c58d7ae3c80b 100644
--- a/packaging/hudi-trino-bundle/pom.xml
+++ b/packaging/hudi-trino-bundle/pom.xml
@@ -67,6 +67,7 @@
               </transformers>
               <artifactSet>
                 <includes combine.children="append">
+                  <include>org.apache.hudi:hudi-trino-plugin</include>
                   <include>org.apache.hudi:hudi-hadoop-common</include>
                   <include>org.apache.hudi:hudi-common</include>
                   <include>org.apache.hudi:hudi-client-common</include>
@@ -168,6 +169,11 @@
 
   <dependencies>
     <!-- Hoodie -->
+    <dependency>
+      <groupId>org.apache.hudi</groupId>
+      <artifactId>hudi-trino-plugin</artifactId>
+      <version>${project.version}</version>
+    </dependency>
     <dependency>
       <groupId>org.apache.hudi</groupId>
       <artifactId>hudi-hadoop-mr-bundle</artifactId>
diff --git a/pom.xml b/pom.xml
index bc2f12137830..fbefb7577389 100644
--- a/pom.xml
+++ b/pom.xml
@@ -59,7 +59,6 @@
     <module>packaging/hudi-utilities-bundle</module>
     <module>packaging/hudi-utilities-slim-bundle</module>
     <module>packaging/hudi-timeline-server-bundle</module>
-    <module>packaging/hudi-trino-bundle</module>
     <module>hudi-examples</module>
     <module>hudi-flink-datasource</module>
     <module>hudi-kafka-connect</module>
@@ -130,6 +129,8 @@
     <hive.avro.version>1.11.4</hive.avro.version>
     <presto.version>0.273</presto.version>
     <trino.version>390</trino.version>
+    <!-- Trino SPI version that hudi-trino-plugin (RFC-105) compiles against. -->
+    <trino.connector.version>472</trino.connector.version>
     <hive.exec.classifier>core</hive.exec.classifier>
     <metrics.version>4.1.1</metrics.version>
     <orc.spark.version>1.6.0</orc.spark.version>
@@ -682,7 +683,6 @@
               <!-- local files not in version control -->
               <exclude>**/*.iml</exclude>
               <exclude>.mvn/**</exclude>
-              <exclude>hudi-trino-plugin/**</exclude>
             </excludes>
           </configuration>
           <executions>
@@ -2271,6 +2271,15 @@
         <module>packaging/hudi-metaserver-server-bundle</module>
       </modules>
     </profile>
+    <profile>
+      <!-- RFC-105: builds the Trino connector and its publishable shaded bundle.
+           Excluded from default builds because it requires JDK 25 and the Trino SPI. -->
+      <id>hudi-trino</id>
+      <modules>
+        <module>hudi-trino-plugin</module>
+        <module>packaging/hudi-trino-bundle</module>
+      </modules>
+    </profile>
     <profile>
       <id>integration-tests</id>
       <activation>


(hudi) 24/36: fix(trino): pin Jetty to 12.1.9 to unblock TestingTrinoServer startup

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit d6080d25425193a49926a1fca2766014a8fe7ce8
Author: voon <vo...@gmail.com>
AuthorDate: Tue May 26 23:52:45 2026 +0800

    fix(trino): pin Jetty to 12.1.9 to unblock TestingTrinoServer startup
    
    Hudi parent pom pins jetty-server / jetty-servlet to 9.4.57 (for its
    embedded timeline-server HTTP endpoint). Trino's testing scaffolding
    brings io.trino:trino-testing which expects Jetty 12.x APIs
    (org.eclipse.jetty.server.Request.Handler exists only in 12.x). The
    parent pin overrode trino-testing's declared 12.1.9 and tests crashed
    with NoClassDefFoundError when TestingTrinoServer wired up Guice.
    
    Two changes:
    - Exclude org.eclipse.jetty:* from hudi-common; the connector never
      starts a Hudi HTTP server.
    - Pin jetty-server to 12.1.9 directly in plugin dependencyManagement
      so it overrides Hudi parent for whatever else (trino-testing) pulls
      the artifact in.
    
    jetty-servlet was retired in Jetty 12 (moved to jetty-ee*-servlet) so
    no replacement pin is needed.
---
 hudi-trino-plugin/pom.xml | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/hudi-trino-plugin/pom.xml b/hudi-trino-plugin/pom.xml
index c26f0bb6fbc9..3659bc9a7058 100644
--- a/hudi-trino-plugin/pom.xml
+++ b/hudi-trino-plugin/pom.xml
@@ -74,6 +74,14 @@
                 <artifactId>jackson-annotations</artifactId>
                 <version>2.21</version>
             </dependency>
+            <!-- Hudi parent pins jetty-server / jetty-servlet at 9.4.57; Trino runs on Jetty 12
+                 (Request$Handler etc. exist only in 12.x). Pin jetty-server here to keep
+                 trino-testing's classpath consistent. jetty-servlet does not exist in 12.x. -->
+            <dependency>
+                <groupId>org.eclipse.jetty</groupId>
+                <artifactId>jetty-server</artifactId>
+                <version>12.1.9</version>
+            </dependency>
             <!-- Airbase manages junit-platform at 6.0.3 (paired with jupiter 6.x). Hudi manages
                  jupiter at 5.14.1 (paired with platform 1.14.1). Pin platform here to keep the
                  pair consistent; without this, surefire fails with OutputDirectoryCreator not found. -->
@@ -227,6 +235,13 @@
                     <groupId>org.apache.orc</groupId>
                     <artifactId>*</artifactId>
                 </exclusion>
+                <!-- Hudi pulls Jetty 9.x for its embedded HTTP server; Trino runs on Jetty 12.
+                     The connector does not start a Hudi HTTP server, so drop the legacy artifacts
+                     to avoid jar-set conflicts (Request$Handler missing from 9.x). -->
+                <exclusion>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>*</artifactId>
+                </exclusion>
                 <!-- Not used by the connector; excluded to keep the plugin jar set lean. -->
                 <exclusion>
                     <groupId>org.rocksdb</groupId>


(hudi) 21/36: fix(trino): pin junit-platform to keep it aligned with jupiter 5.14.1

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit b13ae80dc81763ea6e5d1c61f76614b24e21dbc7
Author: voon <vo...@gmail.com>
AuthorDate: Tue May 26 23:04:35 2026 +0800

    fix(trino): pin junit-platform to keep it aligned with jupiter 5.14.1
    
    Trino's grandparent BOM (io.airlift:airbase:375) manages
    junit-platform-* at 6.0.3 (paired with jupiter 6.x). Hudi's root pom
    manages junit-jupiter at 5.14.1 (paired with platform 1.14.1). With both
    BOMs imported, airbase wins for platform and we end up with jupiter 5.x +
    platform 6.x, which surefire fails to launch with:
    
      OutputDirectoryCreator not available; probably due to unaligned versions
      of the junit-platform-engine and junit-platform-launcher jars on the
      classpath/module path
    
    Pin junit-platform-commons / -engine / -launcher to ${junit.platform.version}
    (1.14.1) in the plugin's dependencyManagement so the local pin overrides
    airbase. Tests discover and run again.
---
 hudi-trino-plugin/pom.xml | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/hudi-trino-plugin/pom.xml b/hudi-trino-plugin/pom.xml
index 9ccd44eef81b..fd281d96ff30 100644
--- a/hudi-trino-plugin/pom.xml
+++ b/hudi-trino-plugin/pom.xml
@@ -55,6 +55,24 @@
                 <type>pom</type>
                 <scope>import</scope>
             </dependency>
+            <!-- Airbase manages junit-platform at 6.0.3 (paired with jupiter 6.x). Hudi manages
+                 jupiter at 5.14.1 (paired with platform 1.14.1). Pin platform here to keep the
+                 pair consistent; without this, surefire fails with OutputDirectoryCreator not found. -->
+            <dependency>
+                <groupId>org.junit.platform</groupId>
+                <artifactId>junit-platform-commons</artifactId>
+                <version>${junit.platform.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.junit.platform</groupId>
+                <artifactId>junit-platform-engine</artifactId>
+                <version>${junit.platform.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.junit.platform</groupId>
+                <artifactId>junit-platform-launcher</artifactId>
+                <version>${junit.platform.version}</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 


(hudi) 10/36: refactor(trino): drop shaded bundle, publish hudi-trino per RFC-105

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit 83b236f43305776f2c97838d059c4c4f7334117c
Author: voon <vo...@gmail.com>
AuthorDate: Sat May 23 03:02:45 2026 +0800

    refactor(trino): drop shaded bundle, publish hudi-trino per RFC-105
    
    RFC-105 specifies the published artifact as a regular non-shaded jar
    named org.apache.hudi:hudi-trino, citing Trino's URLClassLoader plugin
    isolation as the reason no shading is needed. The previous
    packaging/hudi-trino-bundle deviated from this and caused:
    - shaded-vs-canonical GenericRecord type mismatches in Trino-side tests
    - ever-growing SPI exclusion lists to satisfy check-spi-dependencies
    - lance / arrow / rocksdb dragging ~280MB into the Trino server tar
    - hudi-timeline-service pulling banned javax.servlet-api transitively
    - a two-step JDK 17 -> JDK 25 build because the bundle had to be rebuilt
    
    Changes:
    - Delete packaging/hudi-trino-bundle/ (module + pom + README) and remove
      it from the hudi-trino profile in the root pom.
    - Rename hudi-trino-plugin/pom.xml artifactId from hudi-trino-plugin to
      hudi-trino. Source dir stays hudi-trino-plugin/.
    - Add lance / arrow / rocksdb exclusions to hudi-common and hudi-io to
      prevent the 280MB transitive leak that the bundle was working around.
    - Add hudi-timeline-service exclusion to hudi-client-common (test scope).
    - Simplify hudi-trino-plugin/README.md to a single-module build (no more
      packaging step) and drop the bundle verify step from hudi_trino_ci.yml.
    
    Scope choices follow trino-iceberg / trino-delta-lake: io.trino:* and
    io.airlift:* compile-time deps stay at compile (each plugin's classloader
    bundles them). Only the Trino SPI shortlist (trino-spi, jackson-annotations,
    slice, opentelemetry-*, jol-core) is at provided.
---
 .github/workflows/hudi_trino_ci.yml                |  12 +-
 hudi-trino-plugin/README.md                        |  10 +-
 hudi-trino-plugin/pom.xml                          |  41 +-
 packaging/hudi-trino-bundle/README.md              | 103 -----
 packaging/hudi-trino-bundle/pom.xml                | 432 ---------------------
 .../java/org/apache/hudi/trino/bundle/Main.java    |  36 --
 pom.xml                                            |   6 +-
 7 files changed, 51 insertions(+), 589 deletions(-)

diff --git a/.github/workflows/hudi_trino_ci.yml b/.github/workflows/hudi_trino_ci.yml
index 82910688c81e..b9a89c52d99f 100644
--- a/.github/workflows/hudi_trino_ci.yml
+++ b/.github/workflows/hudi_trino_ci.yml
@@ -7,7 +7,6 @@ on:
       - 'release-*'
     paths:
       - 'hudi-trino-plugin/**'
-      - 'packaging/hudi-trino-bundle/**'
       - '.github/workflows/hudi_trino_ci.yml'
   pull_request:
     branches:
@@ -15,7 +14,6 @@ on:
       - 'release-*'
     paths:
       - 'hudi-trino-plugin/**'
-      - 'packaging/hudi-trino-bundle/**'
       - '.github/workflows/hudi_trino_ci.yml'
   workflow_dispatch:
 
@@ -38,13 +36,7 @@ jobs:
           java-version: '25'
           distribution: 'temurin'
           cache: maven
-      - name: Build connector and bundle
-        run: ./mvnw $MVN_ARGS -Phudi-trino -pl hudi-trino-plugin,packaging/hudi-trino-bundle -am install -DskipTests
-      - name: Verify bundle contains connector classes
-        run: |
-          BUNDLE_JAR=$(ls packaging/hudi-trino-bundle/target/hudi-trino-bundle-*.jar | grep -v sources | head -n 1)
-          echo "Inspecting $BUNDLE_JAR"
-          jar tf "$BUNDLE_JAR" | grep -E 'io/trino/plugin/hudi/HudiConnectorFactory\.class$' \
-            || (echo "ERROR: HudiConnectorFactory not present in bundle"; exit 1)
+      - name: Build connector
+        run: ./mvnw $MVN_ARGS -Phudi-trino -pl hudi-trino-plugin -am install -DskipTests
       - name: Run connector tests
         run: ./mvnw $MVN_ARGS -Phudi-trino -pl hudi-trino-plugin test
diff --git a/hudi-trino-plugin/README.md b/hudi-trino-plugin/README.md
index 4a9aba1403db..37f465baea8a 100644
--- a/hudi-trino-plugin/README.md
+++ b/hudi-trino-plugin/README.md
@@ -1,24 +1,26 @@
 # hudi-trino-plugin
 
-Hudi connector for Trino (RFC-105). Published as part of `org.apache.hudi:hudi-trino-bundle`; the Trino-side `HudiPlugin` shim loads classes from that bundle.
+Hudi connector for Trino (RFC-105). Published as `org.apache.hudi:hudi-trino` -- a regular non-shaded JAR. The Trino-side `trino-hudi` plugin module depends on this artifact and Trino's URLClassLoader isolates the plugin's transitive deps from the rest of the server, so no shading is required.
+
+The source directory is named `hudi-trino-plugin/`; the Maven artifactId is `hudi-trino`.
 
 ## Build
 
 Excluded from default builds. Activate the `hudi-trino` Maven profile:
 
 ```
-mvn -Phudi-trino -pl hudi-trino-plugin,packaging/hudi-trino-bundle -am install
+mvn -Phudi-trino -pl hudi-trino-plugin install
 ```
 
 Requires JDK 25 (enforced via `maven-enforcer-plugin`).
 
 ## IDE setup
 
-Only `hudi-trino-plugin` needs JDK 25. Leave the rest of Hudi on its native JDK (11 or 17) so you are not toggling the project default.
+Only this module needs JDK 25. Leave the rest of Hudi on its native JDK (11 or 17) so you are not toggling the project default.
 
 1. Activate the `hudi-trino` Maven profile so the IDE picks up the module.
    - IntelliJ: Maven tool window, Profiles, tick `hudi-trino`.
 2. Override the SDK for the `hudi-trino-plugin` module only, to Temurin 25 with Language level 25.
    - IntelliJ: `File > Project Structure > Modules > hudi-trino-plugin > Dependencies > Module SDK`.
 
-The enforcer rule only runs during `mvn`, not during the IDE's incremental compile.
\ No newline at end of file
+The enforcer rule only runs during `mvn`, not during the IDE's incremental compile.
diff --git a/hudi-trino-plugin/pom.xml b/hudi-trino-plugin/pom.xml
index 5f699d03a110..a2cc55fa1fe8 100644
--- a/hudi-trino-plugin/pom.xml
+++ b/hudi-trino-plugin/pom.xml
@@ -26,7 +26,8 @@
         <relativePath>../pom.xml</relativePath>
     </parent>
 
-    <artifactId>hudi-trino-plugin</artifactId>
+    <!-- Source dir is hudi-trino-plugin/ but artifactId is hudi-trino per RFC-105. -->
+    <artifactId>hudi-trino</artifactId>
     <packaging>jar</packaging>
     <description>Hudi connector for Trino (RFC-105)</description>
 
@@ -81,6 +82,10 @@
             <artifactId>guava</artifactId>
         </dependency>
 
+        <!-- Trino's plugin classloader bundles non-SPI compile deps with the plugin (one URLClassLoader
+             per plugin). Only the SPI shortlist further down (trino-spi, jackson-annotations, slice,
+             opentelemetry-*, jol-core) is at provided scope. Matches trino-iceberg / trino-delta-lake. -->
+
         <dependency>
             <!-- Trino bundles guice as the classes-only classifier; the BOM does not manage the plain jar. -->
             <groupId>com.google.inject</groupId>
@@ -194,6 +199,22 @@
                     <groupId>org.apache.orc</groupId>
                     <artifactId>*</artifactId>
                 </exclusion>
+                <!-- The Trino connector does not exercise Hudi's local state stores, Arrow
+                     materialization, or Lance integration. Excluding them keeps the plugin's
+                     runtime jar set lean (~280MB worth otherwise) and avoids dragging native
+                     libs (rocksdbjni) onto Trino's plugin classpath. -->
+                <exclusion>
+                    <groupId>org.rocksdb</groupId>
+                    <artifactId>*</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.arrow</groupId>
+                    <artifactId>*</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.lance</groupId>
+                    <artifactId>*</artifactId>
+                </exclusion>
             </exclusions>
         </dependency>
 
@@ -219,6 +240,19 @@
                     <groupId>com.google.protobuf</groupId>
                     <artifactId>protobuf-java</artifactId>
                 </exclusion>
+                <!-- Same rationale as hudi-common: connector does not use rocksdb / arrow / lance. -->
+                <exclusion>
+                    <groupId>org.rocksdb</groupId>
+                    <artifactId>*</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.arrow</groupId>
+                    <artifactId>*</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.lance</groupId>
+                    <artifactId>*</artifactId>
+                </exclusion>
             </exclusions>
         </dependency>
 
@@ -437,6 +471,11 @@
                     <groupId>*</groupId>
                     <artifactId>*</artifactId>
                 </exclusion>
+                <!-- hudi-timeline-service pulls Jetty + javax.servlet-api; Trino's enforcer bans them. -->
+                <exclusion>
+                    <groupId>org.apache.hudi</groupId>
+                    <artifactId>hudi-timeline-service</artifactId>
+                </exclusion>
             </exclusions>
         </dependency>
 
diff --git a/packaging/hudi-trino-bundle/README.md b/packaging/hudi-trino-bundle/README.md
deleted file mode 100644
index e73f2dd0903e..000000000000
--- a/packaging/hudi-trino-bundle/README.md
+++ /dev/null
@@ -1,103 +0,0 @@
-<!--
-  Licensed to the Apache Software Foundation (ASF) under one or more
-  contributor license agreements.  See the NOTICE file distributed with
-  this work for additional information regarding copyright ownership.
-  The ASF licenses this file to You under the Apache License, Version 2.0
-  (the "License"); you may not use this file except in compliance with
-  the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
--->
-
-# hudi-trino-bundle
-
-Shaded jar that ships the Trino-Hudi connector. Published as `org.apache.hudi:hudi-trino-bundle` (RFC-105). The Trino-side `HudiPlugin` shim depends on this artifact and loads `io.trino.plugin.hudi.HudiConnectorFactory` from it.
-
-## What is inside
-
-Connector classes (unshaded, canonical FQN preserved):
-- `io.trino.plugin.hudi.*` from `hudi-trino-plugin`
-
-Hudi runtime jars (no relocation):
-- `hudi-common`, `hudi-client-common`, `hudi-java-client`, `hudi-hadoop-common`, `hudi-hadoop-mr`
-
-Shaded third-party libs (relocated under `org.apache.hudi.*` or the `trino.bundle.bootstrap.shade.prefix`):
-- Kryo, parquet-avro, avro, caffeine, commons-io, dropwizard metrics, jol-core, protobuf
-
-What is NOT inside:
-- `META-INF/services/io.trino.spi.Plugin`. That manifest lives only on the Trino-side `trino-hudi` shim; never ship it from this bundle.
-
-## Build
-
-Two-step because `hudi-common` etc. use Lombok 1.18.36 which is not compatible with JDK 25, while `hudi-trino-plugin` requires JDK 25 for the Trino SPI. See `hudi-trino-plugin/README.md` for the why.
-
-```
-# Step 1, on JDK 17: install Hudi base modules into ~/.m2
-JAVA_HOME=$(/usr/libexec/java_home -v 17) \
-  mvn install -DskipTests -pl hudi-common,hudi-io,hudi-hive-sync,hudi-sync-common,hudi-hadoop-common,hudi-client-common,hudi-java-client,packaging/hudi-hadoop-mr-bundle -am
-
-# Step 2, on JDK 25: build the connector and bundle
-JAVA_HOME=$(/usr/libexec/java_home -v 25) \
-  mvn install -Phudi-trino -pl hudi-trino-plugin,packaging/hudi-trino-bundle
-```
-
-The shaded jar lands at `packaging/hudi-trino-bundle/target/hudi-trino-bundle-1.3.0-SNAPSHOT.jar` and is also installed to `~/.m2/repository/org/apache/hudi/hudi-trino-bundle/`.
-
-## Verify the jar
-
-```
-JAR=packaging/hudi-trino-bundle/target/hudi-trino-bundle-1.3.0-SNAPSHOT.jar
-
-# Connector entrypoint must be present at its canonical FQN
-jar tf "$JAR" | grep -E 'io/trino/plugin/hudi/HudiConnectorFactory\.class$'
-
-# Plugin SPI manifest must NOT be present (only the Trino-side shim ships that)
-jar tf "$JAR" | grep -E 'META-INF/services/io\.trino\.spi\.Plugin$' && echo "FAIL: bundle leaks Plugin SPI" || echo "OK"
-```
-
-## Consume from Trino
-
-The Trino-side `plugin/trino-hudi` is already wired:
-- `<dependency>org.apache.hudi:hudi-trino-bundle</dependency>` in `plugin/trino-hudi/pom.xml`.
-- Version property `<dep.hudi-trino.version>` in the root Trino `pom.xml`. Bump this to point at a newer published bundle.
-
-Local development flow:
-```
-# In the Trino repo, after step 2 above has installed the bundle to ~/.m2
-./mvnw -pl :trino-hudi install
-```
-
-The Trino build resolves `hudi-trino-bundle` from your local `~/.m2`. For Hudi snapshots, ensure Apache's snapshot repo is enabled in your Maven settings; otherwise the version property must point at a released version.
-
-## Publish
-
-Follows the standard Hudi `mvn deploy` flow under the `hudi-trino` profile:
-
-```
-JAVA_HOME=$(/usr/libexec/java_home -v 25) \
-  mvn deploy -Phudi-trino -pl hudi-trino-plugin,packaging/hudi-trino-bundle -DskipTests
-```
-
-For release candidates, include this bundle in the RC validation step alongside the other published Hudi bundles.
-
-### Before publishing: switch Trino version off SNAPSHOT
-
-The root pom currently sets `<trino.connector.version>480-SNAPSHOT</trino.connector.version>` because the connector tests depend on `trino-*-tests.jar` artifacts, and Trino only publishes the test-jar classifier for snapshot builds (not for tagged releases). Shipping a bundle whose installed POM references a Trino SNAPSHOT version is awkward for downstream consumers.
-
-Before cutting a release, split the property so main jars resolve to a Trino release while test-jars stay on snapshot:
-
-1. Add a sibling property to the root pom:
-   ```
-   <trino.connector.version>480</trino.connector.version>
-   <trino.connector.test.version>480-SNAPSHOT</trino.connector.test.version>
-   ```
-2. In `hudi-trino-plugin/pom.xml`, change each `<type>test-jar</type>` dependency to use `${dep.trino.test.version}` instead of inheriting from the main version.
-3. Verify with `mvn dependency:tree -Phudi-trino -pl hudi-trino-plugin` that compile deps resolve at `480` and test deps at `480-SNAPSHOT`.
-
-Alternative if the release pipeline must not touch SNAPSHOT artifacts at all: build with `-Dmaven.test.skip=true` so test-jar deps are never resolved. Trade-off is no unit test run during the release build; CI should still exercise tests separately under the snapshot path.
\ No newline at end of file
diff --git a/packaging/hudi-trino-bundle/pom.xml b/packaging/hudi-trino-bundle/pom.xml
deleted file mode 100644
index 8c22384b9551..000000000000
--- a/packaging/hudi-trino-bundle/pom.xml
+++ /dev/null
@@ -1,432 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  Licensed to the Apache Software Foundation (ASF) under one or more
-  contributor license agreements.  See the NOTICE file distributed with
-  this work for additional information regarding copyright ownership.
-  The ASF licenses this file to You under the Apache License, Version 2.0
-  (the "License"); you may not use this file except in compliance with
-  the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <parent>
-    <artifactId>hudi</artifactId>
-    <groupId>org.apache.hudi</groupId>
-    <version>1.3.0-SNAPSHOT</version>
-    <relativePath>../../pom.xml</relativePath>
-  </parent>
-  <modelVersion>4.0.0</modelVersion>
-  <artifactId>hudi-trino-bundle</artifactId>
-  <packaging>jar</packaging>
-
-  <properties>
-    <checkstyle.skip>true</checkstyle.skip>
-    <main.basedir>${project.parent.basedir}</main.basedir>
-    <skipTests>true</skipTests>
-    <dep.trino.version>${trino.connector.version}</dep.trino.version>
-  </properties>
-
-  <dependencyManagement>
-    <dependencies>
-      <!-- Import Trino's parent POM as a BOM so the SPI artifacts declared as
-           provided below resolve to versions matching the connector code. -->
-      <dependency>
-        <groupId>io.trino</groupId>
-        <artifactId>trino-root</artifactId>
-        <version>${dep.trino.version}</version>
-        <type>pom</type>
-        <scope>import</scope>
-      </dependency>
-    </dependencies>
-  </dependencyManagement>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.rat</groupId>
-        <artifactId>apache-rat-plugin</artifactId>
-      </plugin>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-shade-plugin</artifactId>
-        <version>${maven-shade-plugin.version}</version>
-        <executions>
-          <execution>
-            <phase>package</phase>
-            <goals>
-              <goal>shade</goal>
-            </goals>
-            <configuration>
-              <createSourcesJar>${shadeSources}</createSourcesJar>
-              <dependencyReducedPomLocation>${project.build.directory}/dependency-reduced-pom.xml
-              </dependencyReducedPomLocation>
-              <transformers>
-                <transformer implementation="org.apache.maven.plugins.shade.resource.ApacheLicenseResourceTransformer">
-                </transformer>
-                <transformer implementation="org.apache.maven.plugins.shade.resource.ApacheNoticeResourceTransformer">
-                  <addHeader>true</addHeader>
-                </transformer>
-                <transformer implementation="org.apache.maven.plugins.shade.resource.IncludeResourceTransformer">
-                  <resource>META-INF/LICENSE</resource>
-                  <file>target/classes/META-INF/LICENSE</file>
-                </transformer>
-                <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
-              </transformers>
-              <artifactSet>
-                <includes combine.children="append">
-                  <include>org.apache.hudi:hudi-trino-plugin</include>
-                  <include>org.apache.hudi:hudi-hadoop-common</include>
-                  <include>org.apache.hudi:hudi-common</include>
-                  <include>org.apache.hudi:hudi-client-common</include>
-                  <include>org.apache.hudi:hudi-java-client</include>
-                  <include>org.apache.hudi:hudi-hadoop-mr</include>
-
-                  <!-- Kryo -->
-                  <include>com.esotericsoftware:kryo-shaded</include>
-                  <include>com.esotericsoftware:minlog</include>
-                  <include>org.objenesis:objenesis</include>
-
-                  <include>org.apache.parquet:parquet-avro</include>
-                  <include>org.apache.avro:avro</include>
-                  <include>com.github.ben-manes.caffeine:caffeine</include>
-                  <include>org.codehaus.jackson:*</include>
-                  <include>com.yammer.metrics:metrics-core</include>
-                  <include>commons-io:commons-io</include>
-                  <include>com.google.protobuf:protobuf-java</include>
-                  <include>org.openjdk.jol:jol-core</include>
-                </includes>
-              </artifactSet>
-              <relocations combine.children="append">
-                <!-- Kryo -->
-                <relocation>
-                  <pattern>com.esotericsoftware.kryo.</pattern>
-                  <shadedPattern>org.apache.hudi.com.esotericsoftware.kryo.</shadedPattern>
-                </relocation>
-                <relocation>
-                  <pattern>com.esotericsoftware.reflectasm.</pattern>
-                  <shadedPattern>org.apache.hudi.com.esotericsoftware.reflectasm.</shadedPattern>
-                </relocation>
-                <relocation>
-                  <pattern>com.esotericsoftware.minlog.</pattern>
-                  <shadedPattern>org.apache.hudi.com.esotericsoftware.minlog.</shadedPattern>
-                </relocation>
-                <relocation>
-                  <pattern>org.objenesis.</pattern>
-                  <shadedPattern>org.apache.hudi.org.objenesis.</shadedPattern>
-                </relocation>
-
-                <relocation>
-                  <pattern>org.apache.parquet.avro.</pattern>
-                  <shadedPattern>org.apache.hudi.org.apache.parquet.avro.</shadedPattern>
-                </relocation>
-                <relocation>
-                  <pattern>org.apache.avro.</pattern>
-                  <shadedPattern>org.apache.hudi.org.apache.avro.</shadedPattern>
-                </relocation>
-                <relocation>
-                  <pattern>org.apache.commons.io.</pattern>
-                  <shadedPattern>org.apache.hudi.org.apache.commons.io.</shadedPattern>
-                </relocation>
-                <relocation>
-                  <pattern>com.yammer.metrics.</pattern>
-                  <shadedPattern>org.apache.hudi.com.yammer.metrics.</shadedPattern>
-                </relocation>
-                <relocation>
-                  <pattern>com.google.common.</pattern>
-                  <shadedPattern>${trino.bundle.bootstrap.shade.prefix}com.google.common.</shadedPattern>
-                </relocation>
-                <relocation>
-                  <pattern>org.apache.commons.lang.</pattern>
-                  <shadedPattern>${trino.bundle.bootstrap.shade.prefix}org.apache.commons.lang.</shadedPattern>
-                </relocation>
-                <relocation>
-                  <pattern>com.google.protobuf.</pattern>
-                  <shadedPattern>${trino.bundle.bootstrap.shade.prefix}com.google.protobuf.</shadedPattern>
-                </relocation>
-                <relocation>
-                  <pattern>org.openjdk.jol.</pattern>
-                  <shadedPattern>org.apache.hudi.org.openjdk.jol.</shadedPattern>
-                </relocation>
-              </relocations>
-              <createDependencyReducedPom>false</createDependencyReducedPom>
-              <filters>
-                <filter>
-                  <artifact>*:*</artifact>
-                  <excludes>
-                    <exclude>META-INF/*.SF</exclude>
-                    <exclude>META-INF/*.DSA</exclude>
-                    <exclude>META-INF/*.RSA</exclude>
-                    <exclude>META-INF/services/javax.*</exclude>
-                    <exclude>**/*.proto</exclude>
-                  </excludes>
-                </filter>
-              </filters>
-              <finalName>${project.artifactId}-${project.version}</finalName>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-    <resources>
-      <resource>
-        <directory>src/main/resources</directory>
-      </resource>
-    </resources>
-  </build>
-
-  <dependencies>
-    <!-- Hoodie -->
-    <dependency>
-      <!-- Plugin classes are shaded into this bundle. Its compile-scope deps on Trino,
-           Airlift, Jackson, Guice, OpenTelemetry are SPI-provided at Trino runtime and
-           must NOT leak into the bundle's transitive closure (trino-maven-plugin's
-           check-spi-dependencies enforces this on the consumer side). -->
-      <groupId>org.apache.hudi</groupId>
-      <artifactId>hudi-trino-plugin</artifactId>
-      <version>${project.version}</version>
-      <exclusions>
-        <exclusion>
-          <groupId>com.fasterxml.jackson.core</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.fasterxml.jackson.module</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.fasterxml.jackson.datatype</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>io.airlift</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>io.trino</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.google.inject</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>io.opentelemetry</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>org.openjdk.jol</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-        <!-- The connector does not use rocksdb (Hudi's local state stores), arrow, or lance.
-             These leak via hudi-common's compile deps and bloat the Trino server tar. -->
-        <exclusion>
-          <groupId>org.rocksdb</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>org.apache.arrow</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>org.lance</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <!-- Use the plain hudi-hadoop-mr artifact (already listed in the shade artifactSet).
-           hudi-hadoop-mr-bundle pulled lance-core, arrow-dataset, and rocksdbjni transitively
-           (~280MB), which the connector does not use and which blew the trino-server tar size cap. -->
-      <groupId>org.apache.hudi</groupId>
-      <artifactId>hudi-hadoop-mr</artifactId>
-      <version>${project.version}</version>
-      <exclusions>
-        <exclusion>
-          <groupId>com.fasterxml.jackson.core</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.fasterxml.jackson.module</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.fasterxml.jackson.datatype</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>org.rocksdb</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>org.apache.arrow</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>org.lance</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.hudi</groupId>
-      <artifactId>hudi-client-common</artifactId>
-      <version>${project.version}</version>
-      <exclusions>
-        <exclusion>
-          <artifactId>guava</artifactId>
-          <groupId>com.google.guava</groupId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.fasterxml.jackson.core</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.fasterxml.jackson.module</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.fasterxml.jackson.datatype</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-        <!-- hudi-timeline-service pulls Jetty + javax.servlet-api, banned by Trino's enforcer.
-             The Trino connector does not use the timeline service. -->
-        <exclusion>
-          <groupId>org.apache.hudi</groupId>
-          <artifactId>hudi-timeline-service</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.hudi</groupId>
-      <artifactId>hudi-java-client</artifactId>
-      <version>${project.version}</version>
-      <exclusions>
-        <exclusion>
-          <groupId>com.fasterxml.jackson.core</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.fasterxml.jackson.module</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.fasterxml.jackson.datatype</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>org.rocksdb</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>org.apache.arrow</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>org.lance</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-
-    <!-- Kryo -->
-    <dependency>
-      <groupId>com.esotericsoftware</groupId>
-      <artifactId>kryo-shaded</artifactId>
-      <version>${kryo.shaded.version}</version>
-      <scope>compile</scope>
-    </dependency>
-
-    <!-- Parquet -->
-    <dependency>
-      <groupId>org.apache.parquet</groupId>
-      <artifactId>parquet-avro</artifactId>
-      <version>${trino.parquet.version}</version>
-      <scope>compile</scope>
-    </dependency>
-
-    <!-- Avro -->
-    <dependency>
-      <groupId>org.apache.avro</groupId>
-      <artifactId>avro</artifactId>
-      <version>${avro.version}</version>
-      <scope>compile</scope>
-      <exclusions>
-        <!-- Jackson is SPI-provided by Trino at runtime. Avro's transitive jackson-core/databind
-             must not leak into consumers (check-spi-dependencies). The shaded avro classes within
-             this bundle reference unrelocated com.fasterxml.jackson.* which the Trino runtime
-             supplies. -->
-        <exclusion>
-          <groupId>com.fasterxml.jackson.core</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-
-    <!--protobuf needs to be shaded because HBase 1.2.3 + native HFile reader needs it at runtime,
-    but Trino runtime does not have this dependency-->
-    <dependency>
-      <groupId>com.google.protobuf</groupId>
-      <artifactId>protobuf-java</artifactId>
-      <version>${proto.version}</version>
-      <scope>${trino.bundle.bootstrap.scope}</scope>
-    </dependency>
-
-    <!-- Trino SPI artifacts. Declared here as provided to override the compile-scope
-         transitives pulled in via hudi-trino-plugin -> trino-hive/etc. Trino's server
-         supplies these at runtime; bundling them would cause split-classloader bugs
-         and breaks the trino-maven-plugin:check-spi-dependencies enforcer. -->
-    <dependency>
-      <groupId>com.fasterxml.jackson.core</groupId>
-      <artifactId>jackson-annotations</artifactId>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>io.airlift</groupId>
-      <artifactId>slice</artifactId>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>io.opentelemetry</groupId>
-      <artifactId>opentelemetry-api</artifactId>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>io.opentelemetry</groupId>
-      <artifactId>opentelemetry-api-incubator</artifactId>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>io.opentelemetry</groupId>
-      <artifactId>opentelemetry-context</artifactId>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>io.trino</groupId>
-      <artifactId>trino-spi</artifactId>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.openjdk.jol</groupId>
-      <artifactId>jol-core</artifactId>
-      <scope>provided</scope>
-    </dependency>
-
-  </dependencies>
-  <profiles>
-    <profile>
-      <id>trino-shade-unbundle-bootstrap</id>
-      <properties>
-        <trino.bundle.bootstrap.scope>provided</trino.bundle.bootstrap.scope>
-        <trino.bundle.bootstrap.shade.prefix/>
-      </properties>
-    </profile>
-  </profiles>
-</project>
diff --git a/packaging/hudi-trino-bundle/src/main/java/org/apache/hudi/trino/bundle/Main.java b/packaging/hudi-trino-bundle/src/main/java/org/apache/hudi/trino/bundle/Main.java
deleted file mode 100644
index eec1ecf88a8d..000000000000
--- a/packaging/hudi-trino-bundle/src/main/java/org/apache/hudi/trino/bundle/Main.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.hudi.trino.bundle;
-
-import org.apache.hudi.common.util.ReflectionUtils;
-
-/**
- * A simple main class to dump all classes loaded in current classpath
- * <p>
- * This is a workaround for generating sources and javadoc jars for packaging modules. The maven plugins for generating
- * javadoc and sources plugins do not generate corresponding jars if there are no source files.
- * <p>
- * This class does not have anything to do with Hudi but is there to keep mvn javadocs/source plugin happy.
- */
-public class Main {
-
-  public static void main(String[] args) {
-    ReflectionUtils.getTopLevelClassesInClasspath(Main.class).forEach(System.out::println);
-  }
-}
diff --git a/pom.xml b/pom.xml
index 66b57428ee69..b9448e1a940a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2276,12 +2276,12 @@
       </modules>
     </profile>
     <profile>
-      <!-- RFC-105: builds the Trino connector and its publishable shaded bundle.
-           Excluded from default builds because it requires JDK 25 and the Trino SPI. -->
+      <!-- RFC-105: builds the Trino connector (org.apache.hudi:hudi-trino), a regular non-shaded
+           jar relying on Trino's URLClassLoader plugin isolation. Excluded from default builds
+           because it requires JDK 25 and the Trino SPI. -->
       <id>hudi-trino</id>
       <modules>
         <module>hudi-trino-plugin</module>
-        <module>packaging/hudi-trino-bundle</module>
       </modules>
     </profile>
     <profile>


(hudi) 20/36: fix(trino): port connector tests off removed Trino 481 APIs

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit 2d5088f3d09ec4b41a05386f9fd1e5f3ef2b7c11
Author: voon <vo...@gmail.com>
AuthorDate: Tue May 26 21:56:16 2026 +0800

    fix(trino): port connector tests off removed Trino 481 APIs
    
    Two SPI removals we missed on the test side:
    
    - io.trino.plugin.hive.HiveTestUtils.HDFS_ENVIRONMENT and the
      io.trino.hdfs HdfsEnvironment / HdfsContext pair were dropped. The only
      consumer was TpchHudiTablesInitializer, which used HdfsEnvironment.
      getConfiguration(context, path) to mint a Hadoop Configuration for table
      init -- a plain new Configuration() is sufficient for the test's local
      filesystem layout.
    
    - io.trino.filesystem.cache.DefaultCachingHostAddressProvider was deleted
      alongside the CachingHostAddressProvider interface we already removed
      from production sources. TestHudiPartitionInfoLoader and
      TestHudiSplitFactory still passed it to the 3-arg HudiSplitFactory
      constructor / 6-arg createHudiSplits factory; drop the parameter to
      match.
---
 .../plugin/hudi/partition/TestHudiPartitionInfoLoader.java    |  3 +--
 .../java/io/trino/plugin/hudi/split/TestHudiSplitFactory.java |  4 +---
 .../trino/plugin/hudi/testing/TpchHudiTablesInitializer.java  | 11 +++--------
 3 files changed, 5 insertions(+), 13 deletions(-)

diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/partition/TestHudiPartitionInfoLoader.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/partition/TestHudiPartitionInfoLoader.java
index 78f565dcaa2d..765777cf855d 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/partition/TestHudiPartitionInfoLoader.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/partition/TestHudiPartitionInfoLoader.java
@@ -16,7 +16,6 @@ package io.trino.plugin.hudi.partition;
 import com.google.common.collect.ImmutableList;
 import io.airlift.units.DataSize;
 import io.trino.filesystem.Location;
-import io.trino.filesystem.cache.DefaultCachingHostAddressProvider;
 import io.trino.metastore.Partition;
 import io.trino.metastore.StorageFormat;
 import io.trino.plugin.hive.HiveColumnHandle;
@@ -167,7 +166,7 @@ public class TestHudiPartitionInfoLoader
                 "",
                 "101");
         HudiSplitWeightProvider weightProvider = new SizeBasedSplitWeightProvider(0.05, DataSize.of(128, MEGABYTE));
-        return new HudiSplitFactory(tableHandle, weightProvider, DataSize.of(128, MEGABYTE), new DefaultCachingHostAddressProvider());
+        return new HudiSplitFactory(tableHandle, weightProvider, DataSize.of(128, MEGABYTE));
     }
 
     private static HiveHudiPartitionInfo createTestPartition(String partitionPath)
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/split/TestHudiSplitFactory.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/split/TestHudiSplitFactory.java
index 266a5397af41..01a4208e9758 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/split/TestHudiSplitFactory.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/split/TestHudiSplitFactory.java
@@ -15,7 +15,6 @@ package io.trino.plugin.hudi.split;
 
 import com.google.common.collect.ImmutableList;
 import io.airlift.units.DataSize;
-import io.trino.filesystem.cache.DefaultCachingHostAddressProvider;
 import io.trino.plugin.hive.HivePartitionKey;
 import io.trino.plugin.hudi.HudiSplit;
 import io.trino.plugin.hudi.HudiTableHandle;
@@ -152,8 +151,7 @@ public class TestHudiSplitFactory
         FileSlice fileSlice = createFileSlice(baseFileSize, logFileSize);
 
         List<HudiSplit> splits = HudiSplitFactory.createHudiSplits(
-                tableHandle, PARTITION_KEYS, fileSlice, COMMIT_TIME, weightProvider, targetSplitSize,
-            new DefaultCachingHostAddressProvider());
+                tableHandle, PARTITION_KEYS, fileSlice, COMMIT_TIME, weightProvider, targetSplitSize);
 
         assertThat(splits).hasSize(expectedSplitInfo.size());
 
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/testing/TpchHudiTablesInitializer.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/testing/TpchHudiTablesInitializer.java
index 640980c41936..47902849e0d9 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/testing/TpchHudiTablesInitializer.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/testing/TpchHudiTablesInitializer.java
@@ -19,8 +19,6 @@ import io.airlift.log.Logger;
 import io.trino.filesystem.Location;
 import io.trino.filesystem.TrinoFileSystem;
 import io.trino.filesystem.TrinoFileSystemFactory;
-import io.trino.hdfs.HdfsContext;
-import io.trino.hdfs.HdfsEnvironment;
 import io.trino.metastore.Column;
 import io.trino.metastore.HiveMetastore;
 import io.trino.metastore.HiveMetastoreFactory;
@@ -88,9 +86,7 @@ import static io.trino.metastore.HiveType.HIVE_DOUBLE;
 import static io.trino.metastore.HiveType.HIVE_INT;
 import static io.trino.metastore.HiveType.HIVE_LONG;
 import static io.trino.metastore.HiveType.HIVE_STRING;
-import static io.trino.plugin.hive.HiveTestUtils.HDFS_ENVIRONMENT;
 import static io.trino.plugin.hive.TableType.EXTERNAL_TABLE;
-import static io.trino.testing.TestingConnectorSession.SESSION;
 import static java.lang.String.format;
 import static java.nio.file.Files.createTempDirectory;
 import static java.util.Collections.unmodifiableList;
@@ -110,7 +106,6 @@ public class TpchHudiTablesInitializer
             new Column("_hoodie_record_key", HIVE_STRING, Optional.empty(), Map.of()),
             new Column("_hoodie_partition_path", HIVE_STRING, Optional.empty(), Map.of()),
             new Column("_hoodie_file_name", HIVE_STRING, Optional.empty(), Map.of()));
-    private static final HdfsContext CONTEXT = new HdfsContext(SESSION);
 
     private final List<TpchTable<?>> tpchTables;
 
@@ -154,7 +149,7 @@ public class TpchHudiTablesInitializer
 
     public void load(TpchTable<?> tpchTables, QueryRunner queryRunner, java.nio.file.Path tableDirectory)
     {
-        try (HoodieJavaWriteClient<HoodieAvroPayload> writeClient = createWriteClient(tpchTables, HDFS_ENVIRONMENT, new Path(tableDirectory.toUri()))) {
+        try (HoodieJavaWriteClient<HoodieAvroPayload> writeClient = createWriteClient(tpchTables, new Path(tableDirectory.toUri()))) {
             RecordConverter recordConverter = createRecordConverter(tpchTables);
 
             @Language("SQL") String sql = generateScanSql(TPCH_TINY, tpchTables);
@@ -209,10 +204,10 @@ public class TpchHudiTablesInitializer
                 .build();
     }
 
-    private static HoodieJavaWriteClient<HoodieAvroPayload> createWriteClient(TpchTable<?> table, HdfsEnvironment hdfsEnvironment, Path tablePath)
+    private static HoodieJavaWriteClient<HoodieAvroPayload> createWriteClient(TpchTable<?> table, Path tablePath)
     {
         Schema schema = createAvroSchema(table);
-        Configuration conf = hdfsEnvironment.getConfiguration(CONTEXT, tablePath);
+        Configuration conf = new Configuration();
 
         try {
             HoodieTableMetaClient.newTableBuilder()


(hudi) 04/36: test: disable resolve column name casing by default

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit edeaad5733435e345b43a301f2ce1d99158cff50
Author: vamsikarnika <va...@gmail.com>
AuthorDate: Sat Aug 30 19:04:40 2025 +0530

    test: disable resolve column name casing by default
---
 .../src/main/java/io/trino/plugin/hudi/HudiConfig.java |  2 +-
 .../test/java/io/trino/plugin/hudi/SessionBuilder.java |  6 ++++++
 .../hudi/TestHudiAlluxioCacheFileOperations.java       | 18 ------------------
 .../test/java/io/trino/plugin/hudi/TestHudiConfig.java |  6 +++---
 .../plugin/hudi/TestHudiMemoryCacheFileOperations.java | 10 ----------
 .../plugin/hudi/TestHudiNoCacheFileOperations.java     | 10 ----------
 .../java/io/trino/plugin/hudi/TestHudiSmokeTest.java   |  3 +++
 7 files changed, 13 insertions(+), 42 deletions(-)

diff --git a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiConfig.java b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiConfig.java
index 2355744b6976..16e4126fbb81 100644
--- a/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiConfig.java
+++ b/hudi-trino-plugin/src/main/java/io/trino/plugin/hudi/HudiConfig.java
@@ -55,7 +55,7 @@ public class HudiConfig
     private boolean queryPartitionFilterRequired;
     private boolean ignoreAbsentPartitions;
     private Duration dynamicFilteringWaitTimeout = new Duration(1, SECONDS);
-    private boolean resolveColumnNameCasingEnabled = true;
+    private boolean resolveColumnNameCasingEnabled;
 
     // Internal configuration for debugging and testing
     private boolean isRecordLevelIndexEnabled = true;
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/SessionBuilder.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/SessionBuilder.java
index aa26d2d35f8e..9cc8359e41f1 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/SessionBuilder.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/SessionBuilder.java
@@ -25,6 +25,7 @@ import static io.trino.plugin.hudi.HudiSessionProperties.PARTITION_STATS_INDEX_E
 import static io.trino.plugin.hudi.HudiSessionProperties.QUERY_PARTITION_FILTER_REQUIRED;
 import static io.trino.plugin.hudi.HudiSessionProperties.RECORD_INDEX_WAIT_TIMEOUT;
 import static io.trino.plugin.hudi.HudiSessionProperties.RECORD_LEVEL_INDEX_ENABLED;
+import static io.trino.plugin.hudi.HudiSessionProperties.RESOLVE_COLUMN_NAME_CASING_ENABLED;
 import static io.trino.plugin.hudi.HudiSessionProperties.SECONDARY_INDEX_ENABLED;
 import static io.trino.plugin.hudi.HudiSessionProperties.SECONDARY_INDEX_WAIT_TIMEOUT;
 import static io.trino.plugin.hudi.HudiSessionProperties.TABLE_STATISTICS_ENABLED;
@@ -140,4 +141,9 @@ public class SessionBuilder
     {
         return setCatalogProperty(RECORD_INDEX_WAIT_TIMEOUT, durationProp);
     }
+
+    public SessionBuilder withResolveColumnNameCasingEnabled(boolean enabled)
+    {
+        return setCatalogProperty(RESOLVE_COLUMN_NAME_CASING_ENABLED, String.valueOf(enabled));
+    }
 }
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiAlluxioCacheFileOperations.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiAlluxioCacheFileOperations.java
index 4395a9c1ddff..8ad6b416220c 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiAlluxioCacheFileOperations.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiAlluxioCacheFileOperations.java
@@ -38,11 +38,9 @@ import static io.trino.filesystem.tracing.CacheFileSystemTraceUtils.getCacheOper
 import static io.trino.plugin.hudi.testing.ResourceHudiTablesInitializer.TestingTable.HUDI_MULTI_FG_PT_V8_MOR;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.DATA;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.INDEX_DEFINITION;
-import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.LOG;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.METADATA_TABLE;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.METADATA_TABLE_PROPERTIES;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.TABLE_PROPERTIES;
-import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.TIMELINE;
 import static io.trino.testing.MultisetAssertions.assertMultisetsEqual;
 import static java.util.stream.Collectors.toCollection;
 
@@ -85,12 +83,8 @@ public class TestHudiAlluxioCacheFileOperations
                 ImmutableMultiset.<FileOperation>builder()
                         .addCopies(new FileOperation("Alluxio.readCached", DATA), 2)
                         .addCopies(new FileOperation("Alluxio.readCached", METADATA_TABLE), 27)
-                        .addCopies(new FileOperation("Alluxio.readCached", TIMELINE), 4)
-                        .addCopies(new FileOperation("Alluxio.readCached", LOG), 15)
                         .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 4)
                         .addCopies(new FileOperation("InputFile.length", METADATA_TABLE), 10)
-                        .addCopies(new FileOperation("InputFile.length", TIMELINE), 2)
-                        .addCopies(new FileOperation("InputFile.length", LOG), 1)
                         .addCopies(new FileOperation("InputFile.newStream", INDEX_DEFINITION), 2)
                         .add(new FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES))
                         .addCopies(new FileOperation("InputFile.newStream", TABLE_PROPERTIES), 2)
@@ -101,12 +95,8 @@ public class TestHudiAlluxioCacheFileOperations
                 ImmutableMultiset.<FileOperation>builder()
                         .addCopies(new FileOperation("Alluxio.readCached", DATA), 2)
                         .addCopies(new FileOperation("Alluxio.readCached", METADATA_TABLE), 27)
-                        .addCopies(new FileOperation("Alluxio.readCached", TIMELINE), 4)
-                        .addCopies(new FileOperation("Alluxio.readCached", LOG), 15)
                         .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 4)
                         .addCopies(new FileOperation("InputFile.length", METADATA_TABLE), 10)
-                        .addCopies(new FileOperation("InputFile.length", TIMELINE), 2)
-                        .addCopies(new FileOperation("InputFile.length", LOG), 1)
                         .addCopies(new FileOperation("InputFile.newStream", INDEX_DEFINITION), 2)
                         .add(new FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES))
                         .addCopies(new FileOperation("InputFile.newStream", TABLE_PROPERTIES), 2)
@@ -126,12 +116,8 @@ public class TestHudiAlluxioCacheFileOperations
                 ImmutableMultiset.<FileOperation>builder()
                         .addCopies(new FileOperation("Alluxio.readCached", DATA), 6)
                         .addCopies(new FileOperation("Alluxio.readCached", METADATA_TABLE), 288)
-                        .addCopies(new FileOperation("Alluxio.readCached", TIMELINE), 8)
-                        .addCopies(new FileOperation("Alluxio.readCached", LOG), 30)
                         .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 39)
                         .addCopies(new FileOperation("InputFile.length", METADATA_TABLE), 93)
-                        .addCopies(new FileOperation("InputFile.length", TIMELINE), 4)
-                        .addCopies(new FileOperation("InputFile.length", LOG), 2)
                         .addCopies(new FileOperation("InputFile.newStream", INDEX_DEFINITION), 5)
                         .addCopies(new FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES), 3)
                         .addCopies(new FileOperation("InputFile.newStream", TABLE_PROPERTIES), 5)
@@ -141,12 +127,8 @@ public class TestHudiAlluxioCacheFileOperations
                 ImmutableMultiset.<FileOperation>builder()
                         .addCopies(new FileOperation("Alluxio.readCached", DATA), 6)
                         .addCopies(new FileOperation("Alluxio.readCached", METADATA_TABLE), 215)
-                        .addCopies(new FileOperation("Alluxio.readCached", TIMELINE), 8)
-                        .addCopies(new FileOperation("Alluxio.readCached", LOG), 30)
                         .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 29)
                         .addCopies(new FileOperation("InputFile.length", METADATA_TABLE), 69)
-                        .addCopies(new FileOperation("InputFile.length", TIMELINE), 4)
-                        .addCopies(new FileOperation("InputFile.length", LOG), 2)
                         .addCopies(new FileOperation("InputFile.newStream", INDEX_DEFINITION), 4)
                         .addCopies(new FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES), 2)
                         .addCopies(new FileOperation("InputFile.newStream", TABLE_PROPERTIES), 4)
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiConfig.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiConfig.java
index 545693f1ea07..99b6e4942c02 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiConfig.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiConfig.java
@@ -59,7 +59,7 @@ public class TestHudiConfig
                 .setSecondaryIndexWaitTimeout(Duration.valueOf("2s"))
                 .setMetadataPartitionListingEnabled(true)
                 .setMetadataCacheEnabled(true)
-                .setResolveColumnNameCasingEnabled(true));
+                .setResolveColumnNameCasingEnabled(false));
     }
 
     @Test
@@ -93,7 +93,7 @@ public class TestHudiConfig
                 .put("hudi.index.secondary-index.wait-timeout", "1s")
                 .put("hudi.metadata.cache.enabled", "false")
                 .put("hudi.metadata.partition-listing.enabled", "false")
-                .put("hudi.table.resolve-column-name-casing.enabled", "false")
+                .put("hudi.table.resolve-column-name-casing.enabled", "true")
                 .buildOrThrow();
 
         HudiConfig expected = new HudiConfig()
@@ -124,7 +124,7 @@ public class TestHudiConfig
                 .setSecondaryIndexWaitTimeout(Duration.valueOf("1s"))
                 .setMetadataPartitionListingEnabled(false)
                 .setMetadataCacheEnabled(false)
-                .setResolveColumnNameCasingEnabled(false);
+                .setResolveColumnNameCasingEnabled(true);
 
         assertFullMapping(properties, expected);
     }
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiMemoryCacheFileOperations.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiMemoryCacheFileOperations.java
index ed362391b017..b23f0c4f5441 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiMemoryCacheFileOperations.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiMemoryCacheFileOperations.java
@@ -35,11 +35,9 @@ import static io.trino.filesystem.tracing.CacheFileSystemTraceUtils.isTrinoSchem
 import static io.trino.plugin.hudi.testing.ResourceHudiTablesInitializer.TestingTable.HUDI_MULTI_FG_PT_V8_MOR;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.DATA;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.INDEX_DEFINITION;
-import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.LOG;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.METADATA_TABLE;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.METADATA_TABLE_PROPERTIES;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.TABLE_PROPERTIES;
-import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.TIMELINE;
 import static io.trino.testing.MultisetAssertions.assertMultisetsEqual;
 import static java.util.stream.Collectors.toCollection;
 
@@ -76,8 +74,6 @@ public class TestHudiMemoryCacheFileOperations
                         .addCopies(new FileOperation("FileSystemCache.cacheInput", DATA), 2)
                         .addCopies(new FileOperation("FileSystemCache.cacheLength", METADATA_TABLE), 4)
                         .addCopies(new FileOperation("FileSystemCache.cacheStream", METADATA_TABLE), 6)
-                        .addCopies(new FileOperation("FileSystemCache.cacheStream", TIMELINE), 2)
-                        .addCopies(new FileOperation("FileSystemCache.cacheStream", LOG), 1)
                         .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 4)
                         .addCopies(new FileOperation("InputFile.newStream", INDEX_DEFINITION), 2)
                         .add(new FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES))
@@ -90,8 +86,6 @@ public class TestHudiMemoryCacheFileOperations
                         .addCopies(new FileOperation("FileSystemCache.cacheInput", DATA), 2)
                         .addCopies(new FileOperation("FileSystemCache.cacheLength", METADATA_TABLE), 4)
                         .addCopies(new FileOperation("FileSystemCache.cacheStream", METADATA_TABLE), 6)
-                        .addCopies(new FileOperation("FileSystemCache.cacheStream", TIMELINE), 2)
-                        .addCopies(new FileOperation("FileSystemCache.cacheStream", LOG), 1)
                         .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 4)
                         .addCopies(new FileOperation("InputFile.newStream", INDEX_DEFINITION), 2)
                         .add(new FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES))
@@ -113,8 +107,6 @@ public class TestHudiMemoryCacheFileOperations
                         .addCopies(new FileOperation("FileSystemCache.cacheInput", DATA), 6)
                         .addCopies(new FileOperation("FileSystemCache.cacheLength", METADATA_TABLE), 39)
                         .addCopies(new FileOperation("FileSystemCache.cacheStream", METADATA_TABLE), 54)
-                        .addCopies(new FileOperation("FileSystemCache.cacheStream", TIMELINE), 4)
-                        .addCopies(new FileOperation("FileSystemCache.cacheStream", LOG), 2)
                         .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 39)
                         .addCopies(new FileOperation("InputFile.newStream", INDEX_DEFINITION), 5)
                         .addCopies(new FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES), 3)
@@ -126,8 +118,6 @@ public class TestHudiMemoryCacheFileOperations
                         .addCopies(new FileOperation("FileSystemCache.cacheInput", DATA), 6)
                         .addCopies(new FileOperation("FileSystemCache.cacheLength", METADATA_TABLE), 29)
                         .addCopies(new FileOperation("FileSystemCache.cacheStream", METADATA_TABLE), 40)
-                        .addCopies(new FileOperation("FileSystemCache.cacheStream", TIMELINE), 4)
-                        .addCopies(new FileOperation("FileSystemCache.cacheStream", LOG), 2)
                         .addCopies(new FileOperation("InputFile.lastModified", METADATA_TABLE), 29)
                         .addCopies(new FileOperation("InputFile.newStream", INDEX_DEFINITION), 4)
                         .addCopies(new FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES), 2)
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiNoCacheFileOperations.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiNoCacheFileOperations.java
index 9d6a6a8a5200..7271dde44f0d 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiNoCacheFileOperations.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiNoCacheFileOperations.java
@@ -35,11 +35,9 @@ import static io.trino.filesystem.tracing.CacheFileSystemTraceUtils.isTrinoSchem
 import static io.trino.plugin.hudi.testing.ResourceHudiTablesInitializer.TestingTable.HUDI_MULTI_FG_PT_V8_MOR;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.DATA;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.INDEX_DEFINITION;
-import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.LOG;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.METADATA_TABLE;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.METADATA_TABLE_PROPERTIES;
 import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.TABLE_PROPERTIES;
-import static io.trino.plugin.hudi.util.FileOperationUtils.FileType.TIMELINE;
 import static io.trino.testing.MultisetAssertions.assertMultisetsEqual;
 import static java.util.stream.Collectors.toCollection;
 
@@ -78,8 +76,6 @@ public class TestHudiNoCacheFileOperations
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.length", METADATA_TABLE), 4)
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", METADATA_TABLE), 6)
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", INDEX_DEFINITION), 2)
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", TIMELINE), 2)
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", LOG), 1)
                         .add(new FileOperationUtils.FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES))
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", TABLE_PROPERTIES), 2)
                         .build());
@@ -92,8 +88,6 @@ public class TestHudiNoCacheFileOperations
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.length", METADATA_TABLE), 4)
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", INDEX_DEFINITION), 2)
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", METADATA_TABLE), 6)
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", TIMELINE), 2)
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", LOG), 1)
                         .add(new FileOperationUtils.FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES))
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", TABLE_PROPERTIES), 2)
                         .build());
@@ -117,8 +111,6 @@ public class TestHudiNoCacheFileOperations
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", METADATA_TABLE), 54)
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES), 3)
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", TABLE_PROPERTIES), 5)
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", TIMELINE), 4)
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", LOG), 2)
                         .build());
 
         assertFileSystemAccesses(query,
@@ -130,8 +122,6 @@ public class TestHudiNoCacheFileOperations
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", METADATA_TABLE), 40)
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", METADATA_TABLE_PROPERTIES), 2)
                         .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", TABLE_PROPERTIES), 4)
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", TIMELINE), 4)
-                        .addCopies(new FileOperationUtils.FileOperation("InputFile.newStream", LOG), 2)
                         .build());
     }
 
diff --git a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiSmokeTest.java b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiSmokeTest.java
index f49933d3fb98..d1c26fbf5edd 100644
--- a/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiSmokeTest.java
+++ b/hudi-trino-plugin/src/test/java/io/trino/plugin/hudi/TestHudiSmokeTest.java
@@ -727,6 +727,7 @@ public class TestHudiSmokeTest
                 .withRecordLevelIndexEnabled(false)
                 .withSecondaryIndexEnabled(false)
                 .withPartitionStatsIndexEnabled(false)
+                .withResolveColumnNameCasingEnabled(true)
                 .build();
         MaterializedResult prunedRes = getQueryRunner().execute(session, "SELECT * FROM  " + table + " WHERE name='Alice'");
         MaterializedResult totalRes = getQueryRunner().execute(session, "SELECT * FROM " + table);
@@ -751,6 +752,7 @@ public class TestHudiSmokeTest
                 .withRecordIndexTimeout("10s")
                 .withSecondaryIndexEnabled(false)
                 .withPartitionStatsIndexEnabled(false)
+                .withResolveColumnNameCasingEnabled(true)
                 .build();
         MaterializedResult totalRes = getQueryRunner().execute(session, "SELECT * FROM " + HUDI_COW_TABLE_WITH_FIELD_NAMES_IN_CAPS);
         MaterializedResult prunedRes = getQueryRunner().execute(session, "SELECT * FROM  " + HUDI_COW_TABLE_WITH_FIELD_NAMES_IN_CAPS + " WHERE id='1'");
@@ -775,6 +777,7 @@ public class TestHudiSmokeTest
                 .withRecordIndexTimeout("10s")
                 .withSecondaryIndexEnabled(false)
                 .withPartitionStatsIndexEnabled(false)
+                .withResolveColumnNameCasingEnabled(true)
                 .build();
         MaterializedResult totalRes = getQueryRunner().execute(session, "SELECT * FROM " + HUDI_COW_TABLE_WITH_MULTI_KEYS_AND_FIELD_NAMES_IN_CAPS);
         MaterializedResult prunedRes = getQueryRunner().execute(session, "SELECT * FROM  " + HUDI_COW_TABLE_WITH_MULTI_KEYS_AND_FIELD_NAMES_IN_CAPS + " WHERE id='1' and age=30");


(hudi) 19/36: ci(trino): consolidate build + test in hudi_trino_ci, drop stale bot.yml job

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit 8a84c553f3de8e135084543de1491a8a01fa23e8
Author: voon <vo...@gmail.com>
AuthorDate: Tue May 26 17:12:38 2026 +0800

    ci(trino): consolidate build + test in hudi_trino_ci, drop stale bot.yml job
    
    Folds the connector test step into hudi_trino_ci.yml so every PR that
    touches hudi-trino-plugin both builds and runs the test suite.
    
    To run tests we need Trino's test-jars (trino-spi, trino-filesystem,
    trino-hive at the tests classifier), which are not published to Maven
    Central. The workflow now checks out trinodb/trino at tag 481 and runs
    `mvn install -pl :trino-spi,:trino-filesystem,:trino-hive,:trino-main -am
    -DskipTests` to populate them in the local m2. -Dair.check.skip-all=true
    disables Trino's airbase enforcer rules on the truncated reactor.
    
    The JDK 17 stage now also installs hudi-client-common and hudi-java-client
    because the gated hudi-trino-tests profile pulls them in for the test
    classpath.
    
    Removes the test-hudi-trino-plugin block in bot.yml (JDK 23, no Trino
    profile, obsolete api.version flag); the new workflow supersedes it.
---
 .github/workflows/bot.yml           | 27 ---------------------------
 .github/workflows/hudi_trino_ci.yml | 23 ++++++++++++++++++-----
 2 files changed, 18 insertions(+), 32 deletions(-)

diff --git a/.github/workflows/bot.yml b/.github/workflows/bot.yml
index 0f4950993773..9d4d2434424e 100644
--- a/.github/workflows/bot.yml
+++ b/.github/workflows/bot.yml
@@ -1458,30 +1458,3 @@ jobs:
         run:
           mvn test -Punit-tests -Djava17 -Djava.version=17 -D"$SCALA_PROFILE" -D"$FLINK_PROFILE" -pl hudi-examples/hudi-examples-flink $MVN_ARGS
 
-  test-hudi-trino-plugin:
-    runs-on: ubuntu-latest
-    needs: changes
-    steps:
-      - name: Checkout repository
-        if: needs.changes.outputs.relevant == 'true'
-        uses: actions/checkout@v5
-      - name: Set up JDK 23
-        if: needs.changes.outputs.relevant == 'true'
-        uses: actions/setup-java@v5
-        with:
-          # Note: We are not caching here again, as we want to use the .m2 repository populated by
-          # the previous step
-          java-version: '23'
-          distribution: 'temurin'
-          architecture: x64
-          cache: maven
-      - name: Build hudi-trino-plugin with JDK 23
-        if: needs.changes.outputs.relevant == 'true'
-        working-directory: ./hudi-trino-plugin
-        run:
-          mvn clean install -DskipTests
-      - name: Test hudi-trino-plugin with JDK 23
-        if: needs.changes.outputs.relevant == 'true'
-        working-directory: ./hudi-trino-plugin
-        run:
-          mvn test -Dapi.version=1.44
diff --git a/.github/workflows/hudi_trino_ci.yml b/.github/workflows/hudi_trino_ci.yml
index 7153b25c0734..542290978a28 100644
--- a/.github/workflows/hudi_trino_ci.yml
+++ b/.github/workflows/hudi_trino_ci.yml
@@ -26,7 +26,7 @@ env:
 
 jobs:
   build-and-test:
-    name: Build connector
+    name: Build and test connector
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v5
@@ -40,15 +40,28 @@ jobs:
           distribution: 'temurin'
           cache: maven
       - name: Install upstream Hudi modules (JDK 17)
-        run: mvn $MVN_ARGS install -pl :hudi-common,:hudi-hive-sync,:hudi-io,:hudi-sync-common -am -Dmaven.test.skip=true -Drat.skip -Dcheckstyle.skip
+        # hudi-client-common and hudi-java-client are pulled in here for the test stage;
+        # they live behind the hudi-trino-tests profile but the test step needs them.
+        run: mvn $MVN_ARGS install -pl :hudi-common,:hudi-hive-sync,:hudi-io,:hudi-sync-common,:hudi-client-common,:hudi-java-client -am -Dmaven.test.skip=true -Drat.skip -Dcheckstyle.skip
       - name: Set up JDK 25
         uses: actions/setup-java@v5
         with:
           java-version: '25'
           distribution: 'temurin'
           cache: maven
-      # Tests live behind the hudi-trino-tests profile (Trino does not publish the
-      # test-jars we need). -Dmaven.test.skip=true skips test compilation so the build
-      # resolves cleanly against Maven Central.
+      # Trino does not publish trino-spi / trino-filesystem / trino-hive test-jars to
+      # Maven Central. Check out the matching release tag and install just the modules
+      # whose test classifiers we need into the local m2.
+      - name: Checkout trinodb/trino at 481
+        uses: actions/checkout@v5
+        with:
+          repository: trinodb/trino
+          ref: '481'
+          path: trino-src
+      - name: Install Trino test-jars (JDK 25)
+        working-directory: trino-src
+        run: mvn $MVN_ARGS install -pl :trino-spi,:trino-filesystem,:trino-hive,:trino-main -am -DskipTests -Dair.check.skip-all=true
       - name: Build connector (JDK 25)
         run: mvn $MVN_ARGS -Phudi-trino -pl hudi-trino-plugin install -Dmaven.test.skip=true
+      - name: Test connector (JDK 25)
+        run: mvn $MVN_ARGS -Phudi-trino,hudi-trino-tests -pl hudi-trino-plugin test


(hudi) 27/36: fix(trino): pin Jersey to 4.0.2 to match Trino's jakarta stack

Posted by vh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

voonhous pushed a commit to tag rfc-105-pre-cleanup
in repository https://gitbox.apache.org/repos/asf/hudi.git

commit c89c199ccf2ef1c8d20df1e15c37d545520fe301
Author: voon <vo...@gmail.com>
AuthorDate: Wed May 27 15:46:27 2026 +0800

    fix(trino): pin Jersey to 4.0.2 to match Trino's jakarta stack
    
    Hudi parent pins jersey-server at 2.17 (legacy javax, with the repackaged
    guava Predicate); Trino runs on Jersey 4.x (jakarta). The mixed-major-
    version classpath crashes when TestingTrinoServer wires up jaxrs with
    
      NoSuchFieldError: Class ComponentBag does not have member field
      jersey.repackaged.com.google.common.base.Predicate INCLUDE_ALL
    
    Override jersey-server, jersey-client and jersey-media-jaxb in plugin
    dependencyManagement so the whole Jersey set lands at 4.0.2.
---
 hudi-trino-plugin/pom.xml | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/hudi-trino-plugin/pom.xml b/hudi-trino-plugin/pom.xml
index 76864f3e80ea..46c594359aba 100644
--- a/hudi-trino-plugin/pom.xml
+++ b/hudi-trino-plugin/pom.xml
@@ -85,6 +85,24 @@
                 <artifactId>jetty-server</artifactId>
                 <version>12.1.9</version>
             </dependency>
+            <!-- Hudi parent pins jersey-server at 2.17 (legacy javax). Trino runs on Jersey 4.x
+                 (jakarta). The mixed-version classpath crashes with NoSuchFieldError on
+                 ComponentBag.INCLUDE_ALL during ResourceConfig init. -->
+            <dependency>
+                <groupId>org.glassfish.jersey.core</groupId>
+                <artifactId>jersey-server</artifactId>
+                <version>4.0.2</version>
+            </dependency>
+            <dependency>
+                <groupId>org.glassfish.jersey.core</groupId>
+                <artifactId>jersey-client</artifactId>
+                <version>4.0.2</version>
+            </dependency>
+            <dependency>
+                <groupId>org.glassfish.jersey.media</groupId>
+                <artifactId>jersey-media-jaxb</artifactId>
+                <version>4.0.2</version>
+            </dependency>
             <!-- Airbase manages junit-platform at 6.0.3 (paired with jupiter 6.x). Hudi manages
                  jupiter at 5.14.1 (paired with platform 1.14.1). Pin platform here to keep the
                  pair consistent; without this, surefire fails with OutputDirectoryCreator not found. -->