Skip to content

Commit 9786c6e

Browse files
Core: Add metadata table for discovering metadata tables
1 parent 773907d commit 9786c6e

5 files changed

Lines changed: 140 additions & 1 deletion

File tree

core/src/main/java/org/apache/iceberg/MetadataTableType.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@
1818
*/
1919
package org.apache.iceberg;
2020

21+
import java.util.Arrays;
22+
import java.util.List;
2123
import java.util.Locale;
24+
import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
2225

2326
public enum MetadataTableType {
2427
ENTRIES,
@@ -36,7 +39,14 @@ public enum MetadataTableType {
3639
ALL_FILES,
3740
ALL_MANIFESTS,
3841
ALL_ENTRIES,
39-
POSITION_DELETES;
42+
POSITION_DELETES,
43+
METADATA_TABLES;
44+
45+
private final String lower;
46+
47+
MetadataTableType() {
48+
this.lower = name().toLowerCase(Locale.ROOT);
49+
}
4050

4151
public static MetadataTableType from(String name) {
4252
try {
@@ -45,4 +55,14 @@ public static MetadataTableType from(String name) {
4555
return null;
4656
}
4757
}
58+
59+
public String tableName() {
60+
return this.lower;
61+
}
62+
63+
public static List<String> tableNames() {
64+
return Arrays.stream(values())
65+
.map(MetadataTableType::tableName)
66+
.collect(ImmutableList.toImmutableList());
67+
}
4868
}

core/src/main/java/org/apache/iceberg/MetadataTableUtils.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ private static Table createMetadataTableInstance(
8888
return new AllEntriesTable(baseTable, metadataTableName);
8989
case POSITION_DELETES:
9090
return new PositionDeletesTable(baseTable, metadataTableName);
91+
case METADATA_TABLES:
92+
return new MetadataTablesTable(baseTable, metadataTableName);
9193
default:
9294
throw new NoSuchTableException(
9395
"Unknown metadata table type: %s for %s", type, metadataTableName);
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.iceberg;
20+
21+
import java.util.Arrays;
22+
import org.apache.iceberg.types.Types;
23+
24+
/** A {@link Table} implementation that exposes a table's metadata tables as rows. */
25+
public class MetadataTablesTable extends BaseMetadataTable {
26+
MetadataTablesTable(Table table) {
27+
this(table, table.name() + "." + MetadataTableType.METADATA_TABLES.tableName());
28+
}
29+
30+
MetadataTablesTable(Table table, String name) {
31+
super(table, name);
32+
}
33+
34+
private static final Schema METADATA_TABLES_SCHEMA =
35+
new Schema(Types.NestedField.required(1, "metadata_table_name", Types.StringType.get()));
36+
37+
@Override
38+
public TableScan newScan() {
39+
return new MetadataTablesScan(table());
40+
}
41+
42+
@Override
43+
public Schema schema() {
44+
return METADATA_TABLES_SCHEMA;
45+
}
46+
47+
@Override
48+
MetadataTableType metadataTableType() {
49+
return MetadataTableType.METADATA_TABLES;
50+
}
51+
52+
private DataTask task(BaseTableScan scan) {
53+
String location = table().operations().current().metadataFileLocation();
54+
return StaticDataTask.of(
55+
table().io().newInputFile(location != null ? location : scan.table().location()),
56+
schema(),
57+
scan.schema(),
58+
Arrays.asList(MetadataTableType.values()),
59+
metadataType -> StaticDataTask.Row.of(metadataType.tableName()));
60+
}
61+
62+
private class MetadataTablesScan extends StaticTableScan {
63+
MetadataTablesScan(Table table) {
64+
super(
65+
table,
66+
METADATA_TABLES_SCHEMA,
67+
MetadataTableType.METADATA_TABLES,
68+
MetadataTablesTable.this::task);
69+
}
70+
}
71+
}

core/src/test/java/org/apache/iceberg/TestMetadataTableScans.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1833,6 +1833,26 @@ public void testDeleteFilesTableScanOnBranch() throws IOException {
18331833
.isEqualTo(2);
18341834
}
18351835

1836+
@TestTemplate
1837+
public void testMetadataTablesTableScan() throws IOException {
1838+
table.newFastAppend().appendFile(FILE_A).commit();
1839+
1840+
Table metadataTablesTable = new MetadataTablesTable(table);
1841+
List<String> actualTables = Lists.newArrayList();
1842+
try (CloseableIterable<FileScanTask> tasks = metadataTablesTable.newScan().planFiles()) {
1843+
assertThat(tasks).hasSize(1);
1844+
for (FileScanTask task : tasks) {
1845+
try (CloseableIterable<StructLike> rows = task.asDataTask().rows()) {
1846+
for (StructLike row : rows) {
1847+
actualTables.add(row.get(0, String.class));
1848+
}
1849+
}
1850+
}
1851+
}
1852+
List<String> expectedTables = MetadataTableType.tableNames();
1853+
assertThat(actualTables).containsExactlyElementsOf(expectedTables);
1854+
}
1855+
18361856
private int rowCount(TableScan scan) throws IOException {
18371857
int count = 0;
18381858
try (CloseableIterable<FileScanTask> tasks = scan.planFiles()) {

docs/docs/spark-queries.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,32 @@ To inspect a table's history, snapshots, and other metadata, Iceberg supports me
340340

341341
Metadata tables are identified by adding the metadata table name after the original table name. For example, history for `db.table` is read using `db.table.history`.
342342

343+
### Metadata Tables
344+
To list the metadata tables supported by a table:
345+
346+
```sql
347+
SELECT * FROM prod.db.table.metadata_tables;
348+
```
349+
350+
| metadata_table_name |
351+
|----------------------|
352+
| entries |
353+
| files |
354+
| data_files |
355+
| history |
356+
| metadata_log_entries |
357+
| snapshots |
358+
| refs |
359+
| manifests |
360+
| partitions |
361+
| all_data_files |
362+
| all_delete_files |
363+
| all_files |
364+
| all_manifests |
365+
| all_entries |
366+
| position_deletes |
367+
| metadata_tables |
368+
343369
### History
344370

345371
To show table history:

0 commit comments

Comments
 (0)