[SQL][SPARK-59469] Report structured errors for invalid JDBC partition bounds - #58762
[SQL][SPARK-59469] Report structured errors for invalid JDBC partition bounds#58762urosstan-db wants to merge 7 commits into
Conversation
| import org.apache.spark.sql.catalyst.analysis.caseSensitiveResolution | ||
| import org.apache.spark.sql.types.{DateType, StructType, TimestampNTZType, TimestampType} | ||
|
|
||
| class JDBCRelationSuite extends SparkFunSuite { |
There was a problem hiding this comment.
We can convert all tests to integration tests as well, but I think current approach (one integration test, full matrix with unit tests) is a good trade-off between test cost and coverage.
| "message" : [ | ||
| "Cannot parse the value <value> for JDBC option <option> as <dataType>." | ||
| ], | ||
| "sqlState" : "42616" |
There was a problem hiding this comment.
Using 42616 ("Invalid options specified") here. Summary of the SQLSTATE investigation:
- The closest existing precedents are Avro Boolean option parsing and Protobuf Boolean/integer option parsing. Both report
STDS_INVALID_OPTION_VALUE.WITH_MESSAGE, whose SQLSTATE is42616. The state data source also uses this family for invalid option values. - Other formats are mixed: CSV quote/escape length and
lineSepvalidation, and CSV/JSON charset validation, use22023; Parquet/ORC unavailable-codec errors use56038. There is no single SQLSTATE used for all data-source option errors.
JDBC has many checks, but its most comparable validations still have no SQLSTATE:
| Validation | Existing error | SQLSTATE |
|---|---|---|
Invalid integer options (numPartitions, queryTimeout, fetchsize, batchsize) |
Direct .toInt / NumberFormatException |
None |
batchsize < 1, missing required partition options, or lower bound greater than upper bound |
require / IllegalArgumentException |
None |
Invalid isolationLevel |
_LEGACY_ERROR_TEMP_2081 |
None |
Write numPartitions <= 0 |
_LEGACY_ERROR_TEMP_2087 |
None |
Conflicting, missing, or empty dbtable / query |
_LEGACY_ERROR_TEMP_2078 through 2080 |
None |
| Null option value | NULL_DATA_SOURCE_OPTION |
22024 |
hint unsupported by the dialect |
HINT_UNSUPPORTED_FOR_JDBC_DIALECT |
42822 |
Sources: JDBCOptions, bound ordering, write partition count, and legacy error definitions. The legacy conditions omit SQLSTATE; using SparkIllegalArgumentException does not supply one implicitly.
Schema-valued JDBC options reuse parser/schema errors: createTableColumnTypes has syntax errors (42601), duplicate columns (42711), and unsupported types (0A000), as covered in JDBCWriteSuite. The nearby JdbcDialects.getBuiltInDialect API uses 22023 for unknown names, but that validates an API argument, not a data-source option.
So this choice follows the Avro/Protobuf option-conversion precedent, not an established JDBC convention. 22023 ("invalid parameter value") is the more portable standard category; 42616 is DB2-origin and nonstandard, but already established in Spark for this kind of option validation. The JDBC-specific condition preserves the option name, rejected value, and expected type.
Code review — Claude Opus (xhigh reasoning)Verdict: 0 blocking, 0 non-blocking, 0 nits. A clean, well-scoped, backward-compatible change with good test coverage. What the change doesInvalid JDBC Verification (static)
This is a static review — the two affected suites were not executed here (the description notes they weren't rerun after the SQLSTATE-only update), but the code and test expectations agree on Notes (non-blocking)
Automated review generated by Claude Opus at xhigh reasoning effort. |
urosstan-db
left a comment
There was a problem hiding this comment.
Codex review
No findings. 0 blocking, 0 non-blocking, 0 nits.
No changes recommended; the existing review requests are addressed.
Verification
Reviewed all five changed files, the temporal parsers, error formatting, exception inheritance, and JDBC V1/V2 callers. Both read paths use the same partition routine, and the new exception remains an IllegalArgumentException. The tests cover both bound names for all three temporal types and preserve valid predicate expectations. The efficiency scanner found no issues.
Tests were not run during this review.
| }, | ||
| "INVALID_JDBC_PARTITION_BOUND" : { | ||
| "message" : [ | ||
| "Cannot parse the value <value> for JDBC option <option> as <dataType>." |
There was a problem hiding this comment.
| "Cannot parse the value <value> for JDBC option <option> as <dataType>." | |
| "Cannot parse the value <value> for JDBC data source option <option> as <dataType>." |
What changes were proposed in this pull request?
SparkIllegalArgumentException, conditionINVALID_JDBC_PARTITION_BOUND, and SQLSTATE42616.lowerBoundorupperBound), supplied value, and expected data type in the error message.42616("Invalid options specified"), following Avro and Protobuf option-validation errors.Why are the changes needed?
IllegalArgumentExceptionwithout an error condition or SQLSTATE.Cannot parse the bound value {bound} as timestamp, does not identify which JDBC option to correct.Does this PR introduce any user-facing change?
How was this patch tested?
Added
JDBCRelationSuitecoverage for invalid lower and upper bounds acrossDATE,TIMESTAMP, andTIMESTAMP_NTZ, including placeholders, empty strings, and invalid calendar dates. Positive cases check the generated partition predicates.Updated the existing
JDBCSuitetimezone-bound regression test to check the structured error.Both affected test expectations now use
42616; these suites have not been rerun for the SQLSTATE-only update.Was this patch authored or co-authored using generative AI tooling?
Generated-by: OpenAI Codex CLI 0.153.4