Skip to content

[feature] XQuery 4.0 type coercion rules#6260

Open
joewiz wants to merge 2 commits into
eXist-db:developfrom
joewiz:feature/xq4-type-promotion
Open

[feature] XQuery 4.0 type coercion rules#6260
joewiz wants to merge 2 commits into
eXist-db:developfrom
joewiz:feature/xq4-type-promotion

Conversation

@joewiz
Copy link
Copy Markdown
Member

@joewiz joewiz commented Apr 25, 2026

Summary

  • Implement XQuery 4.0 coercion rules from spec §3.4.1, version-gated behind xquery version "4.0"
  • Add implicit casting: xs:string → xs:anyURI, xs:hexBinary ↔ xs:base64Binary, bidirectional numeric
  • Add relabeling for derived atomic types (e.g., xs:integer 3 accepted as xs:positiveInteger)
  • Accept xquery version "4.0" in the ANTLR tree walker

What Changed

XQueryTree.g — Accept xquery version "4.0", setting context version to 40.

DynamicTypeCheck.java — New xq4ImplicitCast() method handles runtime coercion per spec §3.4.1:

  • Item 4 (Implicit Casting table): xs:string→xs:anyURI, xs:hexBinary↔xs:base64Binary, any numeric → any numeric
  • Item 6 (Relabeling): derived type acceptance when datum is in value space
  • isXQ4ImplicitCast() and isXQ4Relabeling() are static for reuse by the static check

Function.java — Bypass static type check for XQ4 implicit casts and relabeling (line 305).

UntypedValueCheck.java — Version-gate the xs:integer → xs:positiveInteger rejection; allow in XQ4 per §3.4.1 item 6.

xq4-type-promotion.xql — 8 XQSuite tests (XQ 4.0 module) covering all coercion rules.

xq4-type-promotion-gating.xql — 1 version-gating test (XQ 3.1 module) confirming xs:string→xs:anyURI is correctly rejected.

Spec References

Design Decisions

  • No changes to Type.java — the type hierarchy is correct; coercion operates at the function argument level via DynamicTypeCheck, exactly as the spec intends
  • Version-gated — all new rules only activate when xquery version "4.0" is declared
  • The 76 date/time XQTS failures (xs:time is not a sub-type of xs:dateTime) are NOT type promotion — they require function signature changes for fn:*-from-dateTime (QT4 PR1481), tracked separately

Test Plan

  • 9 XQSuite tests pass (string→anyURI, binary coercion, numeric coercion, relabeling, version gating)
  • Full exist-core test suite: 6601 tests, 0 failures, 0 regressions
  • XQTS QT4 run to verify function-call-promotion-* tests pass

🤖 Generated with Claude Code

Add version-gated XQ4 coercion rules that only apply when
`xquery version "4.0"` is declared:

- Implicit Casting (§3.4.1 item 4): xs:string → xs:anyURI,
  xs:hexBinary ↔ xs:base64Binary, bidirectional numeric coercion
- Relabeling (§3.4.1 item 6): derived type acceptance when datum
  is within value space (e.g., xs:integer 3 → xs:positiveInteger)
- Accept `xquery version "4.0"` in the parser

Runtime coercion in DynamicTypeCheck, static check bypass in
Function.java, version-gated integer→positiveInteger in
UntypedValueCheck. No changes to the type hierarchy in Type.java.

Includes 9 XQSuite tests covering all coercion rules plus a
version-gating test confirming XQ 3.1 modules reject string→anyURI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@joewiz joewiz requested a review from a team as a code owner April 25, 2026 04:28
Comment thread exist-core/src/main/antlr/org/exist/xquery/parser/XQueryTree.g Outdated
Convert version if-else chain in XQueryTree.g to switch-as-expression.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@joewiz
Copy link
Copy Markdown
Member Author

joewiz commented Apr 25, 2026

[This response was co-authored with Claude Code. -Joe]

Thanks @reinhapa — addressed in 826ef2d:

  • Converted the XQuery version if-else chain in XQueryTree.g to a switch-as-expression

@line-o line-o added xquery issue is related to xquery implementation XQ4 xquery 4 labels May 7, 2026
@line-o line-o requested a review from a team May 7, 2026 21:45
joewiz added a commit to joewiz/exist that referenced this pull request May 30, 2026
Per @duncdrum and @line-o on PR eXist-db#6344: both reviewers flagged the two
xs:hexBinary ↔ xs:base64Binary code paths as XQ 4.0-specific (the
comments literally say "(XQuery 4.0)") and noted they don't belong in
this XQ 3.1 conformance subset. Removed:

- DynamicTypeCheck.java: the xs:base64Binary ↔ xs:hexBinary type-promotion
  branch in the static-type-check ladder
- GeneralComparison.java: case (d) of resolveNumericType — cast both
  operands of a general comparison to xs:base64Binary when both are
  binary types. Renumbered the now-final XPTY0004 case from (e) to (d).

These will be reintroduced together with the rest of XQ 4.0 type
coercion in v2/xq4-core-functions (PR eXist-db#6260).

XQuery3Tests: 1030/1030 pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

XQ4 xquery 4 xquery issue is related to xquery implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants