Skip to content

[SPARK-58221][SQL] Add try_variant_set expression - #57373

Closed
bojana-db wants to merge 4 commits into
apache:masterfrom
bojana-db:try-variant-set
Closed

[SPARK-58221][SQL] Add try_variant_set expression#57373
bojana-db wants to merge 4 commits into
apache:masterfrom
bojana-db:try-variant-set

Conversation

@bojana-db

@bojana-db bojana-db commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

Adds the SQL function try_variant_set(v, path, val[, create_if_missing]), the error-tolerant counterpart of variant_set (SPARK-57804). It sets (inserts or replaces) a value in a Variant value at a single JSONPath location, returning NULL instead of failing the query when the operation hits a recoverable error.

Details:

  • On a valid set, behaves exactly like variant_set: an object path (e.g. $.a) replaces the field if it exists and creates it when create_if_missing is true (the default); an array path (e.g. $[N]) replaces the element at index N, and when N is at or past the end and create_if_missing is true, pads the array with variant nulls up to N; missing intermediate keys/indices along the path are created when create_if_missing is true;
  • When create_if_missing is false, a missing leaf, a missing intermediate, or an out-of-range array index leaves v unchanged;
  • Recoverable errors are caught and return NULL instead of throwing: any path type mismatch (VARIANT_PATH_TYPE_MISMATCH, e.g. an object key applied to an array);
  • Non-recoverable errors still throw, matching variant_set: a malformed path, including the root path $, is rejected with INVALID_VARIANT_PATH (the path is parsed before the set), and a result exceeding the size limit raises VARIANT_SIZE_LIMIT;
  • Any NULL argument returns NULL;
  • The value may be any expression castable to variant.

Why are the changes needed?

Error-tolerant counterpart of variant_set, matching try_variant_get, try_variant_insert, and other try_* functions.

Does this PR introduce any user-facing change?

Yes, a new SQL function try_variant_set (and the corresponding Scala/Python functions API).

How was this patch tested?

Unit tests.

Was this patch authored or co-authored using generative AI tooling?

Generated-by: Cursor with Claude Opus 4.8

@bojana-db bojana-db changed the title Add try_variant_set expression [SPARK-58221] Add try_variant_set expression Jul 20, 2026

@harshmotw-db harshmotw-db left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for the feature!

Comment thread python/pyspark/sql/functions/builtin.py
Comment thread sql/api/src/main/scala/org/apache/spark/sql/functions.scala
@uros-b

uros-b commented Jul 24, 2026

Copy link
Copy Markdown
Member

Thank you @bojana-db and @harshmotw-db @srielau! Proceeding to merge.

@uros-b uros-b changed the title [SPARK-58221] Add try_variant_set expression [SPARK-58221][SQL] Add try_variant_set expression Jul 24, 2026
@uros-b uros-b closed this in 759fbd9 Jul 24, 2026
uros-b pushed a commit that referenced this pull request Jul 24, 2026
### What changes were proposed in this pull request?
Adds the SQL function `try_variant_set(v, path, val[, create_if_missing])`, the error-tolerant counterpart of `variant_set` (SPARK-57804). It sets (inserts or replaces) a value in a Variant value at a single JSONPath location, returning NULL instead of failing the query when the operation hits a recoverable error.

Details:

- On a valid set, behaves exactly like `variant_set`: an object path (e.g. `$.a`) replaces the field if it exists and creates it when `create_if_missing` is true (the default); an array path (e.g. `$[N]`) replaces the element at index `N`, and when `N` is at or past the end and `create_if_missing` is true, pads the array with variant nulls up to `N`; missing intermediate keys/indices along the path are created when `create_if_missing` is true;
- When `create_if_missing` is false, a missing leaf, a missing intermediate, or an out-of-range array index leaves `v` unchanged;
- Recoverable errors are caught and return NULL instead of throwing: any path type mismatch (`VARIANT_PATH_TYPE_MISMATCH`, e.g. an object key applied to an array);
- Non-recoverable errors still throw, matching `variant_set`: a malformed path, including the root path `$`, is rejected with `INVALID_VARIANT_PATH` (the path is parsed before the set), and a result exceeding the size limit raises `VARIANT_SIZE_LIMIT`;
- Any NULL argument returns NULL;
- The value may be any expression castable to variant.

### Why are the changes needed?
Error-tolerant counterpart of `variant_set`, matching `try_variant_get`, `try_variant_insert`, and other `try_*` functions.

### Does this PR introduce _any_ user-facing change?
Yes, a new SQL function `try_variant_set` (and the corresponding Scala/Python `functions` API).

### How was this patch tested?
Unit tests.

### Was this patch authored or co-authored using generative AI tooling?
Generated-by: Cursor with Claude Opus 4.8

Closes #57373 from bojana-db/try-variant-set.

Authored-by: bojana-db <bojana.zecevic@databricks.com>
Signed-off-by: Uros Bojanic <221401595+uros-b@users.noreply.github.com>
(cherry picked from commit 759fbd9)
Signed-off-by: Uros Bojanic <221401595+uros-b@users.noreply.github.com>
@uros-b

uros-b commented Jul 24, 2026

Copy link
Copy Markdown
Member

Merge Summary:

Posted by merge_spark_pr.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants