blob: dbeeb51f3a654aea087a88dee73d339223b77fc3 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace Apache.Ignite.Tests.Linq;
using System;
using System.Linq;
using NUnit.Framework;
/// <summary>
/// Linq JOINs tests.
/// </summary>
public partial class LinqTests
{
[Test]
public void TestSelfJoin()
{
var query1 = PocoView.AsQueryable().Where(x => x.Key > 4);
var query2 = PocoView.AsQueryable().Where(x => x.Key < 6);
var joinQuery = query1.Join(query2, a => a.Key, b => b.Key, (a, b) => new
{
Key1 = a.Key,
Val1 = a.Val,
Key2 = b.Key,
Val2 = b.Val
});
var res = joinQuery.Single();
Assert.AreEqual(5, res.Key1);
Assert.AreEqual(5, res.Key2);
Assert.AreEqual("v-5", res.Val1);
Assert.AreEqual("v-5", res.Val2);
StringAssert.Contains(
"select _T0.KEY, _T0.VAL, _T1.KEY, _T1.VAL " +
"from PUBLIC.TBL1 as _T0 " +
"inner join (select * from PUBLIC.TBL1 as _T2 where (_T2.KEY < ?) ) as _T1 on (_T1.KEY = _T0.KEY)",
joinQuery.ToString());
}
[Test]
public void TestTwoTableJoin()
{
var query1 = PocoView.AsQueryable();
var query2 = PocoIntView.AsQueryable();
var joinQuery = query1.Join(
inner: query2,
outerKeySelector: a => a.Key,
innerKeySelector: b => b.Key,
resultSelector: (a, b) => new
{
Id = a.Key,
Price = b.Val
})
.Where(x => x.Id > 3)
.OrderBy(x => x.Id)
.Take(2);
var res = joinQuery.ToList();
Assert.AreEqual(2, res.Count);
Assert.AreEqual(4, res[0].Id);
Assert.AreEqual(400, res[0].Price);
StringAssert.Contains(
"select _T0.KEY, _T1.VAL " +
"from PUBLIC.TBL1 as _T0 " +
"inner join PUBLIC.TBL_INT32 as _T1 on (cast(_T1.KEY as bigint) = _T0.KEY) " +
"where (_T0.KEY > ?) " +
"order by _T0.KEY asc " +
"limit ?",
joinQuery.ToString());
}
[Test]
public void TestThreeTableJoin()
{
var query1 = PocoView.AsQueryable();
var query2 = PocoIntView.AsQueryable();
var query3 = PocoLongView.AsQueryable();
var joinQuery = query1.Join(
inner: query2,
outerKeySelector: a => a.Key,
innerKeySelector: b => b.Key,
resultSelector: (a, b) => new
{
Id = a.Key,
Price = b.Val
})
.Join(
inner: query3,
outerKeySelector: a => a.Id,
innerKeySelector: b => b.Key,
resultSelector: (a, b) => new
{
a.Id,
a.Price,
Price2 = b.Val
})
.Where(x => x.Id > 3)
.OrderBy(x => x.Id);
var res = joinQuery.First();
Assert.AreEqual(4, res.Id);
Assert.AreEqual(400, res.Price);
Assert.AreEqual(8, res.Price2);
StringAssert.Contains(
"select _T0.KEY, _T1.VAL, _T2.VAL " +
"from PUBLIC.TBL1 as _T0 " +
"inner join PUBLIC.TBL_INT32 as _T1 on (cast(_T1.KEY as bigint) = _T0.KEY) " +
"inner join PUBLIC.TBL_INT64 as _T2 on (_T2.KEY = _T0.KEY)",
joinQuery.ToString());
}
[Test]
public void TestTwoTableJoinQuerySyntax()
{
var query1 = PocoView.AsQueryable();
var query2 = PocoIntView.AsQueryable();
var joinQuery =
from a in query1
join b in query2
on a.Key equals b.Key
where b.Key > 3
orderby b.Key
select new { Id = a.Key, Price = b.Val };
var res = joinQuery.Take(1).ToList();
Assert.AreEqual(1, res.Count);
Assert.AreEqual(4, res[0].Id);
Assert.AreEqual(400, res[0].Price);
StringAssert.Contains(
"select _T0.KEY, _T1.VAL " +
"from PUBLIC.TBL1 as _T0 " +
"inner join PUBLIC.TBL_INT32 as _T1 on (cast(_T1.KEY as bigint) = _T0.KEY) " +
"where (_T1.KEY > ?) " +
"order by _T1.KEY asc",
joinQuery.ToString());
}
[Test]
public void TestJoinAsMultipleFrom()
{
var query1 = PocoView.AsQueryable();
var query2 = PocoLongView.AsQueryable();
var joinQuery =
from a in query1
from b in query2
where a.Key == b.Key && a.Key > 3
orderby b.Key
select new { Id = a.Key, Price = b.Val };
var res = joinQuery.Take(1).ToList();
Assert.AreEqual(1, res.Count);
Assert.AreEqual(4, res[0].Id);
Assert.AreEqual(8, res[0].Price);
StringAssert.Contains(
"select _T0.KEY, _T1.VAL from PUBLIC.TBL1 as _T0 , PUBLIC.TBL_INT64 as _T1 " +
"where ((_T0.KEY IS NOT DISTINCT FROM _T1.KEY) and (_T0.KEY > ?))",
joinQuery.ToString());
}
[Test]
public void TestMultiKeyJoin()
{
var query1 = PocoIntView.AsQueryable();
var query2 = PocoIntView.AsQueryable();
var joinQuery = query1.Join(
inner: query2,
outerKeySelector: a => new { a.Key, a.Val },
innerKeySelector: b => new { b.Key, b.Val },
resultSelector: (a, b) => new
{
Id = b.Key,
Price = a.Val
})
.Where(x => x.Id > 1 && x.Price > 0)
.OrderBy(x => x.Id);
var res = joinQuery.First();
Assert.AreEqual(2, res.Id);
Assert.AreEqual(200, res.Price);
StringAssert.Contains(
"select _T0.KEY, _T1.VAL " +
"from PUBLIC.TBL_INT32 as _T1 " +
"inner join PUBLIC.TBL_INT32 as _T0 on (_T0.KEY = _T1.KEY and _T0.VAL = _T1.VAL)",
joinQuery.ToString());
}
[Test]
public void TestOuterJoinValueTypeKey()
{
var query1 = PocoIntView.AsQueryable(); // Sequential keys.
var query2 = PocoShortView.AsQueryable(); // Sequential keys times 2.
var joinQuery = query1.Join(
inner: query2.DefaultIfEmpty(),
outerKeySelector: a => a.Key,
innerKeySelector: b => b!.Key,
resultSelector: (a, b) => new
{
Id = a.Key,
Price = b!.Val!.Value
})
.OrderBy(x => x.Id);
var res = joinQuery.ToList();
Assert.AreEqual(Count, res.Count);
Assert.AreEqual(1, res[1].Id);
Assert.AreEqual(0, res[1].Price);
Assert.AreEqual(2, res[2].Id);
Assert.AreEqual(2, res[2].Price);
Assert.AreEqual(3, res[3].Id);
Assert.AreEqual(0, res[3].Price);
StringAssert.Contains(
"select _T0.KEY, cast(_T1.VAL as smallint) as PRICE " +
"from PUBLIC.TBL_INT32 as _T0 " +
"left outer join (select * from PUBLIC.TBL_INT16 as _T2 ) as _T1 " +
"on (cast(_T1.KEY as int) = _T0.KEY)",
joinQuery.ToString());
}
[Test]
public void TestOuterJoinReferenceTypeKey()
{
var query1 = PocoView.AsQueryable(); // Sequential values.
var query2 = PocoStringView.AsQueryable(); // Sequential values times 2.
var joinQuery = query1.Join(
inner: query2.DefaultIfEmpty(),
outerKeySelector: a => a.Val,
innerKeySelector: b => b!.Val,
resultSelector: (a, b) => new
{
Id = a.Key,
Id2 = b!.Key,
Name = b.Val
})
.OrderBy(x => x.Id);
var res = joinQuery.ToList();
Assert.AreEqual(Count, res.Count);
Assert.AreEqual(1, res[1].Id);
Assert.AreEqual(null, res[1].Name);
Assert.AreEqual(2, res[2].Id);
Assert.AreEqual("v-2", res[2].Name);
Assert.AreEqual(3, res[3].Id);
Assert.AreEqual(null, res[3].Name);
StringAssert.Contains(
"select _T0.KEY, _T1.KEY, _T1.VAL " +
"from PUBLIC.TBL1 as _T0 " +
"left outer join (select * from PUBLIC.TBL_STRING as _T2 ) as _T1 on (_T1.VAL = _T0.VAL) " +
"order by _T0.KEY asc",
joinQuery.ToString());
}
[Test]
public void TestLocalCollectionJoinThrowsNotSupportedException()
{
var query1 = PocoIntView.AsQueryable(); // Sequential keys.
var query2 = new[] { 2, 4, 6 };
var joinQuery = query1.Join(
inner: query2,
outerKeySelector: a => a.Key,
innerKeySelector: b => b,
resultSelector: (a, b) => new
{
Id = a.Key,
Price = a.Val
})
.OrderBy(x => x.Id);
// ReSharper disable once ReturnValueOfPureMethodIsNotUsed
var ex = Assert.Throws<NotSupportedException>(() => joinQuery.ToList());
StringAssert.Contains("Local collection joins are not supported, try `.Contains()` instead:", ex!.Message);
}
}