Skip to content

Support caching queries with autodiscovered types #3184

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

Merged
merged 24 commits into from
Oct 27, 2022
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
c59e60e
Support caching queries with autodiscovered types
fredericDelaporte Oct 2, 2022
94aa1de
Fix a typo
fredericDelaporte Oct 16, 2022
0bf7921
Generate async files
github-actions[bot] Oct 16, 2022
261ac75
Add the aliases directly into cached data
fredericDelaporte Oct 16, 2022
3f28ad9
Generate async files
github-actions[bot] Oct 16, 2022
8228b04
Minimize the change
fredericDelaporte Oct 16, 2022
81c1b18
Generate async files
github-actions[bot] Oct 16, 2022
b38af02
Fix whitespaces
fredericDelaporte Oct 16, 2022
b7bea83
Fix some tests
fredericDelaporte Oct 16, 2022
300ccee
Generate async files
github-actions[bot] Oct 16, 2022
c355c34
Simplify code
fredericDelaporte Oct 18, 2022
ec0c5a0
Implement breaking change minimizing suggestions
fredericDelaporte Oct 23, 2022
fda5a75
Generate async files
github-actions[bot] Oct 23, 2022
ee43157
Fix some more metadata reserved slots changes
fredericDelaporte Oct 23, 2022
594d694
Generate async files
github-actions[bot] Oct 23, 2022
b0a2fd2
Fix a regression fromminimizing breaking change
fredericDelaporte Oct 23, 2022
8bbd84e
Add a JsonSerializer test and fix it
fredericDelaporte Oct 23, 2022
8232bcf
Simplify metadata extraction
fredericDelaporte Oct 23, 2022
c07c6af
Add test for multi-columns cached queries
fredericDelaporte Oct 23, 2022
4b1d56b
Fix a typo
fredericDelaporte Oct 23, 2022
ae9c660
Apply code suggestions
fredericDelaporte Oct 24, 2022
72ee45c
Merge branch 'master' into GH3169
fredericDelaporte Oct 25, 2022
50078f0
Simplify code. Fix comment. Cleanup whitespaces
hazzik Oct 27, 2022
b165a88
Merge branch 'master' into GH3169
hazzik Oct 27, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/NHibernate.Test/Async/QueryTest/MultiCriteriaFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@ public async Task CanGetMultiQueryFromSecondLevelCacheAsync()

var cacheHashtable = MultipleQueriesFixtureAsync.GetHashTableUsedAsQueryCache(Sfi);
var cachedListEntry = (IList)new ArrayList(cacheHashtable.Values)[0];
var cachedQuery = (IList)cachedListEntry[1];
// The first element is a timestamp, the second is aliases, then only we have the cached data.
var cachedQuery = (IList)cachedListEntry[2] ?? throw new InvalidOperationException("Cached data is null");

var firstQueryResults = (IList)cachedQuery[0];
firstQueryResults.Clear();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ public async Task CanGetMultiQueryFromSecondLevelCacheAsync()

var cacheHashtable = MultipleQueriesFixtureAsync.GetHashTableUsedAsQueryCache(Sfi);
var cachedListEntry = (IList)new ArrayList(cacheHashtable.Values)[0];
var cachedQuery = (IList)cachedListEntry[1];
// The first element is a timestamp, the second is aliases, then only we have the cached data.
var cachedQuery = (IList) cachedListEntry[2] ?? throw new InvalidOperationException("Cached data is null");

var firstQueryResults = (IList)cachedQuery[0];
firstQueryResults.Clear();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ public async Task CanGetMultiQueryFromSecondLevelCacheAsync()

var cacheHashtable = GetHashTableUsedAsQueryCache(Sfi);
var cachedListEntry = (IList)new ArrayList(cacheHashtable.Values)[0];
var cachedQuery = (IList)cachedListEntry[1];
// The first element is a timestamp, the second is aliases, then only we have the cached data.
var cachedQuery = (IList) cachedListEntry[2] ?? throw new InvalidOperationException("Cached data is null");

var firstQueryResults = (IList)cachedQuery[0];
firstQueryResults.Clear();
Expand Down
116 changes: 66 additions & 50 deletions src/NHibernate.Test/Async/SqlTest/Query/NativeSQLQueriesFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@

using System.Collections;
using System.Linq;
using NHibernate.Criterion;
using NHibernate.Multi;
using NHibernate.Transform;
using NUnit.Framework;
using NHibernate.Criterion;

namespace NHibernate.Test.SqlTest.Query
{
Expand Down Expand Up @@ -62,6 +63,20 @@ protected override string MappingsAssembly
get { return "NHibernate.Test"; }
}

protected override void OnTearDown()
{
using (var session = OpenSession())
using (var transaction = session.BeginTransaction())
{
session.CreateQuery("delete from Employment").ExecuteUpdate();
session.CreateQuery("delete from System.Object").ExecuteUpdate();

transaction.Commit();
}

Sfi.QueryCache.Clear();
}

[Test]
public async Task FailOnNoAddEntityOrScalarAsync()
{
Expand Down Expand Up @@ -136,18 +151,6 @@ public async Task SQLQueryInterfaceAsync()
await (t.CommitAsync());
s.Close();
}

using (var s = OpenSession())
using (var t = s.BeginTransaction())
{
await (s.DeleteAsync(emp));
await (s.DeleteAsync(gavin));
await (s.DeleteAsync(ifa));
await (s.DeleteAsync(jboss));

await (t.CommitAsync());
s.Close();
}
}

[Test]
Expand Down Expand Up @@ -202,18 +205,6 @@ public async Task SQLQueryInterfaceCacheableAsync()
await (t.CommitAsync());
s.Close();
}

using (var s = OpenSession())
using (var t = s.BeginTransaction())
{
await (s.DeleteAsync(emp));
await (s.DeleteAsync(gavin));
await (s.DeleteAsync(ifa));
await (s.DeleteAsync(jboss));

await (t.CommitAsync());
s.Close();
}
}

[Test(Description = "GH-2904")]
Expand Down Expand Up @@ -270,20 +261,11 @@ Task<IList> GetCacheableSqlQueryResultsAsync()
Assert.That(Sfi.Statistics.QueryCacheHitCount, Is.EqualTo(1), "results are expected from cache");
}
}

using (var s = OpenSession())
using (var t = s.BeginTransaction())
{
await (s.DeleteAsync(emp));
await (s.DeleteAsync(gavin));
await (s.DeleteAsync(ifa));
await (s.DeleteAsync(jboss));
await (t.CommitAsync());
}
}

class ResultDto
{
public long orgId { get; set; }
public string regionCode { get; set; }
}

Expand Down Expand Up @@ -312,23 +294,64 @@ async Task AssertQueryAsync(bool fromCache)
.ListAsync());
await (t.CommitAsync());

Assert.AreEqual(1, l.Count);
//TODO: Uncomment if we properly fix caching auto discovery type queries with transformers
// var msg = "results are expected from " + (fromCache ? "cache" : "DB");
// Assert.That(Sfi.Statistics.QueryCacheMissCount, Is.EqualTo(fromCache ? 0 : 1), msg);
// Assert.That(Sfi.Statistics.QueryCacheHitCount, Is.EqualTo(fromCache ? 1 : 0), msg);
Assert.That(l.Count, Is.EqualTo(1));
var msg = "Results are expected from " + (fromCache ? "cache" : "DB");
Assert.That(Sfi.Statistics.QueryCacheMissCount, Is.EqualTo(fromCache ? 0 : 1), msg);
Assert.That(Sfi.Statistics.QueryCacheHitCount, Is.EqualTo(fromCache ? 1 : 0), msg);
}
}

await (AssertQueryAsync(false));
await (AssertQueryAsync(true));
}

using (var s = OpenSession())
using (var t = s.BeginTransaction())
[Test(Description = "GH-3169")]
public async Task CacheableScalarSQLMultiQueryWithTransformerAsync()
{
Organization ifa = new Organization("IFA");

using (ISession s = OpenSession())
using (ITransaction t = s.BeginTransaction())
{
await (s.DeleteAsync(ifa));
await (s.SaveAsync(ifa));
await (t.CommitAsync());
}

async Task AssertQueryAsync(bool fromCache)
{
using (var s = OpenSession())
using (var t = s.BeginTransaction())
using (EnableStatisticsScope())
{
var q1 = s.CreateSQLQuery("select org.NAME as regionCode from ORGANIZATION org")
.AddScalar("regionCode", NHibernateUtil.String)
.SetResultTransformer(Transformers.AliasToBean<ResultDto>())
.SetCacheable(true);
var q2 = s.CreateSQLQuery("select org.ORGID as orgId from ORGANIZATION org")
.AddScalar("orgId", NHibernateUtil.Int64)
.SetResultTransformer(Transformers.AliasToBean<ResultDto>())
.SetCacheable(true);

var batch = s.CreateQueryBatch();
batch.Add<ResultDto>(q1);
batch.Add<ResultDto>(q2);
await (batch.ExecuteAsync());

var l1 = await (batch.GetResultAsync<ResultDto>(0));
var l2 = await (batch.GetResultAsync<ResultDto>(1));

await (t.CommitAsync());

Assert.That(l1.Count, Is.EqualTo(1), "Unexpected results count for the first query.");
Assert.That(l2.Count, Is.EqualTo(1), "Unexpected results count for the second query.");
var msg = "Results are expected from " + (fromCache ? "cache" : "DB");
Assert.That(Sfi.Statistics.QueryCacheMissCount, Is.EqualTo(fromCache ? 0 : 2), msg);
Assert.That(Sfi.Statistics.QueryCacheHitCount, Is.EqualTo(fromCache ? 2 : 0), msg);
}
}

await (AssertQueryAsync(false));
await (AssertQueryAsync(true));
}

[Test]
Expand Down Expand Up @@ -356,11 +379,6 @@ public async Task ResultSetMappingDefinitionAsync()
.ListAsync());
Assert.AreEqual(l.Count, 1);

await (s.DeleteAsync(emp));
await (s.DeleteAsync(gavin));
await (s.DeleteAsync(ifa));
await (s.DeleteAsync(jboss));

await (t.CommitAsync());
s.Close();
}
Expand Down Expand Up @@ -443,8 +461,6 @@ public async Task ScalarValuesAsync()
Assert.AreEqual(o[1], "JBoss");
Assert.AreEqual(o[0], idJBoss);

await (s.DeleteAsync(ifa));
await (s.DeleteAsync(jboss));
await (t.CommitAsync());
s.Close();
}
Expand Down
3 changes: 2 additions & 1 deletion src/NHibernate.Test/QueryTest/MultiCriteriaFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ public void CanGetMultiQueryFromSecondLevelCache()

var cacheHashtable = MultipleQueriesFixture.GetHashTableUsedAsQueryCache(Sfi);
var cachedListEntry = (IList)new ArrayList(cacheHashtable.Values)[0];
var cachedQuery = (IList)cachedListEntry[1];
// The first element is a timestamp, the second is aliases, then only we have the cached data.
var cachedQuery = (IList)cachedListEntry[2] ?? throw new InvalidOperationException("Cached data is null");

var firstQueryResults = (IList)cachedQuery[0];
firstQueryResults.Clear();
Expand Down
3 changes: 2 additions & 1 deletion src/NHibernate.Test/QueryTest/MultipleMixedQueriesFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ public void CanGetMultiQueryFromSecondLevelCache()

var cacheHashtable = MultipleQueriesFixture.GetHashTableUsedAsQueryCache(Sfi);
var cachedListEntry = (IList)new ArrayList(cacheHashtable.Values)[0];
var cachedQuery = (IList)cachedListEntry[1];
// The first element is a timestamp, the second is aliases, then only we have the cached data.
var cachedQuery = (IList) cachedListEntry[2] ?? throw new InvalidOperationException("Cached data is null");

var firstQueryResults = (IList)cachedQuery[0];
firstQueryResults.Clear();
Expand Down
3 changes: 2 additions & 1 deletion src/NHibernate.Test/QueryTest/MultipleQueriesFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ public void CanGetMultiQueryFromSecondLevelCache()

var cacheHashtable = GetHashTableUsedAsQueryCache(Sfi);
var cachedListEntry = (IList)new ArrayList(cacheHashtable.Values)[0];
var cachedQuery = (IList)cachedListEntry[1];
// The first element is a timestamp, the second is aliases, then only we have the cached data.
var cachedQuery = (IList) cachedListEntry[2] ?? throw new InvalidOperationException("Cached data is null");

var firstQueryResults = (IList)cachedQuery[0];
firstQueryResults.Clear();
Expand Down
Loading