ExportXMLWordPrintableJSON

    • Type: Bug
    • Resolution: Fixed
    • Priority: Unknown
    • 10.0.3, 9.1.3, 8.4.3
    • Affects Version/s: None
    • Component/s: None
    • None
    • Dotnet Drivers
    • Not Needed
    • None
    • None
    • None
    • None
    • None
    • None

      Summary

      When a paging operator sits between two joins in a multi-join Include chain, it is hoisted above both $lookup stages, so a row-dropping (inner) $unwind runs before the paging is applied and the wrong rows survive.

      Unable to find source-code formatter for language: csharp. Available languages are: actionscript, ada, applescript, bash, c, c#, c++, cpp, css, erlang, go, groovy, haskell, html, java, javascript, js, json, lua, none, nyan, objc, perl, php, python, r, rainbow, ruby, scala, sh, sql, swift, visualbasic, xml, yaml
      db.Lines.OrderBy(l => l.LineName)
              .Where(l => l.Order.OrderName != "O2")   // above the Order join
              .Take(3)                                 // BETWEEN the two joins
              .Include(l => l.Product)                 // second inner join
              .ToList();
      // correct: filter gives L1,L3,L5,L6 -> Take(3) gives L1,L3,L5 -> Product join drops L5 => ["L1","L3"]
      // actual:  ["L1","L3","L6"]
      
      

      Silent wrong data in the default query mode. L6 is outside the Take(3) window and can only appear because the second join's $unwind dropped a row before the paging ran.

      Scope

      Unreleased. The affected code arrived with efb5f25 (PR #309), which is not an ancestor of v10.0.2; at every release tag the affected files do not exist and the driver-LINQ bridge threw for cross-collection navigation. Not a breaking change.

      Relationship to EF-370

      Found while re-reviewing the EF-370 fix. Not a regression from it — the output is byte-identical at that branch's pre-fix commit.

      EF-370 fixed the closely-related case of paging below the innermost join, by recording the base-source node and emitting the forced-unwind lookups immediately above it instead of at the query root. That repositioning is correct for operators below the joins and is verified by regression tests. This ticket is the residual: an operator interleaved between two joins has no single correct position in a scheme that emits all forced-unwind lookups as one contiguous group.

      A comment added by EF-370 currently claims the emission point "keeps both orderings the query asked for", which is true only for operators below the joins. That comment is being scoped to say so, with a pointer to this ticket, so the overclaim does not mislead a later reader.

      Why it is harder than the case EF-370 fixed

      The forced-unwind lookups must stay together and in dependency order, because a transitive lookup's localField refers to an earlier lookup's output field. That constraint is what makes "emit them as one group, above the base source" a workable rule. Supporting an operator interleaved between two joins means either splitting the group — emitting some lookups, then the operator, then the rest, while preserving the dependency chain — or declining the strip for that shape and letting the driver render the surviving Join natively.

      Declining is the conservative option and is cheap: a decline falls back and returns correct rows, which is strictly better than reordered wrong data. That may be the right first step even if splitting the group is the eventual fix.

      Gating tests

      Assert row counts and identities, not MQL. The whole reason this class of defect persists in this area is that the wrong MQL is indistinguishable from a legitimately different query. Cover Take, Skip and Distinct interleaved between two joins, and keep a control with the same operator below the innermost join (which EF-370 fixed and which must stay correct).

      Related

      Note EF-372 (three-hop ThenInclude emits an unprefixed localField) bounds the same transitive-prefixing invariant this ticket's grouping constraint depends on.

            Assignee:
            Arthur Vickers
            Reporter:
            Arthur Vickers
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: