feat(codecs, databricks_zerobus sink): Unity Catalog VARIANT support#25890
feat(codecs, databricks_zerobus sink): Unity Catalog VARIANT support#25890yorickvanzweeden wants to merge 3 commits into
Conversation
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 938623cd33
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| let json = if let Some(json) = value.as_str() { | ||
| json | ||
| } else { | ||
| owned_json = value.to_string(); | ||
| &owned_json |
There was a problem hiding this comment.
Preserve string scalars when encoding VARIANT values
When a VARIANT column receives a normal Vector string value, this branch treats that string as already-serialized JSON instead of as the JSON string scalar it is. In practice inputs such as "hello" are rejected as invalid JSON, while strings like "42" or "true" are silently stored as numeric/boolean VARIANTs rather than strings; this corrupts or drops rows for VARIANT columns containing scalar string data. Since non-string serde_json::Values are serialized below, string values need a path that preserves them as strings unless the user has explicitly provided pre-serialized JSON.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Declining this one. Strings are intentionally treated as serialized JSON so values such as {"name":"Alice"} become VARIANT objects rather than quoted strings. Native objects, arrays, numbers, and booleans are serialized directly. A VARIANT string scalar can still be provided as valid JSON string text, for example "\"hello\"". Supporting both interpretations would require an explicit input mode; guessing would make one of them silently incorrect.
| return Ok(()); | ||
| } | ||
|
|
||
| if is_variant_data_type(data_type) { |
There was a problem hiding this comment.
Avoid treating ordinary binary structs as VARIANT
Because this generic Arrow/Parquet encoder now infers VARIANT solely from the child field shape, any user schema with a normal Struct<metadata: LargeBinary, value: LargeBinary> is rewritten as a Parquet VARIANT instead of preserving the two binary fields. This affects non-Databricks users of the same serializer, such as user-provided Arrow schemas for ClickHouse or Parquet output, where an event object containing metadata and value would be serialized as a new VARIANT payload and the original binary fields are lost. Please gate this conversion on an explicit VARIANT marker/configuration rather than the plain struct shape.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed. The generic Arrow encoder no longer identifies VARIANT from the metadata/value struct shape. VARIANT fields must now be passed explicitly by logical field path. With no paths configured—the default for Parquet, ClickHouse, and other users—the struct is encoded normally. I also added regression coverage for an ordinary struct with the same physical shape.
| } | ||
|
|
||
| fn is_variant_data_type(data_type: &DataType) -> bool { | ||
| let DataType::Struct(fields) = data_type else { |
There was a problem hiding this comment.
Duck typing here might be a bit risky in case a user defines a struct type in a table with exactly the same fields. It probably would make sense to attach an annotation that the Field is variant before checking it but I think it would require changes in the zerobus server and SDK.
There was a problem hiding this comment.
Fixed without changing the server or SDK. We retain the logical VARIANT paths from the Unity Catalog schema and pass them separately to Vector’s encoder. The Arrow wire schema remains unchanged. The encoder validates each marked path against the expected physical representation, but never infers VARIANT from that representation alone.
Forgot to push, will do in about 12 hours. Let me know if this solution fits the bill
Summary
Hi Vector team,
Databricks released another fix for their Zerobus Ingestion SDK. This PR:
Please let me know if you require any changes, or have any questions.
Vector configuration
The sink can be configured as follows:
When using ${...} environment variables, Vector environment interpolation must be explicitly enabled or replaced with an appropriate secret-injection mechanism.
How did you test this PR?
Additionally, I ran an internal test against our Databricks instance.
Change Type
Is this a breaking change?
Does this PR include user facing changes?
References