Skip to content

[SPARK-58098][SQL] Convert _LEGACY_ERROR_TEMP_0033 to an internal error#57218

Closed
LuciferYang wants to merge 2 commits into
apache:masterfrom
LuciferYang:assign-name-legacy-0033
Closed

[SPARK-58098][SQL] Convert _LEGACY_ERROR_TEMP_0033 to an internal error#57218
LuciferYang wants to merge 2 commits into
apache:masterfrom
LuciferYang:assign-name-legacy-0033

Conversation

@LuciferYang

@LuciferYang LuciferYang commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

Convert the legacy error condition _LEGACY_ERROR_TEMP_0033 to a SparkException.internalError and remove it from error-conditions.json.

Why are the changes needed?

The error-conditions README disallows new _LEGACY_ERROR_TEMP_* entries and asks existing ones to be resolved. This resolves one of them.

The condition is raised in AstBuilder.visitCreateFileFormat, in the branch where both STORED AS and STORED BY are present. That branch is not reachable from normal parsing:

  • The grammar rule createFileFormat is STORED AS fileFormat | STORED BY storageHandler, so one clause carries only one of the two.
  • Two clauses (STORED AS ... STORED BY ...) are rejected earlier by checkDuplicateClauses as DUPLICATE_CLAUSES.

As it only signals an internal inconsistency, it does not need a user-facing error condition and is converted to an internal error, following precedents such as SPARK-42839.

One trade-off: SparkException.internalError has no overload that carries the parser context, so the ParseException position information (offending fragment, line/column) is no longer attached. This is acceptable here because the branch is unreachable from user queries.

Does this PR introduce any user-facing change?

No. The code path is unreachable from user queries, so the change is not observable in practice.

How was this patch tested?

build/sbt "core/testOnly org.apache.spark.SparkThrowableSuite" passes, covering the JSON validation gates (alphabetical ordering, mandatory SQLSTATE, round-trip). No test is added because the path is unreachable.

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

Generated-by: Claude Code (Opus 4.8)

…_TEMP_0033

Rename the legacy error condition `_LEGACY_ERROR_TEMP_0033` to
`STORED_AS_AND_STORED_BY_BOTH_SPECIFIED`.

The branch in `AstBuilder.visitCreateFileFormat` that raises this error is
unreachable during normal parsing: the grammar rule `createFileFormat` accepts
either STORED AS or STORED BY but not both, and a duplicated clause is already
rejected as `DUPLICATE_CLAUSES`. Since it can only be reached through an
internal inconsistency, the new condition is defined as an internal error
(SQLSTATE `XX000`), following the existing `UNEXPECTED_USE_OF_PARAMETER_MARKER`
precedent, and no user-facing test is added.

@MaxGekk MaxGekk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If it is an internal error, why can't you just throw SparkException.internalError?

Convert the legacy error condition `_LEGACY_ERROR_TEMP_0033` to a
`SparkException.internalError` and remove it from `error-conditions.json`.

The branch in `AstBuilder.visitCreateFileFormat` that raises this error is
unreachable during normal parsing: the grammar rule `createFileFormat` accepts
either STORED AS or STORED BY but not both, and a duplicated clause is already
rejected as `DUPLICATE_CLAUSES`. Since it can only be reached through an
internal inconsistency, it does not need a user-facing error condition.

Note that `SparkException.internalError` has no overload that carries the
parser context, so the `ParseException` position information (offending
fragment, line/column) is no longer attached. This is acceptable here because
the branch is unreachable from user queries.
@LuciferYang LuciferYang changed the title [SPARK-58098][SQL] Assign a name to the error condition _LEGACY_ERROR_TEMP_0033 [SPARK-58098][SQL] Convert _LEGACY_ERROR_TEMP_0033 to an internal error Jul 13, 2026
@LuciferYang

Copy link
Copy Markdown
Contributor Author

Good point, done. I've switched it to SparkException.internalError and removed the condition from error-conditions.json.

One thing worth flagging: internalError has no overload that takes the parser context, so the ParseException position info (offending fragment, line/column) is dropped. Since this branch is unreachable from normal parsing — the grammar allows only one of STORED AS / STORED BY, and a duplicated clause is already caught earlier as DUPLICATE_CLAUSES — losing the context has no user-facing impact here. Let me know if you'd prefer to keep the context anyway.

@MaxGekk MaxGekk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. This implements the SparkException.internalError conversion from the earlier thread.

I verified the case _ branch is not reachable via any public API, not just "normal parsing":

  • visitCreateFileFormat has a single definition (AstBuilder.scala:5599) overriding the generated ANTLR visitor — no subclass (incl. SparkSqlParser) reimplements it.
  • Its only caller is createFileFormatCtx.map(visitCreateFileFormat) (AstBuilder.scala:5779); the contexts come from the grammar rule createFileFormat : STORED AS fileFormat | STORED BY storageHandler (SqlBaseParser.g4:726-729), a strict alternation, so a single CreateFileFormatContext can never carry both children.
  • The statement-level "both clauses" case is caught earlier by checkDuplicateClauses(ctx.createFileFormat, "STORED AS/BY", ctx)DUPLICATE_CLAUSES (AstBuilder.scala:5733), before the visitor runs.
  • AstBuilder/getSerdeInfo are internal, so there's no programmatic path that hands a synthetic context to the visitor.

So it can only fire on a violated grammar invariant — internalError is the right call, and dropping the parser position info has no user-facing impact. The removal is complete (no dangling _LEGACY_ERROR_TEMP_0033 references, alphabetical order preserved, sole caller updated) and consistent with the existing internalError precedent at QueryParsingErrors.scala:44.

@MaxGekk

MaxGekk commented Jul 13, 2026

Copy link
Copy Markdown
Member

+1, LGTM. Merging to master/4.x.
Thank you, @LuciferYang.

@MaxGekk MaxGekk closed this in e33ac21 Jul 13, 2026
MaxGekk pushed a commit that referenced this pull request Jul 13, 2026
### What changes were proposed in this pull request?

Convert the legacy error condition `_LEGACY_ERROR_TEMP_0033` to a `SparkException.internalError` and remove it from `error-conditions.json`.

### Why are the changes needed?

The error-conditions README disallows new `_LEGACY_ERROR_TEMP_*` entries and asks existing ones to be resolved. This resolves one of them.

The condition is raised in `AstBuilder.visitCreateFileFormat`, in the branch where both `STORED AS` and `STORED BY` are present. That branch is not reachable from normal parsing:

- The grammar rule `createFileFormat` is `STORED AS fileFormat | STORED BY storageHandler`, so one clause carries only one of the two.
- Two clauses (`STORED AS ... STORED BY ...`) are rejected earlier by `checkDuplicateClauses` as `DUPLICATE_CLAUSES`.

As it only signals an internal inconsistency, it does not need a user-facing error condition and is converted to an internal error, following precedents such as SPARK-42839.

One trade-off: `SparkException.internalError` has no overload that carries the parser context, so the `ParseException` position information (offending fragment, line/column) is no longer attached. This is acceptable here because the branch is unreachable from user queries.

### Does this PR introduce _any_ user-facing change?

No. The code path is unreachable from user queries, so the change is not observable in practice.

### How was this patch tested?

`build/sbt "core/testOnly org.apache.spark.SparkThrowableSuite"` passes, covering the JSON validation gates (alphabetical ordering, mandatory SQLSTATE, round-trip). No test is added because the path is unreachable.

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

Generated-by: Claude Code (Opus 4.8)

Closes #57218 from LuciferYang/assign-name-legacy-0033.

Authored-by: YangJie <yangjie01@baidu.com>
Signed-off-by: Max Gekk <max.gekk@gmail.com>
(cherry picked from commit e33ac21)
Signed-off-by: Max Gekk <max.gekk@gmail.com>
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.

2 participants