Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Must be reducible node exception when performing Join #3103

Closed
kskalski opened this issue Sep 11, 2015 · 10 comments
Closed

Must be reducible node exception when performing Join #3103

kskalski opened this issue Sep 11, 2015 · 10 comments
Assignees
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-bug
Milestone

Comments

@kskalski
Copy link

Doing following join:
ScheduledPayouts.Join(Assets, p => p.Good.Id, a => a.Good.Id, (p, a) => new Tuple<Asset, ScheduledPayout>(a, p));

throws following exception:

   w System.Linq.Expressions.Expression.ReduceAndCheck()
   w System.Linq.Expressions.Expression.ReduceExtensions()
   w System.Linq.Expressions.Compiler.StackSpiller.RewriteExtensionExpression(Expression expr, Stack stack)
   w System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
   w System.Linq.Expressions.Compiler.StackSpiller.RewriteMemberExpression(Expression expr, Stack stack)
   w System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
   w System.Linq.Expressions.Compiler.StackSpiller.Rewrite[T](Expression`1 lambda)
   w System.Linq.Expressions.Expression`1.Accept(StackSpiller spiller)
   w System.Linq.Expressions.Compiler.StackSpiller.RewriteLambdaExpression(Expression expr, Stack stack)
   w System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
   w System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.Add(Expression node)
   w System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.AddArguments(IArgumentProvider expressions)
   w System.Linq.Expressions.Compiler.StackSpiller.RewriteMethodCallExpression(Expression expr, Stack stack)
   w System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
   w System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.Add(Expression node)
   w System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.AddArguments(IArgumentProvider expressions)
   w System.Linq.Expressions.Compiler.StackSpiller.RewriteMethodCallExpression(Expression expr, Stack stack)
   w System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
   w System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.Add(Expression node)
   w System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.AddArguments(IArgumentProvider expressions)
   w System.Linq.Expressions.Compiler.StackSpiller.RewriteMethodCallExpression(Expression expr, Stack stack)
   w System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
   w System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.Add(Expression node)
   w System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.AddArguments(IArgumentProvider expressions)
   w System.Linq.Expressions.Compiler.StackSpiller.RewriteMethodCallExpression(Expression expr, Stack stack)
   w System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
   w System.Linq.Expressions.Compiler.StackSpiller.Rewrite[T](Expression`1 lambda)
   w System.Linq.Expressions.Expression`1.Accept(StackSpiller spiller)
   w System.Linq.Expressions.Compiler.StackSpiller.RewriteLambdaExpression(Expression expr, Stack stack)
   w System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
   w System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.Add(Expression node)
   w System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.AddArguments(IArgumentProvider expressions)
   w System.Linq.Expressions.Compiler.StackSpiller.RewriteMethodCallExpression(Expression expr, Stack stack)
   w System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
   w System.Linq.Expressions.Compiler.StackSpiller.Rewrite[T](Expression`1 lambda)
   w System.Linq.Expressions.Expression`1.Accept(StackSpiller spiller)
   w System.Linq.Expressions.Compiler.LambdaCompiler.Compile(LambdaExpression lambda, DebugInfoGenerator debugInfoGenerator)
   w System.Linq.Expressions.Expression`1.Compile()
   w Microsoft.Data.Entity.Query.EntityQueryModelVisitor.CreateExecutorLambda[TResults]()
   w Microsoft.Data.Entity.Query.EntityQueryModelVisitor.CreateQueryExecutor[TResult](QueryModel queryModel)
   w Microsoft.Data.Entity.Storage.RelationalDatabase.CompileQuery[TResult](QueryModel queryModel)
--- Koniec śladu stosu z poprzedniej lokalizacji, w której wystąpił wyjątek ---
   w System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   w Microsoft.Data.Entity.Query.CompiledQueryCache.CompileQuery(IDatabase database, MethodInfo compileMethodInfo, Type resultItemType, QueryModel queryModel)
   w Microsoft.Data.Entity.Query.CompiledQueryCache.<>c__7`1.<Execute>b__7_0(Expression q, IDatabase ds)
   w Microsoft.Data.Entity.Query.CompiledQueryCache.GetOrAdd(Expression query, QueryContext queryContext, IDatabase database, Boolean isAsync, Func`3 compiler)
   w Microsoft.Data.Entity.Query.CompiledQueryCache.Execute[TResult](Expression query, IDatabase database, QueryContext queryContext)
   w Microsoft.Data.Entity.Query.EntityQueryProvider.Execute[TResult](Expression expression)
   w Remotion.Linq.QueryableBase`1.GetEnumerator()
   w System.Linq.SystemCore_EnumerableDebugView`1.get_Items()

the model is:

  [Table("assets")]
  public class Asset {
    public int Id { get; set; }
    [StringLength(16)]
    public string Name { get; set; }
    public decimal Amount { get; set; }
    public decimal ObtainPrice { get; set; }
    public MarketGood Good { get; set; }
  }
  [Table("market_goods")]
  public class MarketGood {
    public int Id { get; set; }
    [StringLength(16)]
    public string Name { get; set; }
    [StringLength(32)]
    public string LongName { get; set; }
  }

  [Table("scheduled_payouts")]
  public class ScheduledPayout {
    public int Id { get; set; }
    public MarketGood Good { get; set; }
    public decimal ValuePerUnit { get; set; }
    public DateTime ValidityDate { get; set; }
    public DateTime PayoutDate { get; set; }
  }

and debug string for the failed expression:

.Call System.Linq.Queryable.Join(
    .Constant<Microsoft.Data.Entity.Query.EntityQueryable`1[Portfolio.Models.ScheduledPayout]>(Microsoft.Data.Entity.Query.EntityQueryable`1[Portfolio.Models.ScheduledPayout]),
    .Constant<Microsoft.Data.Entity.Query.EntityQueryable`1[Portfolio.Models.Asset]>(Microsoft.Data.Entity.Query.EntityQueryable`1[Portfolio.Models.Asset]),
    '(.Lambda #Lambda1<System.Func`2[Portfolio.Models.ScheduledPayout,System.Int32]>),
    '(.Lambda #Lambda2<System.Func`2[Portfolio.Models.Asset,System.Int32]>),
    '(.Lambda #Lambda3<System.Func`3[Portfolio.Models.ScheduledPayout,Portfolio.Models.Asset,System.Tuple`2[Portfolio.Models.Asset,Portfolio.Models.ScheduledPayout]]>))

.Lambda #Lambda1<System.Func`2[Portfolio.Models.ScheduledPayout,System.Int32]>(Portfolio.Models.ScheduledPayout $p) {
    ($p.Good).Id
}

.Lambda #Lambda2<System.Func`2[Portfolio.Models.Asset,System.Int32]>(Portfolio.Models.Asset $a) {
    ($a.Good).Id
}

.Lambda #Lambda3<System.Func`3[Portfolio.Models.ScheduledPayout,Portfolio.Models.Asset,System.Tuple`2[Portfolio.Models.Asset,Portfolio.Models.ScheduledPayout]]>(
    Portfolio.Models.ScheduledPayout $p,
    Portfolio.Models.Asset $a) {
    .New System.Tuple`2[Portfolio.Models.Asset,Portfolio.Models.ScheduledPayout](
        $a,
        $p)
}

Note that materializing the collections and doing the join then works fine:
return ScheduledPayouts.Include(p => p.Good).ToList().Join(Assets.Include(a => a.Good).ToList(), p => p.Good.Id, a => a.Good.Id, (p, a) => new Tuple<Asset, ScheduledPayout>(a, p));

this is with beta7, in beta6 I had different kind of exception (something about Single not allowing multiple elements in collection).

@Sharpiro
Copy link

I'm new to EF and LINQ, and I am receiving the same error, though I don't know if for the same reason. Also using beta7.

Here is the query I would like to perform that throws the "Must be reducible node exception":

var day = context.Days.OrderByDescending(d => d.Created).FirstOrDefault();
                var meals = context.Meals
                    .Where(m => m.DayId == day.Created)
                    .OrderBy(m => m.MealNumber).Include(m => m.MealEntries)
                    .Select(m => new MealViewModel
                    {
                        Id = m.Id,
                        MealNumber = m.MealNumber,
                        MealEntries = m.MealEntries.Select(me => new mealEntryViewModel
                        {
                            FoodId = me.Id,
                            Calories = me.Calories
                        })
                    });

Here is the modification that fixes the exception:

.OrderBy(m => m.MealNumber).Include(m => m.MealEntries).ToList()

You can see the only difference is the addition of "ToList()". Please let me know if I'm doing anything wrong or inefficient. Thanks.

@rowanmiller rowanmiller added this to the 7.0.0-rc1 milestone Sep 18, 2015
@AlexTo
Copy link

AlexTo commented Sep 30, 2015

Exact same issue, my simple join query like so do not work:
from a in _db.A join b in _db.B on ...

but if I add .ToList() after _db.A and _db.B then it works :(

@maumar
Copy link
Contributor

maumar commented Oct 1, 2015

@kskalski the problem is because of the way we translate navigation properties in the key selectors.

consider a simpler version of the query:

from p in ctx.Payouts
join a in ctx.Assets on p.Good.Id equals a.Id
select p

What we do is expand the nav prop p.Good into a join like so:

from p in ctx.Payouts
join g from ctx.Goods on p.Id equals g.Id
join a in ctx.Assets on g.Id equals a.Id
select p

this works great, however if the nav prop is in the inner selector:

from p in ctx.Payouts
join a in ctx.Assets on p.Id equals a.Good.Id
select p

this logic fails due to chicken and egg problem:

from p in ctx.Payouts
join g in ctx.Good on a.Id equals g.Id // invalid, because g was not declared yet
join a in ctx.Assets on g.Id equals a.Id

We need to do a different expansion pattern for the case like yours. In the meantime, you could mitigate this by using foreign keys rather than nav props, like so:

ScheduledPayouts.Join(Assets, p => p.GoodId, a => a.GoodId, (p, a) => new Tuple<Asset, ScheduledPayout>(a, p));

(you would need to add the foreign keys to the model first).

@Sharpiro @AlexTo adding ToList() to a query makes it so that it no longer uses Entity Framework, but Linq to Objects instead, and may cause inefficiencies in your queries, e.g.

ctx.Customers.ToList().Where(c => c.Id = 10)  

will query the database for all the customers and perform the filter on the client. @Sharpiro in your case this is not that impactful, because you add ToList() before the projection. Filter, sorting and include is done using EF. I'll investigate your case as well, probably the root cause is similar even though the query is little different.

@AlexTo can you share the query that fails for your, I'm mostly interested in the part that comes after "on" (key selectors). Also could you post the model that you used?

@kskalski
Copy link
Author

kskalski commented Oct 2, 2015

Thanks for analysis.
Right, I thought that using foreign key property would work around the problem, since I would not involve MarketGood table at all.
However this query also shows the inefficiency of the current translation method. Note that I never actually requested Good to be materialized / included in the result set, so in theory your suggestion for modifying query to use GoodId instead of Good.Id is not just a way to avoid this bug, but also a way to optimize DB access such that MarketGood table is not joined at all. It would be nice if the framework made this kind of optimization on its own.

On the other hand I'm not sure what is the standardized or expected semantics when using navigational properties for filtering or joins, do they imply materialization of intermediate objects or not. I can imagine somebody doing 'from p in ctx.Assets where p.Good.Id == 3 select p' would expect returned p to have non-null p.Good and if the navigation property doesn't actually translate to foreign key in the source table, e.g. 'from p in ctx.Assets where p.Good.Name == "x" select p' then DB access need to do the join anyway. So maybe for the sake of consistency it's better to always do it and materialize intermediate objects.

@AlexTo
Copy link

AlexTo commented Oct 2, 2015

Here is the complete query that works, to make it failed, just remove all ToList()

return (from f in _db.Fields.Include(f => f.Node).ToList()
                    join e in _db.Edges.Include(e => e.A).Include(e => e.B).ToList() on f.Node.Id equals e.A.Id
                    join n in _db.Nodes.ToList() on e.B.Id equals n.Id
                    where f.Key == FieldKey.UserId.ToString() && f.Value == userId
                    && e.Type == EdgeType.HasProfilePicture.ToString()
                    select e.B).FirstOrDefault();

And my model

public class Field : Common
    {
        [Required]
        public string Key { get; set; }

        [Required]
        public string Value { get; set; }

        [Required]
        public string Type { get; set; }

        [Required]
        public Node Node { get; set; }
}

public class Node : Common
    {
        private ICollection<Field> _fields;
        private ICollection<Edge> _outgoingEdges;
        private ICollection<Edge> _incomingEdges;

        [Required]
        public string Type { get; set; }

        public virtual ICollection<Field> Fields
        {
            get { return _fields ?? (_fields = new List<Field>()); }
            set { _fields = value; }
        }

        public virtual ICollection<Edge> OutgoingEdges
        {
            get { return _outgoingEdges ?? (_outgoingEdges = new List<Edge>()); }
            set { _outgoingEdges = value; }
        }

        public virtual ICollection<Edge> IncomingEdges
        {
            get { return _incomingEdges ?? (_incomingEdges = new List<Edge>()); }
            set { _incomingEdges = value; }
        }
}

public class Edge : Common
    {
        [Required]
        public Node A { get; set; }

        [Required]
        public Node B { get; set; }

        [Required]
        public string Type { get; set; }
}

And I have this configuration in OnModelCreating

builder.Entity<Node>()
                .Collection(n => n.OutgoingEdges)
                .InverseReference(e => e.A);

            builder.Entity<Node>()
                .Collection(n => n.IncomingEdges)
                .InverseReference(e => e.B);

Thank you

@maumar
Copy link
Contributor

maumar commented Oct 2, 2015

I am currently working on a fix that will detect this case and translate to FK, if possible. Problem is that this can only be done for a subset of scenarios (no composite keys, no chaining of nav props, you need to use PK as a key selector, as opposed to e.g. "name", and navigation needs to point in the right direction).

For other cases we will try to do a more involved and much less optimal translation, probably involving CROSS APPLY.

When it comes to materialization, we only materialize stuff that is specified in the select clause, intermediate results will not get materialized. In the example you provided, p will not load in the "Good" nav prop, unless you explicitly ask for it (using Include). We always want to materialize as little as possible to minimize the amount of data sent over the wire.

maumar added a commit that referenced this issue Oct 9, 2015
…ng Join

Problem is in a query with join, that has a navigation property in inner key selector.
We normally try to expand the navigation property into a join clause, however if done for inner key selector, leads to chicken-and-egg problem:

e.g.
from p in ctx.Payouts
join a in ctx.Assets on p.Id equals a.Good.Id
select p

translated to:
from p in ctx.Payouts
join g in ctx.Good on a.Id equals g.Id // invalid, because a was not declared yet
join a in ctx.Assets on g.Id equals a.Id

(alternatively)

from p in ctx.Payouts
join a in ctx.Assets on g.Id equals a.Id // invalid, because g was not declared yet
join g in ctx.Good on a.Id equals g.Id

Is some cases this can we worked around by translating navigation property into a FK:
from p in ctx.Payouts
join a in ctx.Assets on p.Id equals a.GoodId
select p

This is only possible if we actually have foreign key on this side of the navigation, and if the navigation itself is simple (not nested, not composite and we are accessing PK after the navigation).
maumar added a commit that referenced this issue Oct 14, 2015
Problem:
We were incorrectly expanding navigations that appeared in the inner key selector of a join expression (right side).
Normally we expand nav props into additional join. E.g.:

from p in ctx.Payouts
join a in ctx.Assets on p.Good.Id equals a.Id
select p

converts to:

from p in ctx.Payouts
join g from ctx.Goods on p.Id equals g.Id
join a in ctx.Assets on g.Id equals a.Id
select p

However if navigation propery is in the inner key selector, like so:

from p in ctx.Payouts
join a in ctx.Assets on p.Id equals a.Good.Id
select p

we encounter chicken-and-egg problem:

from p in ctx.Payouts
join g in ctx.Good on a.Id equals g.Id // invalid, because a was not declared yet
join a in ctx.Assets on g.Id equals a.Id

or

from p in ctx.Payouts
join a in ctx.Assets on g.Id equals a.Id // invalid, because g was not declared yet
join g in ctx.Good on a.Id equals g.Id

Solution:

Some navigation properties can be translated into FKs, which removes the problem:

from c in Customers
join d in Details on c.Id equals d.Customer.Id
select c

can be translated into:

from c in Customers
join d in Details on c.Id equals c.CustomerId
select c

This can only be done for a subset of queries - join needs to be based on key property, FK must be pointing the right way, and key must not be composite.

For all other cases we translate this into a subquery:

from c in Customers
join d in Details on c.Id equals
(from c2 in Customers
 where c2.CustomerId equals d.Id
 select c2.Id).FirstOrDefault()

In case of nested navigation property we expand the first one into a subquery, and add extra joins to the subquery, just like we did originally. Only the first navigation is "problematic", the following ones can be safely translated to joins
maumar added a commit that referenced this issue Oct 15, 2015
Problem:
We were incorrectly expanding navigations that appeared in the inner key selector of a join expression (right side).
Normally we expand nav props into additional join. E.g.:

from p in ctx.Payouts
join a in ctx.Assets on p.Good.Id equals a.Id
select p

converts to:

from p in ctx.Payouts
join g from ctx.Goods on p.Id equals g.Id
join a in ctx.Assets on g.Id equals a.Id
select p

However if navigation propery is in the inner key selector, like so:

from p in ctx.Payouts
join a in ctx.Assets on p.Id equals a.Good.Id
select p

we encounter chicken-and-egg problem:

from p in ctx.Payouts
join g in ctx.Good on a.Id equals g.Id // invalid, because a was not declared yet
join a in ctx.Assets on g.Id equals a.Id

or

from p in ctx.Payouts
join a in ctx.Assets on g.Id equals a.Id // invalid, because g was not declared yet
join g in ctx.Good on a.Id equals g.Id

Solution:

Some navigation properties can be translated into FKs, which removes the problem:

from c in Customers
join d in Details on c.Id equals d.Customer.Id
select c

can be translated into:

from c in Customers
join d in Details on c.Id equals c.CustomerId
select c

This can only be done for a subset of queries - join needs to be based on key property, FK must be pointing the right way, and key must not be composite.

For all other cases we translate this into a subquery:

from c in Customers
join d in Details on c.Id equals
(from c2 in Customers
 where c2.CustomerId equals d.Id
 select c2.Id).FirstOrDefault()

In case of nested navigation property we expand the first one into a subquery, and add extra joins to the subquery, just like we did originally. Only the first navigation is "problematic", the following ones can be safely translated to joins
maumar added a commit that referenced this issue Oct 15, 2015
Problem:
We were incorrectly expanding navigations that appeared in the inner key selector of a join expression (right side).
Normally we expand nav props into additional join. E.g.:

from p in ctx.Payouts
join a in ctx.Assets on p.Good.Id equals a.Id
select p

converts to:

from p in ctx.Payouts
join g from ctx.Goods on p.Id equals g.Id
join a in ctx.Assets on g.Id equals a.Id
select p

However if navigation propery is in the inner key selector, like so:

from p in ctx.Payouts
join a in ctx.Assets on p.Id equals a.Good.Id
select p

we encounter chicken-and-egg problem:

from p in ctx.Payouts
join g in ctx.Good on a.Id equals g.Id // invalid, because a was not declared yet
join a in ctx.Assets on g.Id equals a.Id

or

from p in ctx.Payouts
join a in ctx.Assets on g.Id equals a.Id // invalid, because g was not declared yet
join g in ctx.Good on a.Id equals g.Id

Solution:

Some navigation properties can be translated into FKs, which removes the problem:

from c in Customers
join d in Details on c.Id equals d.Customer.Id
select c

can be translated into:

from c in Customers
join d in Details on c.Id equals c.CustomerId
select c

This can only be done for a subset of queries - join needs to be based on key property, FK must be pointing the right way, and key must not be composite.

For all other cases we translate this into a subquery:

from c in Customers
join d in Details on c.Id equals
(from c2 in Customers
 where c2.CustomerId equals d.Id
 select c2.Id).FirstOrDefault()

In case of nested navigation property we expand the first one into a subquery, and add extra joins to the subquery, just like we did originally. Only the first navigation is "problematic", the following ones can be safely translated to joins
maumar added a commit that referenced this issue Oct 15, 2015
Problem:
We were incorrectly expanding navigations that appeared in the inner key selector of a join expression (right side).
Normally we expand nav props into additional join. E.g.:

from p in ctx.Payouts
join a in ctx.Assets on p.Good.Id equals a.Id
select p

converts to:

from p in ctx.Payouts
join g from ctx.Goods on p.Id equals g.Id
join a in ctx.Assets on g.Id equals a.Id
select p

However if navigation propery is in the inner key selector, like so:

from p in ctx.Payouts
join a in ctx.Assets on p.Id equals a.Good.Id
select p

we encounter chicken-and-egg problem:

from p in ctx.Payouts
join g in ctx.Good on a.Id equals g.Id // invalid, because a was not declared yet
join a in ctx.Assets on g.Id equals a.Id

or

from p in ctx.Payouts
join a in ctx.Assets on g.Id equals a.Id // invalid, because g was not declared yet
join g in ctx.Good on a.Id equals g.Id

Solution:

Some navigation properties can be translated into FKs, which removes the problem:

from c in Customers
join d in Details on c.Id equals d.Customer.Id
select c

can be translated into:

from c in Customers
join d in Details on c.Id equals c.CustomerId
select c

This can only be done for a subset of queries - join needs to be based on key property, FK must be pointing the right way, and key must not be composite.

For all other cases we translate this into a subquery:

from c in Customers
join d in Details on c.Id equals
(from c2 in Customers
 where c2.CustomerId equals d.Id
 select c2.Id).FirstOrDefault()

In case of nested navigation property we expand the first one into a subquery, and add extra joins to the subquery, just like we did originally. Only the first navigation is "problematic", the following ones can be safely translated to joins
CR: Andrew
@maumar
Copy link
Contributor

maumar commented Oct 15, 2015

Fixed in c2b0179

@maumar maumar closed this as completed Oct 15, 2015
@maumar
Copy link
Contributor

maumar commented Oct 15, 2015

@AlexTo the fix is now in, I double checked the sample you provided and the bug is not happening on it anymore (and I verified it was happening on the bits prior to the fix)

@AlexTo
Copy link

AlexTo commented Oct 16, 2015

Thank you, so if I understand correctly, this fix will be included in RC1, but not in the beta8 recently released right?

@maumar
Copy link
Contributor

maumar commented Oct 16, 2015

@AlexTo yes, the fix didn't make it to beta8, so you need to wait till the next release or try our nightly builds

maumar added a commit that referenced this issue May 17, 2017
…ation inside a subquery inside join inner key selector

Problem was that navigation inside inner key selector of a JoinClause was always being rewritten to subquery (needed for #3103). However, we should only be doing this for "naked" navs - if the nav itself is inside a subquery it can be safely rewritten into a join.

Fix is to "reset" the state indicating whether we are inside join inner key selector every time we visit SubQuery.
maumar added a commit that referenced this issue May 17, 2017
…ation inside a subquery inside join inner key selector

Problem was that navigation inside inner key selector of a JoinClause was always being rewritten to subquery (needed for #3103). However, we should only be doing this for "naked" navs - if the nav itself is inside a subquery it can be safely rewritten into a join.

Fix is to "reset" the state indicating whether we are inside join inner key selector every time we visit SubQuery.
@ajcvickers ajcvickers added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Oct 15, 2022
@ajcvickers ajcvickers modified the milestones: 1.0.0-rc1, 1.0.0 Oct 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-bug
Projects
None yet
Development

No branches or pull requests

6 participants