From bbd5989b7dd61a9453be5d0c411a9ade4cc0af0d Mon Sep 17 00:00:00 2001 From: alberic Date: Sun, 19 Feb 2023 10:39:03 +0800 Subject: [PATCH 1/2] Add a metadata table showing commits in Hudi connector --- docs/src/main/sphinx/connector/hudi.rst | 49 ++++++++++ .../io/trino/plugin/hudi/HudiMetadata.java | 31 +++++++ .../io/trino/plugin/hudi/HudiSplitSource.java | 3 +- .../io/trino/plugin/hudi/HudiTableName.java | 84 +++++++++++++++++ .../java/io/trino/plugin/hudi/TableType.java | 20 ++++ .../io/trino/plugin/hudi/TimelineTable.java | 91 +++++++++++++++++++ .../plugin/hudi/TestHudiSystemTables.java | 48 ++++++++++ .../env/environment/EnvSinglenodeHudi.java | 5 +- .../singlenode-hudi/hive.properties | 4 + .../hudi/TestHudiSparkCompatibility.java | 32 +++++++ 10 files changed, 365 insertions(+), 2 deletions(-) create mode 100644 plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/HudiTableName.java create mode 100644 plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/TableType.java create mode 100644 plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/TimelineTable.java create mode 100644 plugin/trino-hudi/src/test/java/io/trino/plugin/hudi/TestHudiSystemTables.java create mode 100644 testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-hudi/hive.properties diff --git a/docs/src/main/sphinx/connector/hudi.rst b/docs/src/main/sphinx/connector/hudi.rst index 4acfc00c6560..0d8f8aad499e 100644 --- a/docs/src/main/sphinx/connector/hudi.rst +++ b/docs/src/main/sphinx/connector/hudi.rst @@ -157,3 +157,52 @@ Here are some sample queries: ------------+--------+ 2018-08-31 | 99 | (1 rows) + +.. _hudi-metadata-tables: + +Metadata tables +--------------- + +The connector exposes a metadata table for each Hudi table. +The metadata table contains information about the internal structure +of the Hudi table. You can query each metadata table by appending the +metadata table name to the table name:: + + SELECT * FROM "test_table$timeline" + +``$timeline`` table +^^^^^^^^^^^^^^^^^^^^ + +The ``$timeline`` table provides a detailed view of meta-data instants +in the Hudi table. Instants are specific points in time. + +You can retrieve the information about the timeline of the Hudi table +``test_table`` by using the following query:: + + SELECT * FROM "test_table$timeline" + +.. code-block:: text + + timestamp | action | state + --------------------+---------+----------- + 8667764846443717831 | commit | COMPLETED + 7860805980949777961 | commit | COMPLETED + +The output of the query has the following columns: + +.. list-table:: Timeline columns + :widths: 20, 30, 50 + :header-rows: 1 + + * - Name + - Type + - Description + * - ``timestamp`` + - ``varchar`` + - Instant time is typically a timestamp when the actions performed + * - ``action`` + - ``varchar`` + - `Type of action `_ performed on the table + * - ``state`` + - ``varchar`` + - Current state of the instant diff --git a/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/HudiMetadata.java b/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/HudiMetadata.java index bd2d83fa762b..fec75c1dff0c 100644 --- a/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/HudiMetadata.java +++ b/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/HudiMetadata.java @@ -18,6 +18,7 @@ import io.airlift.log.Logger; import io.trino.hdfs.HdfsContext; import io.trino.hdfs.HdfsEnvironment; +import io.trino.plugin.base.classloader.ClassLoaderSafeSystemTable; import io.trino.plugin.hive.HiveColumnHandle; import io.trino.plugin.hive.metastore.Column; import io.trino.plugin.hive.metastore.HiveMetastore; @@ -33,6 +34,7 @@ import io.trino.spi.connector.ConstraintApplicationResult; import io.trino.spi.connector.SchemaTableName; import io.trino.spi.connector.SchemaTablePrefix; +import io.trino.spi.connector.SystemTable; import io.trino.spi.connector.TableColumnsMetadata; import io.trino.spi.connector.TableNotFoundException; import io.trino.spi.predicate.TupleDomain; @@ -116,6 +118,35 @@ public HudiTableHandle getTableHandle(ConnectorSession session, SchemaTableName TupleDomain.all()); } + @Override + public Optional getSystemTable(ConnectorSession session, SchemaTableName tableName) + { + return getRawSystemTable(session, tableName) + .map(systemTable -> new ClassLoaderSafeSystemTable(systemTable, getClass().getClassLoader())); + } + + private Optional getRawSystemTable(ConnectorSession session, SchemaTableName tableName) + { + HudiTableName name = HudiTableName.from(tableName.getTableName()); + if (name.getTableType() == TableType.DATA) { + return Optional.empty(); + } + + Optional tableOptional = metastore.getTable(tableName.getSchemaName(), name.getTableName()); + if (tableOptional.isEmpty()) { + return Optional.empty(); + } + switch (name.getTableType()) { + case DATA: + break; + case TIMELINE: + SchemaTableName systemTableName = new SchemaTableName(tableName.getSchemaName(), name.getTableNameWithType()); + Configuration configuration = hdfsEnvironment.getConfiguration(new HdfsContext(session), new Path(tableOptional.get().getStorage().getLocation())); + return Optional.of(new TimelineTable(configuration, systemTableName, tableOptional.get())); + } + return Optional.empty(); + } + @Override public ConnectorTableMetadata getTableMetadata(ConnectorSession session, ConnectorTableHandle table) { diff --git a/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/HudiSplitSource.java b/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/HudiSplitSource.java index 2726bbb741d0..b302754be045 100644 --- a/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/HudiSplitSource.java +++ b/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/HudiSplitSource.java @@ -128,9 +128,10 @@ public boolean isFinished() return queue.isFinished(); } - private static HoodieTableMetaClient buildTableMetaClient(Configuration configuration, String basePath) + public static HoodieTableMetaClient buildTableMetaClient(Configuration configuration, String basePath) { HoodieTableMetaClient client = HoodieTableMetaClient.builder().setConf(configuration).setBasePath(basePath).build(); + // Do not load the bootstrap index, will not read bootstrap base data or a mapping index defined client.getTableConfig().setValue("hoodie.bootstrap.index.enable", "false"); return client; } diff --git a/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/HudiTableName.java b/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/HudiTableName.java new file mode 100644 index 000000000000..e996b12c3a4a --- /dev/null +++ b/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/HudiTableName.java @@ -0,0 +1,84 @@ +/* + * 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; + +import io.trino.spi.TrinoException; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static io.trino.spi.StandardErrorCode.NOT_SUPPORTED; +import static java.lang.String.format; +import static java.util.Locale.ENGLISH; +import static java.util.Objects.requireNonNull; + +public class HudiTableName +{ + private static final Pattern TABLE_PATTERN = Pattern.compile("" + + "(?
[^$@]+)" + + "(?:\\$(?[^@]+))?"); + + private final String tableName; + private final TableType tableType; + + public HudiTableName(String tableName, TableType tableType) + { + this.tableName = requireNonNull(tableName, "tableName is null"); + this.tableType = requireNonNull(tableType, "tableType is null"); + } + + public String getTableName() + { + return tableName; + } + + public TableType getTableType() + { + return tableType; + } + + public String getTableNameWithType() + { + return tableName + "$" + tableType.name().toLowerCase(ENGLISH); + } + + @Override + public String toString() + { + return getTableNameWithType(); + } + + public static HudiTableName from(String name) + { + Matcher match = TABLE_PATTERN.matcher(name); + if (!match.matches()) { + throw new TrinoException(NOT_SUPPORTED, "Invalid Hudi table name: " + name); + } + + String table = match.group("table"); + String typeString = match.group("type"); + + TableType type = TableType.DATA; + if (typeString != null) { + try { + type = TableType.valueOf(typeString.toUpperCase(ENGLISH)); + } + catch (IllegalArgumentException e) { + throw new TrinoException(NOT_SUPPORTED, format("Invalid Hudi table name (unknown type '%s'): %s", typeString, name)); + } + } + + return new HudiTableName(table, type); + } +} diff --git a/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/TableType.java b/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/TableType.java new file mode 100644 index 000000000000..676d8b738c41 --- /dev/null +++ b/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/TableType.java @@ -0,0 +1,20 @@ +/* + * 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; + +public enum TableType +{ + DATA, + TIMELINE; +} diff --git a/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/TimelineTable.java b/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/TimelineTable.java new file mode 100644 index 000000000000..3d0e13400942 --- /dev/null +++ b/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/TimelineTable.java @@ -0,0 +1,91 @@ +/* + * 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; + +import com.google.common.collect.ImmutableList; +import io.trino.plugin.hive.metastore.Table; +import io.trino.spi.connector.ColumnMetadata; +import io.trino.spi.connector.ConnectorSession; +import io.trino.spi.connector.ConnectorTableMetadata; +import io.trino.spi.connector.ConnectorTransactionHandle; +import io.trino.spi.connector.InMemoryRecordSet; +import io.trino.spi.connector.RecordCursor; +import io.trino.spi.connector.SchemaTableName; +import io.trino.spi.connector.SystemTable; +import io.trino.spi.predicate.TupleDomain; +import io.trino.spi.type.Type; +import org.apache.hadoop.conf.Configuration; +import org.apache.hudi.common.table.HoodieTableMetaClient; +import org.apache.hudi.common.table.timeline.HoodieInstant; + +import java.util.ArrayList; +import java.util.List; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.collect.ImmutableList.toImmutableList; +import static io.trino.plugin.hudi.HudiSplitSource.buildTableMetaClient; +import static io.trino.spi.type.VarcharType.VARCHAR; +import static java.util.Objects.requireNonNull; + +public class TimelineTable + implements SystemTable +{ + private final ConnectorTableMetadata tableMetadata; + private final List types; + private final Configuration configuration; + private final String location; + + public TimelineTable(Configuration configuration, SchemaTableName tableName, Table hudiTable) + { + this.tableMetadata = new ConnectorTableMetadata(requireNonNull(tableName, "tableName is null"), + ImmutableList.builder() + .add(new ColumnMetadata("timestamp", VARCHAR)) + .add(new ColumnMetadata("action", VARCHAR)) + .add(new ColumnMetadata("state", VARCHAR)) + .build()); + this.types = tableMetadata.getColumns().stream().map(ColumnMetadata::getType).collect(toImmutableList()); + this.configuration = requireNonNull(configuration, "configuration is null"); + this.location = requireNonNull(hudiTable.getStorage().getLocation(), "location is null"); + } + + @Override + public Distribution getDistribution() + { + return Distribution.SINGLE_COORDINATOR; + } + + @Override + public ConnectorTableMetadata getTableMetadata() + { + return tableMetadata; + } + + @Override + public RecordCursor cursor(ConnectorTransactionHandle transactionHandle, ConnectorSession session, TupleDomain constraint) + { + HoodieTableMetaClient metaClient = buildTableMetaClient(configuration, location); + Iterable> records = () -> metaClient.getCommitsTimeline().getInstants().map(this::getRecord).iterator(); + return new InMemoryRecordSet(types, records).cursor(); + } + + private List getRecord(HoodieInstant hudiInstant) + { + List columns = new ArrayList<>(); + columns.add(hudiInstant.getTimestamp()); + columns.add(hudiInstant.getAction()); + columns.add(hudiInstant.getState().toString()); + checkArgument(columns.size() == types.size(), "Expected %s types in row, but got %s values", types.size(), columns.size()); + return columns; + } +} diff --git a/plugin/trino-hudi/src/test/java/io/trino/plugin/hudi/TestHudiSystemTables.java b/plugin/trino-hudi/src/test/java/io/trino/plugin/hudi/TestHudiSystemTables.java new file mode 100644 index 000000000000..b74a5e330430 --- /dev/null +++ b/plugin/trino-hudi/src/test/java/io/trino/plugin/hudi/TestHudiSystemTables.java @@ -0,0 +1,48 @@ +/* + * 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; + +import com.google.common.collect.ImmutableMap; +import io.trino.plugin.hudi.testing.ResourceHudiTablesInitializer; +import io.trino.testing.AbstractTestQueryFramework; +import io.trino.testing.QueryRunner; +import org.testng.annotations.Test; + +import static io.trino.plugin.hudi.HudiQueryRunner.createHudiQueryRunner; + +public class TestHudiSystemTables + extends AbstractTestQueryFramework +{ + @Override + protected QueryRunner createQueryRunner() + throws Exception + { + return createHudiQueryRunner(ImmutableMap.of(), ImmutableMap.of(), new ResourceHudiTablesInitializer()); + } + + @Test + public void testTimelineTable() + { + assertQuery("SHOW COLUMNS FROM tests.\"hudi_cow_pt_tbl$timeline\"", + "VALUES ('timestamp', 'varchar', '', '')," + + "('action', 'varchar', '', '')," + + "('state', 'varchar', '', '')"); + + assertQuery("SELECT timestamp, action, state FROM tests.\"hudi_cow_pt_tbl$timeline\"", + "VALUES ('20220906063435640', 'commit', 'COMPLETED'), ('20220906063456550', 'commit', 'COMPLETED')"); + + assertQueryFails("SELECT timestamp, action, state FROM tests.\"non_existing$timeline\"", + ".*Table 'hudi.tests.non_existing\\$timeline' does not exist"); + } +} diff --git a/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/environment/EnvSinglenodeHudi.java b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/environment/EnvSinglenodeHudi.java index 8a8dd94c9b21..ad020c483caa 100644 --- a/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/environment/EnvSinglenodeHudi.java +++ b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/environment/EnvSinglenodeHudi.java @@ -83,7 +83,10 @@ public void extendEnvironment(Environment.Builder builder) { // Using hdp3.1 so we are using Hive metastore with version close to versions of hive-*.jars Spark uses builder.configureContainer(HADOOP, container -> container.setDockerImageName("ghcr.io/trinodb/testing/hdp3.1-hive:" + hadoopImagesVersion)); - + builder.addConnector( + "hive", + forHostPath(configDir.getPath("hive.properties")), + CONTAINER_TRINO_ETC + "/catalog/hive.properties"); builder.addConnector( "hudi", forHostPath(configDir.getPath("hudi.properties")), diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-hudi/hive.properties b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-hudi/hive.properties new file mode 100644 index 000000000000..de8a1b226642 --- /dev/null +++ b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-hudi/hive.properties @@ -0,0 +1,4 @@ +connector.name=hive +hive.metastore.uri=thrift://hadoop-master:9083 +hive.config.resources=/docker/presto-product-tests/conf/presto/etc/hive-default-fs-site.xml +hive.hudi-catalog-name=hudi diff --git a/testing/trino-product-tests/src/main/java/io/trino/tests/product/hudi/TestHudiSparkCompatibility.java b/testing/trino-product-tests/src/main/java/io/trino/tests/product/hudi/TestHudiSparkCompatibility.java index bf79fb1f9edc..5f0650ff9b51 100644 --- a/testing/trino-product-tests/src/main/java/io/trino/tests/product/hudi/TestHudiSparkCompatibility.java +++ b/testing/trino-product-tests/src/main/java/io/trino/tests/product/hudi/TestHudiSparkCompatibility.java @@ -23,6 +23,7 @@ import java.util.List; import static io.trino.tempto.assertions.QueryAssert.Row.row; +import static io.trino.tempto.assertions.QueryAssert.assertQueryFailure; import static io.trino.tempto.assertions.QueryAssert.assertThat; import static io.trino.testing.TestingNames.randomNameSuffix; import static io.trino.tests.product.TestGroups.HUDI; @@ -288,6 +289,37 @@ public void testCopyOnWriteTableSelectWithSessionProperties() } } + @Test(groups = {HUDI, PROFILE_SPECIFIC_TESTS}) + public void testTimelineTable() + { + String tableName = "test_hudi_timeline_system_table_" + randomNameSuffix(); + createNonPartitionedTable(tableName, COW_TABLE_TYPE); + try { + assertThat(onTrino().executeQuery(format("SELECT action, state FROM hudi.default.\"%s$timeline\"", tableName))) + .containsOnly(row("commit", "COMPLETED")); + } + finally { + onHudi().executeQuery("DROP TABLE " + tableName); + } + } + + @Test(groups = {HUDI, PROFILE_SPECIFIC_TESTS}) + public void testTimelineTableRedirect() + { + String tableName = "test_hudi_timeline_system_table_redirect_" + randomNameSuffix(); + String nonExistingTableName = tableName + "_non_existing"; + createNonPartitionedTable(tableName, COW_TABLE_TYPE); + try { + assertThat(onTrino().executeQuery(format("SELECT action, state FROM hive.default.\"%s$timeline\"", tableName))) + .containsOnly(row("commit", "COMPLETED")); + assertQueryFailure(() -> onTrino().executeQuery(format("SELECT * FROM hive.default.\"%s$timeline\"", nonExistingTableName))) + .hasMessageMatching(".*Table 'hive.default.test_hudi_timeline_system_table_redirect_.*_non_existing\\$timeline' does not exist"); + } + finally { + onHudi().executeQuery("DROP TABLE " + tableName); + } + } + private void createNonPartitionedTable(String tableName, String tableType) { onHudi().executeQuery(format( From a8dd2dcfb0ff1d3943ac36f4d00e649463fcfe22 Mon Sep 17 00:00:00 2001 From: alberic Date: Wed, 15 Mar 2023 14:35:51 +0800 Subject: [PATCH 2/2] Move buildTableMetaClient to HudiUtil class --- .../java/io/trino/plugin/hudi/HudiSplitSource.java | 9 +-------- .../src/main/java/io/trino/plugin/hudi/HudiUtil.java | 10 ++++++++++ .../main/java/io/trino/plugin/hudi/TimelineTable.java | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/HudiSplitSource.java b/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/HudiSplitSource.java index b302754be045..c2666a9287cd 100644 --- a/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/HudiSplitSource.java +++ b/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/HudiSplitSource.java @@ -47,6 +47,7 @@ import static io.trino.plugin.hudi.HudiSessionProperties.getStandardSplitWeightSize; import static io.trino.plugin.hudi.HudiSessionProperties.isHudiMetadataEnabled; import static io.trino.plugin.hudi.HudiSessionProperties.isSizeBasedSplitWeightsEnabled; +import static io.trino.plugin.hudi.HudiUtil.buildTableMetaClient; import static io.trino.spi.StandardErrorCode.GENERIC_INTERNAL_ERROR; import static java.util.stream.Collectors.toList; @@ -128,14 +129,6 @@ public boolean isFinished() return queue.isFinished(); } - public static HoodieTableMetaClient buildTableMetaClient(Configuration configuration, String basePath) - { - HoodieTableMetaClient client = HoodieTableMetaClient.builder().setConf(configuration).setBasePath(basePath).build(); - // Do not load the bootstrap index, will not read bootstrap base data or a mapping index defined - client.getTableConfig().setValue("hoodie.bootstrap.index.enable", "false"); - return client; - } - private static HudiSplitWeightProvider createSplitWeightProvider(ConnectorSession session) { if (isSizeBasedSplitWeightsEnabled(session)) { diff --git a/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/HudiUtil.java b/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/HudiUtil.java index 51d61aa132e8..4976e7e3e539 100644 --- a/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/HudiUtil.java +++ b/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/HudiUtil.java @@ -27,11 +27,13 @@ import io.trino.spi.predicate.NullableValue; import io.trino.spi.predicate.TupleDomain; import io.trino.spi.type.Type; +import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileStatus; import org.apache.hadoop.mapred.InputFormat; import org.apache.hudi.common.fs.FSUtils; import org.apache.hudi.common.model.HoodieBaseFile; import org.apache.hudi.common.model.HoodieFileFormat; +import org.apache.hudi.common.table.HoodieTableMetaClient; import org.apache.hudi.hadoop.HoodieParquetInputFormat; import org.apache.hudi.hadoop.utils.HoodieInputFormatUtils; @@ -152,6 +154,14 @@ public static List buildPartitionKeys(List keys, List< return partitionKeys.build(); } + public static HoodieTableMetaClient buildTableMetaClient(Configuration configuration, String basePath) + { + HoodieTableMetaClient client = HoodieTableMetaClient.builder().setConf(configuration).setBasePath(basePath).build(); + // Do not load the bootstrap index, will not read bootstrap base data or a mapping index defined + client.getTableConfig().setValue("hoodie.bootstrap.index.enable", "false"); + return client; + } + public static FileStatus getFileStatus(HoodieBaseFile baseFile) { try { diff --git a/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/TimelineTable.java b/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/TimelineTable.java index 3d0e13400942..5d819c32bdbe 100644 --- a/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/TimelineTable.java +++ b/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/TimelineTable.java @@ -34,7 +34,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.collect.ImmutableList.toImmutableList; -import static io.trino.plugin.hudi.HudiSplitSource.buildTableMetaClient; +import static io.trino.plugin.hudi.HudiUtil.buildTableMetaClient; import static io.trino.spi.type.VarcharType.VARCHAR; import static java.util.Objects.requireNonNull;