[SPARK-58300][PROTOBUF] Add from_protobuf option to keep Timestamp/Duration as struct#57474
Open
bhollis-dbx wants to merge 1 commit into
Open
[SPARK-58300][PROTOBUF] Add from_protobuf option to keep Timestamp/Duration as struct#57474bhollis-dbx wants to merge 1 commit into
bhollis-dbx wants to merge 1 commit into
Conversation
…ration as struct `from_protobuf` always maps `google.protobuf.Timestamp` -> `TimestampType` and `google.protobuf.Duration` -> `DayTimeIntervalType`, with no way to turn it off. This adds a `from_protobuf` reader option `convert.timestamp.duration.to.native` (default `true`, preserving today's behavior). When set to `false`, both well-known types fall through to the generic message path and deserialize as their raw proto shape `struct<seconds: bigint, nanos: int>`. The two well-known-type special-cases in `SchemaConverters.structFieldFor` are guarded with the flag so Timestamp/Duration fall through to the existing generic `case MESSAGE =>` -> `StructType` path. The deserializer needs no change: it dispatches on the catalyst type, so the existing (MESSAGE, StructType) case already produces the struct. The `to_protobuf` serializer is intentionally not touched -- this is a read-path option only. Co-authored-by: Isaac
bhollis-dbx
force-pushed
the
bhollis-dbx/protobuf-wkt-native-option
branch
from
July 23, 2026 23:04
436c6f7 to
6a5ea84
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changes were proposed in this pull request?
from_protobufalways mapsgoogle.protobuf.Timestamp->TimestampTypeandgoogle.protobuf.Duration->DayTimeIntervalType. This is Spark's well-known-type conversion and there is currently no way to turn it off.This adds a
from_protobufreader optionconvert.timestamp.duration.to.native(defaulttrue, preserving today's behavior). When set tofalse, both well-known types fall through to the generic message path and deserialize as their raw proto shapestruct<seconds: bigint, nanos: int>.The two well-known-type special-cases in
SchemaConverters.structFieldForare the only places these types are selected. Guarding both with the flag makesTimestamp/Durationfall through to the existing genericcase MESSAGE =>->StructTypepath. The deserializer needs no change: it dispatches on the catalyst type, so the existing(MESSAGE, StructType)case already produces the struct. The option mirrors the existingunwrap.primitive.wrapper.typesprecedent.Scope note: the
to_protobufserializer is intentionally not touched -- this is a read-path option only.Why are the changes needed?
A consumer whose downstream schema was defined against the
{seconds, nanos}struct representation (e.g. a table populated by a different decode path) and must stay stable, or that needs the exactseconds/nanosrather than a microsecond-truncated interval/timestamp, currently has no way to keep these well-known types in their raw proto shape.Does this PR introduce any user-facing change?
Yes, additively. A new
from_protobufreader optionconvert.timestamp.duration.to.nativeis introduced. Its default istrue, which preserves the existing behavior (google.protobuf.Timestamp->TimestampType,google.protobuf.Duration->DayTimeIntervalType). Setting it tofalsemakes those well-known types deserialize asstruct<seconds: bigint, nanos: int>instead. Default behavior is unchanged, so this is purely opt-in.How was this patch tested?
Added
ProtobufFunctionsSuitetest "convert.timestamp.duration.to.native=false keeps Timestamp/Duration as struct", which round-trips aTimestampand aDurationfield throughto_protobuf/from_protobufwith the option set tofalseand asserts:struct<seconds: bigint, nanos: int>(notTimestampType/DayTimeIntervalType), andDuration4.5s->seconds=4, nanos=500000000; theTimestampseconds are derived from the input so the assertion is time-zone independent).Default behavior (
true) is unchanged, so existing well-known-type tests continue to exercise the native-type path. Ran the new test and the existing WKT round-trip tests locally via sbt; all pass.Was this patch authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Opus 4.8)