Skip to content

Commit

Permalink
Fix Contains subquery with parameter (#3220)
Browse files Browse the repository at this point in the history
Fixes #3218
  • Loading branch information
bahusoid authored Jan 18, 2023
1 parent cc13153 commit ac5e2b6
Show file tree
Hide file tree
Showing 4 changed files with 236 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by AsyncGenerator.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------


using System;
using System.Linq;
using NHibernate.Cfg.MappingSchema;
using NHibernate.Mapping.ByCode;
using NUnit.Framework;
using NHibernate.Linq;

namespace NHibernate.Test.NHSpecificTest.GH3218
{
using System.Threading.Tasks;
[TestFixture]
public class ContainsParameterFixtureAsync : TestCaseMappingByCode
{
protected override HbmMapping GetMappings()
{
var mapper = new ModelMapper();
mapper.Class<Child>(rc =>
{
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
rc.Property(x => x.Name);
rc.Component(
x => x.Component,
ekm =>
{
ekm.Property(ek => ek.Id1);
ekm.Property(ek => ek.Id2);
});
});
mapper.Class<Entity>(rc =>
{
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
rc.Property(x => x.Name);
rc.Bag(x => x.List, m => { }, r => r.OneToMany());
});

return mapper.CompileMappingForAllExplicitlyAddedEntities();
}

[Test]
public async Task ContainsOnIdAsync()
{
using (var session = OpenSession())
{
Guid clientId = Guid.NewGuid();
await (session.Query<Entity>().Where(x => x.List.Select(l => l.Id).Contains(clientId)).ToListAsync());
}
}

[Test]
public async Task ContainsOnNameWithInnerSubqueryAsync()
{
using (var session = OpenSession())
{
var clientId = "aa";
await (session.Query<Entity>().Where(x =>
x.List.Where(l => session.Query<Entity>().Any(s => s.Name == l.Name)).Select(l => l.Name)
.Contains(clientId)).ToListAsync());
}
}

[Test]
public async Task ContainsOnEntityAsync()
{
using (var session = OpenSession())
{
var client = await (session.LoadAsync<Child>(Guid.NewGuid()));
await (session.Query<Entity>().Where(x => x.List.Contains(client)).ToListAsync());
}
}

[Test]
public async Task ContainsOnNameAsync()
{
using (var session = OpenSession())
{
var client = "aaa";
await (session.Query<Entity>().Where(x => x.List.Select(l => l.Name).Contains(client)).ToListAsync());
}
}

[Test]
public async Task ContainsOnComponentAsync()
{
using (var session = OpenSession())
{
var client = new CompositeKey() { Id1 = 1, Id2 = 2 };
await (session.Query<Entity>().Where(x => x.List.Select(l => l.Component).Contains(client)).ToListAsync());
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
using System;
using System.Linq;
using NHibernate.Cfg.MappingSchema;
using NHibernate.Mapping.ByCode;
using NUnit.Framework;

namespace NHibernate.Test.NHSpecificTest.GH3218
{
[TestFixture]
public class ContainsParameterFixture : TestCaseMappingByCode
{
protected override HbmMapping GetMappings()
{
var mapper = new ModelMapper();
mapper.Class<Child>(rc =>
{
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
rc.Property(x => x.Name);
rc.Component(
x => x.Component,
ekm =>
{
ekm.Property(ek => ek.Id1);
ekm.Property(ek => ek.Id2);
});
});
mapper.Class<Entity>(rc =>
{
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
rc.Property(x => x.Name);
rc.Bag(x => x.List, m => { }, r => r.OneToMany());
});

return mapper.CompileMappingForAllExplicitlyAddedEntities();
}

[Test]
public void ContainsOnId()
{
using (var session = OpenSession())
{
Guid clientId = Guid.NewGuid();
session.Query<Entity>().Where(x => x.List.Select(l => l.Id).Contains(clientId)).ToList();
}
}

[Test]
public void ContainsOnNameWithInnerSubquery()
{
using (var session = OpenSession())
{
var clientId = "aa";
session.Query<Entity>().Where(x =>
x.List.Where(l => session.Query<Entity>().Any(s => s.Name == l.Name)).Select(l => l.Name)
.Contains(clientId)).ToList();
}
}

[Test]
public void ContainsOnEntity()
{
using (var session = OpenSession())
{
var client = session.Load<Child>(Guid.NewGuid());
session.Query<Entity>().Where(x => x.List.Contains(client)).ToList();
}
}

[Test]
public void ContainsOnName()
{
using (var session = OpenSession())
{
var client = "aaa";
session.Query<Entity>().Where(x => x.List.Select(l => l.Name).Contains(client)).ToList();
}
}

[Test]
public void ContainsOnComponent()
{
using (var session = OpenSession())
{
var client = new CompositeKey() { Id1 = 1, Id2 = 2 };
session.Query<Entity>().Where(x => x.List.Select(l => l.Component).Contains(client)).ToList();
}
}
}
}
41 changes: 41 additions & 0 deletions src/NHibernate.Test/NHSpecificTest/GH3218/Entity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;

namespace NHibernate.Test.NHSpecificTest.GH3218
{
public class Entity
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<Child> List { get; set; }
}

public class Child
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
public virtual CompositeKey Component { get; set; }
}

public class CompositeKey
{
public int Id1 { get; set; }
public int Id2 { get; set; }

public override bool Equals(object obj)
{
var key = obj as CompositeKey;
return key != null
&& Id1 == key.Id1
&& Id2 == key.Id2;
}

public override int GetHashCode()
{
var hashCode = -1596524975;
hashCode = hashCode * -1521134295 + Id1.GetHashCode();
hashCode = hashCode * -1521134295 + Id2.GetHashCode();
return hashCode;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Linq.Expressions;
using NHibernate.Hql.Ast;
using NHibernate.Hql.Ast.ANTLR;
using Remotion.Linq.Clauses.ResultOperators;

namespace NHibernate.Linq.Visitors.ResultOperatorProcessors
Expand Down Expand Up @@ -38,7 +36,7 @@ public void Process(ContainsResultOperator resultOperator, QueryModelVisitor que
if (itemExpression is HqlParameter)
{
tree.AddWhereClause(tree.TreeBuilder.Equality(
tree.TreeBuilder.Ident(GetFromAlias(tree.Root).AstNode.Text),
GetSelectExpression(tree.Root),
itemExpression));
ProcessAny.Process(tree);
}
Expand All @@ -54,9 +52,9 @@ private static HqlRange GetFromRangeClause(HqlTreeNode node)
return node.NodesPreOrder.OfType<HqlRange>().First();
}

private static HqlAlias GetFromAlias(HqlTreeNode node)
private static HqlExpression GetSelectExpression(HqlTreeNode node)
{
return node.NodesPreOrder.Single(n => n is HqlRange).Children.Single(n => n is HqlAlias) as HqlAlias;
return node.NodesPreOrder.First(x => x.AstNode.Type == HqlSqlWalker.SELECT).Children.Single() as HqlExpression;
}

private static bool IsEmptyList(HqlParameter source, VisitorParameters parameters)
Expand Down

0 comments on commit ac5e2b6

Please sign in to comment.