[SPARK-58366][SQL] Support JSON_TABLE table-valued function - #57559
Open
ganeshashree wants to merge 1 commit into
Open
[SPARK-58366][SQL] Support JSON_TABLE table-valued function#57559ganeshashree wants to merge 1 commit into
ganeshashree wants to merge 1 commit into
Conversation
ganeshashree
force-pushed
the
SPARK-58366
branch
4 times, most recently
from
July 27, 2026 14:32
111f2b5 to
efcc563
Compare
Add the ANSI SQL:2016 `JSON_TABLE` table-valued function, which shreds a JSON
document into a relational table. A row path selects a sequence of JSON items
and a `COLUMNS` clause projects a typed value out of each item into a column.
Syntax (flat, non-nested subset):
JSON_TABLE(json_expr, row_path
COLUMNS (
col1 FOR ORDINALITY,
col2 <type> [PATH '<json_path>'],
col3 <type> EXISTS [PATH '<json_path>']
)
[ { NULL | ERROR } ON ERROR ]
) [AS] alias
- A row path ending in `[*]` expands a JSON array into one row per element; a
non-wildcard path yields a single row for the matched value.
- `FOR ORDINALITY`: a 1-based BIGINT row counter.
- Value columns are extracted and cast to the declared type; the path may be
explicit (`PATH '...'`) or implicit (`'$.<columnName>'`).
- `EXISTS` columns are a presence test cast to the declared type; a
present-but-null JSON value counts as existing, only an absent path is false.
- `{ NULL | ERROR } ON ERROR`: `NULL ON ERROR` (default) yields no rows on
null/malformed input; `ERROR ON ERROR` raises.
- Usable in a comma join and with `LATERAL`.
Implementation notes:
- A `JsonTable` `Generator` expression is wrapped by the existing `Generate`
operator, so no new execution operator is introduced.
- A dedicated grammar production handles the `COLUMNS(...)` clause;
`AstBuilder.visitJsonTableRelation` builds the plan. `ERROR`, `ORDINALITY`,
and `JSON_TABLE` are added as non-reserved keywords.
- A token-aware navigator (`JsonTableEvaluator`) extracts values so that a
missing path, a JSON `null`, and the literal string `"null"` are all
distinguished (unlike `get_json_object`). Non-trailing wildcard paths are
rejected during analysis via `DATATYPE_MISMATCH.INVALID_JSON_TABLE_PATH`.
- Only the flat subset is implemented; `NESTED PATH`, `FORMAT JSON` query
columns, and `DEFAULT ... ON EMPTY` are left as follow-ups.
`JSON_TABLE` is the SQL-standard way to turn JSON into rows and columns, and is
supported by Oracle, DB2, MySQL 8, PostgreSQL 17, Snowflake, and Trino. Spark
previously required chaining `from_json` + `explode`/`inline` + `get_json_object`
to achieve the same result. This folds that into one declarative, standard
construct and eases migration from those systems.
Yes. It adds the `JSON_TABLE` SQL table-valued function and a SQL reference
documentation page. `ERROR`, `ORDINALITY`, and `JSON_TABLE` are added as
non-reserved keywords, so existing queries using them as identifiers continue to
parse. There is no change to existing behavior.
New end-to-end suite `JsonTableSuite` covering array expansion, ordinality,
explicit/implicit paths, missing-vs-null semantics for value and EXISTS columns,
`NULL`/`ERROR ON ERROR`, `[*]` over a non-array, mid-path wildcard rejection,
non-explode string row items, arrays of scalars/strings, duplicate keys,
structure-valued columns, `LATERAL` joins, nested-field extraction, and column
aliases. Existing `JsonExpressionsSuite`, `JsonFunctionsSuite`,
`GeneratorFunctionSuite`, `PlanParserSuite`, `DDLParserSuite`, `SQLKeywordSuite`,
and `SparkThrowableSuite` continue to pass.
Generated-by: Claude Code (Claude Opus 4.8)
ganeshashree
force-pushed
the
SPARK-58366
branch
from
July 28, 2026 03:31
efcc563 to
d8b3a24
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?
Add the ANSI SQL:2016
JSON_TABLEtable-valued function, which shreds a JSON document into a relational table. A row path selects a sequence of JSON items and aCOLUMNSclause projects a typed value out of each item into a column.Syntax (flat, non-nested subset):
[*]expands a JSON array into one row per element; a non-wildcard path yields a single row for the matched value.FOR ORDINALITY: a 1-based BIGINT row counter.PATH '...') or implicit ('$.<columnName>').EXISTScolumns are a presence test cast to the declared type; a present-but-null JSON value counts as existing, only an absent path is false.{ NULL | ERROR } ON ERROR:NULL ON ERROR(default) yields no rows on null/malformed input;ERROR ON ERRORraises.LATERAL.Implementation notes:
JsonTableGeneratorexpression is wrapped by the existingGenerateoperator, so no new execution operator is introduced.COLUMNS(...)clause;AstBuilder.visitJsonTableRelationbuilds the plan.ERROR,ORDINALITY, andJSON_TABLEare added as non-reserved keywords.JsonTableEvaluator) extracts values so that a missing path, a JSONnull, and the literal string"null"are all distinguished (unlikeget_json_object). Non-trailing wildcard paths are rejected during analysis viaDATATYPE_MISMATCH.INVALID_JSON_TABLE_PATH.NESTED PATH,FORMAT JSONquery columns, andDEFAULT ... ON EMPTYare left as follow-ups.Why are the changes needed?
JSON_TABLEis the SQL-standard way to turn JSON into rows and columns, and is supported by Oracle, DB2, MySQL 8, PostgreSQL 17, Snowflake, and Trino. Spark previously required chainingfrom_json+explode/inline+get_json_objectto achieve the same result. This folds that into one declarative, standard construct and eases migration from those systems.Does this PR introduce any user-facing change?
Yes. It adds the
JSON_TABLESQL table-valued function and a SQL reference documentation page.ERROR,ORDINALITY, andJSON_TABLEare added as non-reserved keywords, so existing queries using them as identifiers continue to parse. There is no change to existing behavior.How was this patch tested?
New end-to-end suite
JsonTableSuitecovering array expansion, ordinality, explicit/implicit paths, missing-vs-null semantics for value and EXISTS columns,NULL/ERROR ON ERROR,[*]over a non-array, mid-path wildcard rejection, non-explode string row items, arrays of scalars/strings, duplicate keys, structure-valued columns,LATERALjoins, nested-field extraction, and column aliases. ExistingJsonExpressionsSuite,JsonFunctionsSuite,GeneratorFunctionSuite,PlanParserSuite,DDLParserSuite,SQLKeywordSuite, andSparkThrowableSuitecontinue to pass.Was this patch authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Claude Opus 4.8)