Introduces a new LogicalType: FILE#585
Conversation
emkornfield
left a comment
There was a problem hiding this comment.
Looks reasonable to me a few minor comments for clarification.
etseidl
left a comment
There was a problem hiding this comment.
Just a few questions I have after reviewing the Rust implementation.
| The annotated group must contain the following fields, identified by name. Field IDs | ||
| may also be used for projection: |
There was a problem hiding this comment.
| The annotated group must contain the following fields, identified by name. Field IDs | |
| may also be used for projection: | |
| The annotated group must contain the following fields, identified by name (not by order). | |
| Field IDs (if exist) may also be used for projection: |
| ##### size | ||
|
|
||
| The length of the content in bytes. Must be zero or a positive integer if provided. | ||
| A value of 0 indicates an empty file. If not provided, the length of the referenced |
There was a problem hiding this comment.
Do we want to advise the reader to ignore negative value here?
There was a problem hiding this comment.
IMO we should specify that readers error on invalid values, not silently ignore
There was a problem hiding this comment.
We can't require readers to fail, we can only say what it means when the length is -1. Failure is a responsibility of whatever uses this data, and it's even hard to require that component to fail because users don't want their query to fail for one bad row. They expect reasonable fallback behavior.
Also, does 0 indicate an empty file or does it indicate 0-length content? With offset, I think this indicates that the content length is 0, not that the underlying file is empty.
| A value of 0 indicates an empty file. If not provided, the length of the referenced | ||
| content is unknown and the entirety of the content can be read. | ||
|
|
||
| ##### offset |
There was a problem hiding this comment.
Should we specify that it must be non-negative?
| The annotated group must contain the following fields, identified by name. Field IDs | ||
| may also be used for projection: | ||
|
|
||
| | Field | Type | Required | |
There was a problem hiding this comment.
I think it would be better to use repetition instead of required, and either required or optional in the table.
I would also state that the struct must contain exactly these fields, rather than saying they are all required since "required" has a special meaning here (the Parquet type's repetition).
| | `path` | STRING | Yes | | ||
| | `size` | INT64 | No | | ||
| | `offset` | INT64 | No | | ||
| | `etag` | STRING | No | |
There was a problem hiding this comment.
I'm neutral on whether the Parquet spec should stay minimal or include convenient metadata (content type, metadata map etc.) for common use cases
But if we are leaning toward keeping the spec simple, I don't think etag should be part of the spec either. etag feels more like storage specific metadata than a portable field with consistent semantics across storage systems
Would be happy to hear more thoughts on this!
There was a problem hiding this comment.
I actually brought this up today in the Parquet sync, it's the odd one out of this pack of properties.
There was a problem hiding this comment.
I concur. The type should be minimal. Also we should make all fields optional and define the semantics of them missing:
path: the file path if present, otherwise this is the path of the current fileoffset: the start of the binary data, otherwise 0size: the size of the binary data, otherwise the length of the file.size, given or derived, is capped such thatoffset + size <= file_size
| * | ||
| * Annotates a group that represents a reference to an external file. | ||
| * The group must contain the following fields identified by name: | ||
| * - path (STRING, required): an opaque string path to the file (e.g. s3://bucket/file.jpg) |
There was a problem hiding this comment.
If it's meant to be a URI, can we mandate it and call the field "uri" instead?
There was a problem hiding this comment.
it's not meant to be a URI. it can be anything, but everyone asked for an example, so I provided a URI example. It's up to the clients on what they store and how they read/consume it
There was a problem hiding this comment.
Disagreed. The standard should say how the field is to be interpreted. If there is no standard interpretation then this is not a proper spec.
There was a problem hiding this comment.
We've gotten pretty far with it just defined as "path" within the Iceberg context. So I would probably be fine with that being the same here although I"m not sure that's actually been useful for Iceberg. I assume most consumers will attempt to parse a URI here anyway and relative paths are also allowed within the URI.
There was a problem hiding this comment.
There is no unambiguous way to distinguish between URIs and "paths", so this needs to be specified explicitly.
The example shows an URI, so the spec should mandate an URI.
There was a problem hiding this comment.
I think Rfc for URI covers all cases mentioned.
We could specify something like
A URI-reference as defined by RFC 3986, encoded as a Parquet STRING. If absolute, it identifies an external resource. If relative, readers must resolve it against the URI of the Parquet file containing this value using RFC 3986 section 5. If
uriis not set, the value refers to the current Parquet file.Readers may support an implementation-defined set of URI schemes. If the scheme is unsupported or the base URI is unavailable for a relative reference, the value is not resolvable.
There was a problem hiding this comment.
I think it should be left to engines. e.g iceberg could choose to resolve relative paths against table's base location. Other engines might do it differently.
There was a problem hiding this comment.
To answer the "it can be left to engines" argument: this is fine for closed environments where the Parquet file never leaves some company cloud of sorts (and even there, several Parquet implementations may be involved).
But Parquet files are a widespread way of publishing and sharing columnar data. If FILE columns cannot be interpreted unambiguously, then ingesting a Parquet file needs additional hands-holding from the user.
There was a problem hiding this comment.
I don't understand the push against uri. A path is a subset of URI, ARN is a URI, database path is an URI. URI comes with the contract that it is a a string identifying a resource. If the idea is to add a free form metadata field then path is not the correct name either.
| | – | set | set | – | external `path`, `[offset, EOF)` | | ||
| | – | set | – | set | external `path`, `[0, size)` | | ||
| | – | set | set | set | external `path`, `[offset, offset + size)` | | ||
| | – | – | set | – | this file, `[offset, EOF)` (self-reference) | |
There was a problem hiding this comment.
This would be invalid with the new requirements for size.
| |----------|--------|----------|--------|----------------------------------------------| | ||
| | set | – | – | – | the inline bytes | | ||
| | – | set | – | – | whole external file at `path` | | ||
| | – | set | set | – | external `path`, `[offset, EOF)` | |
There was a problem hiding this comment.
This would be invalid with the new requirements for size.
| | `inline` | `path` | `offset` | `size` | Resolves to | | ||
| |----------|--------|----------|--------|----------------------------------------------| | ||
| | set | – | – | – | the inline bytes | | ||
| | – | set | – | – | whole external file at `path` | |
There was a problem hiding this comment.
This would be invalid with the new requirements for size.
| The referenced bytes are compressed with the same `CompressionCodec` as the one | ||
| specified for the `inline` column. |
There was a problem hiding this comment.
Let's make this clearer.
| The referenced bytes are compressed with the same `CompressionCodec` as the one | |
| specified for the `inline` column. | |
| The bytes referenced by a self-reference are compressed with the same `CompressionCodec` as the one specified for the `inline` column. |
There was a problem hiding this comment.
Should we point out CompressionCodec can differ per page?
|
@etseidl @sfc-gh-sgrafberger @alkis @rdblue addressed your comments, can you please take another look? |
| `size` must be set whenever `offset` is set or `path` is not set, so a self-reference | ||
| and any offset-based read always carry an explicit `size`. It may be omitted only for a | ||
| whole-file external reference, where the range runs to the end of the referenced file. |
sfc-gh-sgrafberger
left a comment
There was a problem hiding this comment.
Thank you @brkyvz! Looks good to me.
| |----------|--------|----------|--------|-------------------------------------------------------| | ||
| | set | – | – | – | the inline bytes | | ||
| | – | set | – | – | whole external file at `path` | | ||
| | – | set | set | - | external `path`, `[offset, EOF)` | |
There was a problem hiding this comment.
As per text below ("size must be set whenever offset is set, so any offset-based read always carries an explicit size") this should be invalid?
| | – | set | set | - | external `path`, `[offset, EOF)` | | |
| | – | set | set | - | external `path`, invalid | |
| If not set, readers must treat the value as 0. | ||
| If set and non-zero, readers must seek to this offset to retrieve the referenced data. | ||
| `offset` must be set for a self-reference (`path` not set); it is optional for an | ||
| external reference (`path` set). |
There was a problem hiding this comment.
Perhaps worth specifying?
| external reference (`path` set). | |
| external reference (`path` set). `offset must not be < 0. |
…a-io#585) Align with the latest apache/parquet-format#585: - size must be set whenever offset is set; a self-reference (no path) must set offset, and therefore size. Drop the now-invalid [offset, EOF) and [0, size) self-reference modes and the external [offset, EOF) mode from the resolution table; add explicit invalid rows. - Define "set" (present, non-null, non-empty for strings) and allow sparse group definitions (a group need only define the fields it uses); add an inline-only example group. - Fields matched case-sensitively by name; field IDs "if they exist". - Readers should ignore unknown checksum algorithms. Follows the consistent prose intent of PR delta-io#585; note its resolution table still lists an [offset, EOF) row that contradicts its own validation section (offset requires size) -- to be raised on the Parquet PR. Co-authored-by: Isaac
Rationale for this change
Introduces a new type called File as a typed FileReference. The design document is here.
The motivation is as follows:
What changes are included in this PR?
Introduces the specification for FileType.
Do these changes have PoC implementations?
Yes: