Core: Add metadata table for discovering metadata tables#17134
Core: Add metadata table for discovering metadata tables#17134yangshangqing95 wants to merge 1 commit into
Conversation
44676e5 to
4c79db9
Compare
|
|
||
| AllDataFilesTable(Table table) { | ||
| this(table, table.name() + ".all_data_files"); | ||
| this(table, table.name() + "." + MetadataTableType.ALL_DATA_FILES.tableName()); |
There was a problem hiding this comment.
To reduce the size of this PR, would you mind moving this refactor and all of the similar replacements into a separate PR?
There was a problem hiding this comment.
Yes, sure. These refactors are related to and required by the changes in this PR, though. Another option is that I can wait until this PR is merged, then submit the refactors separately in a follow-up PR. Would that work for you?
gaborkaszab
left a comment
There was a problem hiding this comment.
Hi @yangshangqing95 ,
I took a Quick Look and left some comments wrt refactors and the new metadata scan implementation.
A general note: querying static data such as metadata table names through SELECT * FROM catalog.db.table.metadata_tables seems somewhat odd to me. We'd expect the same answer regardless the table we use for the query, right?
Anyway, I recall for Iceberg V4 there are consideration to not allow some of the current metadata table and have new ones because the physical representation of a table changes. So this might make sense to have different answers based on the table's version.
Let's see what others think!
| } | ||
|
|
||
| private static final Schema METADATA_TABLES_SCHEMA = | ||
| new Schema(Types.NestedField.required(1, "metadata_table", Types.StringType.get())); |
There was a problem hiding this comment.
"metadata_table_name" ?
| return new StaticDataTask(metadataFile, schema(), scan.schema(), rows); | ||
| } | ||
|
|
||
| private class MetadataTableScan extends BaseMetadataTableScan { |
There was a problem hiding this comment.
Instead of MetadataTableScan maybe MetadataTablesScan or MetadataTableNameScan
| .map(metadataType -> StaticDataTask.Row.of(metadataType.tableName())) | ||
| .toArray(StaticDataTask.Row[]::new); | ||
|
|
||
| DataFile metadataFile = |
There was a problem hiding this comment.
I randomly checked other metadata tables and they seem to use the following InputFile:
table().io().newInputFile(table().operations().current().metadataFileLocation()),
There was a problem hiding this comment.
That’s a good point. For listing the available metadata tables, at least at this stage, we don’t actually need to read any physical file.
Using a directly constructed empty DataFile has a couple of benefits here:
- It avoids unnecessary file operations.
- It makes the intent clearer in the code, since otherwise it may look like the metadata table information is stored in or read from the table metadata file.
So I think using an empty DataFile is more explicit for this particular metadata table.
| .withFileSizeInBytes(0) | ||
| .build(); | ||
|
|
||
| return new StaticDataTask(metadataFile, schema(), scan.schema(), rows); |
There was a problem hiding this comment.
Other metadata tables use StaticDataTask.of()
There was a problem hiding this comment.
same reason as the above one
| } | ||
|
|
||
| private DataTask task(BaseTableScan scan) { | ||
| StaticDataTask.Row[] rows = |
There was a problem hiding this comment.
Checking RefsTable instead of constructing StaticDataTask.Row[]', we can simply use Collectionwith a transform function to convert it to row viaStaticDataTask.Row.of()`
There was a problem hiding this comment.
Hi @gaborkaszab same reason with the usage of empty Datafile, as constructor accept parameter Row[]
StaticDataTask(
DataFile metadataFile,
Schema tableSchema,
Schema projectedSchema,
StructLike[] rows)
| } | ||
|
|
||
| private class MetadataTableScan extends BaseMetadataTableScan { | ||
| MetadataTableScan(Table table, Schema schema) { |
There was a problem hiding this comment.
I don't think any of these constructors need the Schema parameter. See RefsTable.RefsTableScan
| protected CloseableIterable<FileScanTask> doPlanFiles() { | ||
| return CloseableIterable.withNoopClose(task(this)); | ||
| } | ||
| } |
There was a problem hiding this comment.
After reding this Scan class and comparing to others can't we simply do what PartitionsScan does?
PartitionsScan(Table table) {
super(
table,
PartitionsTable.this.schema(),
MetadataTableType.PARTITIONS,
PartitionsTable.this::task);
|
|
||
| // Expect that the new data is changed in the meantime | ||
| assertThat(deserializedFiles).isNotEqualTo(newFiles); | ||
| if (type == MetadataTableType.METADATA_TABLES) { |
There was a problem hiding this comment.
not entirely sure why the new table is any different than the other in this test.
There was a problem hiding this comment.
Since reading the metadata tables does not require reading any actual files, the file path would remain unchanged regardless of how many commits are made. Therefore, this case needs to be handled separately.
| Set.of(DataFile.FIRST_ROW_ID.fieldId())); | ||
| Schema filesTableSchema = | ||
| Spark3Util.loadIcebergTable(spark, tableName + ".all_data_files").schema(); | ||
| Spark3Util.loadIcebergTable( |
There was a problem hiding this comment.
These changes are pure refactors. Move to separate PR to reduce the noise as advised above.
There was a problem hiding this comment.
sure for the refactors I can submit a separate one when this PR get merged.
Hi @gaborkaszab thanks for taking a look and leaving the comments! Regarding the metadata table query, I did consider this initially as well. From both an implementation perspective and the current project structure, I’m still leaning toward exposing it under each table, mainly for a few reasons:
So from that perspective, it may not necessarily be true that all tables should always return the exact same metadata tables. |
4c79db9 to
fbd4c32
Compare
fbd4c32 to
ef31403
Compare
close #17132
Summary
This PR adds a new Iceberg metadata table, metadata_tables, to make available metadata tables discoverable through the existing metadata table mechanism.
For example, in Spark users can query:
Result:
The new metadata table returns the supported metadata table names
This avoids requiring users to know all metadata table names ahead of time from documentation or source code.
Also, replace selected hard-coded metadata table suffixes in tests and metadata table implementations with MetadataTableType#tableName, enhance code robustness.