Skip to content

[fix] Preceding/following axes miss nodes when predicates add context tracking#6076

Open
joewiz wants to merge 1 commit intoeXist-db:developfrom
joewiz:claude/analyze-issue-4109-KY2bt
Open

[fix] Preceding/following axes miss nodes when predicates add context tracking#6076
joewiz wants to merge 1 commit intoeXist-db:developfrom
joewiz:claude/analyze-issue-4109-KY2bt

Conversation

@joewiz
Copy link
Member

@joewiz joewiz commented Mar 3, 2026

Closes #4109.

Problem

The preceding:: and following:: axes skip nodes when the input node set was produced by an expression with a context-dependent predicate. For example:

(: Expected: w1:pb1, w2:pb1, w3:pb1, w4:pb2, w5:pb2 :)
(: Actual:   w1:pb1, w2:PRECEDING_PB_NOT_FOUND, w3:PRECEDING_PB_NOT_FOUND, w4:pb2, w5:PRECEDING_PB_NOT_FOUND :)
for $w in doc("/db/test/test.xml")//w[exists(.)]
let $preceding-page := $w/preceding::pb[1]
return $w/@id || ":" || ($preceding-page/@id, "PRECEDING_PB_NOT_FOUND")[1]

The predicate [exists(.)] is a no-op logically, but it triggers context tracking: the self:: axis evaluation inside the predicate attaches a context entry to each NodeProxy in the result set. When these nodes are later used as input to preceding:: or following::, the context entries leak through copyContext() into the axis result nodes. The context ID deduplication check in NewArrayNodeSet.selectPreceding() / selectFollowing() then sees a matching context ID and incorrectly skips valid result nodes, treating them as duplicates.

Approach

The fix adds a NO_CONTEXT_ID guard to the existing IGNORE_CONTEXT check in both selectFollowing() and selectPreceding() of NewArrayNodeSet. When contextId is NO_CONTEXT_ID (meaning the axis step is not inside a predicate context tracking scope), the context-based deduplication check is skipped — the same behavior as IGNORE_CONTEXT.

The change is two lines (one per method), following the same pattern already used elsewhere in the codebase where IGNORE_CONTEXT and NO_CONTEXT_ID are treated as equivalent for dedup purposes.

XQTS results

Test set Before (develop) After (this PR) Notes
prod-AxisStep 46 failures 46 failures No change — all pre-existing
prod-AxisStep.following 2 failures 2 failures No change — all pre-existing
prod-AxisStep.preceding 2 failures 2 failures No change — all pre-existing

No regressions introduced.

Note: The XQTS axis tests do not cover the specific scenario of context tracking leaking through predicates on the input expression, which is why there is no XQTS improvement. The issue manifests specifically with persistent (database-stored) nodes and context-dependent predicates on the input node set — a scenario tested by the new XQSuite tests below.

Test plan

  • 4 new XQSuite tests in axes-persistent-nodes.xqm covering both preceding:: and following:: axes with context predicates, in both FLWOR and simple map forms
  • Full eXist test suite: 6,476 tests, 0 failures, 129 skipped
  • XQTS prod-AxisStep, prod-AxisStep.following, prod-AxisStep.preceding: no regressions

🤖 Generated with Claude Code

…ext tracking

Closes eXist-db#4109.

When a context-dependent predicate like [exists(.)] is applied to the
input expression of a FLWOR for clause or simple map operator, the self
axis evaluation inside the predicate adds context tracking entries to
each NodeProxy. These context entries then leak into the cached result
nodes of subsequent selectPreceding/selectFollowing calls via
copyContext(), causing a false-positive match in the context ID
deduplication check. This makes the axis skip valid result nodes after
the first match per group.

The fix adds a NO_CONTEXT_ID guard to the context deduplication check
in both selectFollowing and selectPreceding of NewArrayNodeSet. When
contextId is NO_CONTEXT_ID, the step is not inside a predicate context
tracking scope, so the deduplication check should not be applied.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@joewiz joewiz force-pushed the claude/analyze-issue-4109-KY2bt branch from c48b87a to a388cf8 Compare March 5, 2026 01:40
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.

[BUG] Additional bug affecting predicates on preceding and following steps

3 participants