/src/NHibernate.Test/Linq/ByMethod/JoinTests.cs

https://github.com/nhibernate/nhibernate-core · C# · 307 lines · 277 code · 30 blank · 0 comment · 17 complexity · bf7ddfa38bffe4d940b729e71377722e MD5 · raw file

  1. using System.Linq;
  2. using NHibernate.Linq;
  3. using NHibernate.Util;
  4. using NSubstitute;
  5. using NUnit.Framework;
  6. namespace NHibernate.Test.Linq.ByMethod
  7. {
  8. [TestFixture]
  9. public class JoinTests : LinqTestCase
  10. {
  11. [Test]
  12. public void MultipleLinqJoinsWithSameProjectionNames()
  13. {
  14. using (var sqlSpy = new SqlLogSpy())
  15. {
  16. var orders = db.Orders
  17. .Join(db.Orders, x => x.OrderId, x => x.OrderId - 1, (order, order1) => new { order, order1 })
  18. .Select(x => new { First = x.order, Second = x.order1 })
  19. .Join(db.Orders, x => x.First.OrderId, x => x.OrderId - 2, (order, order1) => new { order, order1 })
  20. .Select(x => new { FirstId = x.order.First.OrderId, SecondId = x.order.Second.OrderId, ThirdId = x.order1.OrderId })
  21. .ToList();
  22. var sql = sqlSpy.GetWholeLog();
  23. Assert.That(orders.Count, Is.EqualTo(828));
  24. Assert.IsTrue(orders.All(x => x.FirstId == x.SecondId - 1 && x.SecondId == x.ThirdId - 1));
  25. Assert.That(GetTotalOccurrences(sql, "inner join"), Is.EqualTo(2));
  26. }
  27. }
  28. [Test]
  29. public void MultipleLinqJoinsWithSameProjectionNamesWithLeftJoin()
  30. {
  31. using (var sqlSpy = new SqlLogSpy())
  32. {
  33. var orders = db.Orders
  34. .GroupJoin(db.Orders, x => x.OrderId, x => x.OrderId - 1, (order, order1) => new { order, order1 })
  35. .SelectMany(x => x.order1.DefaultIfEmpty(), (x, order1) => new { First = x.order, Second = order1 })
  36. .GroupJoin(db.Orders, x => x.First.OrderId, x => x.OrderId - 2, (order, order1) => new { order, order1 })
  37. .SelectMany(x => x.order1.DefaultIfEmpty(), (x, order1) => new
  38. {
  39. FirstId = x.order.First.OrderId,
  40. SecondId = (int?) x.order.Second.OrderId,
  41. ThirdId = (int?) order1.OrderId
  42. })
  43. .ToList();
  44. var sql = sqlSpy.GetWholeLog();
  45. Assert.That(orders.Count, Is.EqualTo(830));
  46. Assert.IsTrue(orders.Where(x => x.SecondId.HasValue && x.ThirdId.HasValue)
  47. .All(x => x.FirstId == x.SecondId - 1 && x.SecondId == x.ThirdId - 1));
  48. Assert.That(GetTotalOccurrences(sql, "left outer join"), Is.EqualTo(2));
  49. }
  50. }
  51. [Test]
  52. public void MultipleLinqJoinsWithSameProjectionNamesWithLeftJoinExtensionMethod()
  53. {
  54. using (var sqlSpy = new SqlLogSpy())
  55. {
  56. var orders = db.Orders
  57. .LeftJoin(db.Orders, x => x.OrderId, x => x.OrderId - 1, (order, order1) => new { order, order1 })
  58. .Select(x => new { First = x.order, Second = x.order1 })
  59. .LeftJoin(db.Orders, x => x.First.OrderId, x => x.OrderId - 2, (order, order1) => new { order, order1 })
  60. .Select(x => new
  61. {
  62. FirstId = x.order.First.OrderId,
  63. SecondId = (int?) x.order.Second.OrderId,
  64. ThirdId = (int?) x.order1.OrderId
  65. })
  66. .ToList();
  67. var sql = sqlSpy.GetWholeLog();
  68. Assert.That(orders.Count, Is.EqualTo(830));
  69. Assert.IsTrue(orders.Where(x => x.SecondId.HasValue && x.ThirdId.HasValue)
  70. .All(x => x.FirstId == x.SecondId - 1 && x.SecondId == x.ThirdId - 1));
  71. Assert.That(GetTotalOccurrences(sql, "left outer join"), Is.EqualTo(2));
  72. }
  73. }
  74. [Test]
  75. public void LeftJoinExtensionMethodWithMultipleKeyProperties()
  76. {
  77. using (var sqlSpy = new SqlLogSpy())
  78. {
  79. var orders = db.Orders
  80. .LeftJoin(
  81. db.Orders,
  82. x => new {x.OrderId, x.Customer.CustomerId},
  83. x => new {x.OrderId, x.Customer.CustomerId},
  84. (order, order1) => new {order, order1})
  85. .Select(x => new {FirstId = x.order.OrderId, SecondId = x.order1.OrderId})
  86. .ToList();
  87. var sql = sqlSpy.GetWholeLog();
  88. Assert.That(orders.Count, Is.EqualTo(830));
  89. Assert.IsTrue(orders.All(x => x.FirstId == x.SecondId));
  90. Assert.That(GetTotalOccurrences(sql, "left outer join"), Is.EqualTo(1));
  91. }
  92. }
  93. [Test]
  94. public void LeftJoinExtensionMethodWithOuterReferenceInWhereClauseOnly()
  95. {
  96. using (var sqlSpy = new SqlLogSpy())
  97. {
  98. var animals = db.Animals
  99. .LeftJoin(
  100. db.Mammals,
  101. x => x.Id,
  102. x => x.Id,
  103. (animal, mammal) => new { animal, mammal })
  104. .Where(x => x.mammal.SerialNumber.StartsWith("9"))
  105. .Select(x => new { SerialNumber = x.animal.SerialNumber })
  106. .ToList();
  107. var sql = sqlSpy.GetWholeLog();
  108. Assert.That(animals.Count, Is.EqualTo(1));
  109. Assert.That(GetTotalOccurrences(sql, "left outer join"), Is.EqualTo(1));
  110. }
  111. }
  112. [Test]
  113. public void LeftJoinExtensionMethodWithOuterReferenceInWhereClauseOnlyCount()
  114. {
  115. using (var sqlSpy = new SqlLogSpy())
  116. {
  117. var total = db.Orders
  118. .LeftJoin(
  119. db.OrderLines,
  120. x => x,
  121. x => x.Order,
  122. (order, line) => new { order, line })
  123. .Select(x => new { x.order.OrderId, x.line.Discount })
  124. .Count();
  125. var sql = sqlSpy.GetWholeLog();
  126. Assert.That(total, Is.EqualTo(2155));
  127. Assert.That(GetTotalOccurrences(sql, "left outer join"), Is.EqualTo(1));
  128. }
  129. }
  130. [KnownBug("GH-2739")]
  131. public void NestedLeftJoinExtensionMethodWithOuterReferenceInWhereClauseOnly()
  132. {
  133. using (var sqlSpy = new SqlLogSpy())
  134. {
  135. var innerAnimals = db.Animals
  136. .LeftJoin(
  137. db.Mammals,
  138. x => x.Id,
  139. x => x.Id,
  140. (animal, mammal) => new { animal, mammal })
  141. .Where(x => x.mammal.SerialNumber.StartsWith("9"))
  142. .Select(x=>x.animal);
  143. var animals = db.Animals
  144. .LeftJoin(
  145. innerAnimals,
  146. x => x.Id,
  147. x => x.Id,
  148. (animal, animal2) => new { animal, animal2 })
  149. .Select(x => new { SerialNumber = x.animal2.SerialNumber })
  150. .ToList();
  151. var sql = sqlSpy.GetWholeLog();
  152. Assert.That(animals.Count, Is.EqualTo(1));
  153. Assert.That(GetTotalOccurrences(sql, "left outer join"), Is.EqualTo(1));
  154. }
  155. }
  156. [Test]
  157. public void LeftJoinExtensionMethodWithNoUseOfOuterReference()
  158. {
  159. using (var sqlSpy = new SqlLogSpy())
  160. {
  161. var animals = db.Animals
  162. .LeftJoin(
  163. db.Mammals,
  164. x => x.Id,
  165. x => x.Id,
  166. (animal, mammal) => new { animal, mammal })
  167. .Select(x => x.animal)
  168. .ToList();
  169. var sql = sqlSpy.GetWholeLog();
  170. Assert.That(animals.Count, Is.EqualTo(6));
  171. Assert.That(GetTotalOccurrences(sql, "left outer join"), Is.EqualTo(6));
  172. }
  173. }
  174. [Test]
  175. public void LeftJoinExtensionMethodWithNoUseOfOuterReferenceCount()
  176. {
  177. using (var sqlSpy = new SqlLogSpy())
  178. {
  179. var total = db.Animals
  180. .LeftJoin(
  181. db.Mammals,
  182. x => x.Id,
  183. x => x.Id,
  184. (animal, mammal) => new {animal, mammal})
  185. .Select(x => x.animal)
  186. .Count();
  187. var sql = sqlSpy.GetWholeLog();
  188. Assert.That(total, Is.EqualTo(6));
  189. Assert.That(GetTotalOccurrences(sql, "left outer join"), Is.EqualTo(1));
  190. }
  191. }
  192. [Test]
  193. public void LeftJoinExtensionMethodWithOuterReferenceInOrderByClauseOnly()
  194. {
  195. using (var sqlSpy = new SqlLogSpy())
  196. {
  197. var animals = db.Animals
  198. .LeftJoin(
  199. db.Mammals,
  200. x => x.Id,
  201. x => x.Id,
  202. (animal, mammal) => new { animal, mammal })
  203. .OrderBy(x => x.mammal.SerialNumber ?? "z")
  204. .Select(x => new { SerialNumber = x.animal.SerialNumber })
  205. .ToList();
  206. var sql = sqlSpy.GetWholeLog();
  207. Assert.That(animals.Count, Is.EqualTo(6));
  208. Assert.That(animals[0].SerialNumber, Is.EqualTo("1121"));
  209. Assert.That(GetTotalOccurrences(sql, "left outer join"), Is.EqualTo(1));
  210. }
  211. }
  212. [Test]
  213. public void LeftJoinExtensionMethodWithOuterReferenceInOrderByClauseOnlyCount()
  214. {
  215. using (var sqlSpy = new SqlLogSpy())
  216. {
  217. var total = db.Animals
  218. .LeftJoin(
  219. db.Mammals,
  220. x => x.Id,
  221. x => x.Id,
  222. (animal, mammal) => new {animal, mammal})
  223. .OrderBy(x => x.mammal.SerialNumber ?? "z")
  224. .Select(x => new {SerialNumber = x.animal.SerialNumber})
  225. .Count();
  226. var sql = sqlSpy.GetWholeLog();
  227. Assert.That(total, Is.EqualTo(6));
  228. Assert.That(GetTotalOccurrences(sql, "left outer join"), Is.EqualTo(1));
  229. }
  230. }
  231. [TestCase(false)]
  232. [TestCase(true)]
  233. public void CrossJoinWithPredicateInWhereStatement(bool useCrossJoin)
  234. {
  235. if (useCrossJoin && !Dialect.SupportsCrossJoin)
  236. {
  237. Assert.Ignore("Dialect does not support cross join.");
  238. }
  239. using (var substitute = SubstituteDialect())
  240. using (var sqlSpy = new SqlLogSpy())
  241. {
  242. ClearQueryPlanCache();
  243. substitute.Value.SupportsCrossJoin.Returns(useCrossJoin);
  244. var result = (from o in db.Orders
  245. from o2 in db.Orders.Where(x => x.Freight > 50)
  246. where (o.OrderId == o2.OrderId + 1) || (o.OrderId == o2.OrderId - 1)
  247. select new { o.OrderId, OrderId2 = o2.OrderId }).ToList();
  248. var sql = sqlSpy.GetWholeLog();
  249. Assert.That(result.Count, Is.EqualTo(720));
  250. Assert.That(sql, Does.Contain(useCrossJoin ? "cross join" : "inner join"));
  251. Assert.That(GetTotalOccurrences(sql, "inner join"), Is.EqualTo(useCrossJoin ? 0 : 1));
  252. }
  253. }
  254. [Test]
  255. public void CanJoinOnEntityWithSubclasses()
  256. {
  257. var result = (from o in db.Animals
  258. from o2 in db.Animals.Where(x => x.BodyWeight > 50)
  259. select new {o, o2}).Take(1).ToList();
  260. }
  261. [Test(Description = "GH-2580")]
  262. public void CanInnerJoinOnSubclassWithBaseTableReferenceInOnClause()
  263. {
  264. var result = (from o in db.Animals
  265. join o2 in db.Mammals on o.BodyWeight equals o2.BodyWeight
  266. select new { o, o2 }).Take(1).ToList();
  267. }
  268. [Test(Description = "GH-2805")]
  269. public void CanJoinOnInterface()
  270. {
  271. var result = db.IUsers.Join(db.IUsers,
  272. u => u.Id,
  273. iu => iu.Id,
  274. (u, iu) => iu.Name).Take(1).ToList();
  275. }
  276. }
  277. }