Skip to content

Commit cf6a810

Browse files
committed
Regenerate code
1 parent 8687052 commit cf6a810

File tree

6 files changed

+336
-12
lines changed

6 files changed

+336
-12
lines changed

src/NHibernate/Async/Cache/Entry/CollectionCacheEntry.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ namespace NHibernate.Cache.Entry
99
[System.CodeDom.Compiler.GeneratedCode("AsyncGenerator", "1.0.0")]
1010
public partial class CollectionCacheEntry
1111
{
12+
public static async Task<CollectionCacheEntry> CreateAsync(IPersistentCollection collection, ICollectionPersister persister)
13+
{
14+
return new CollectionCacheEntry(await (collection.DisassembleAsync(persister)));
15+
}
16+
1217
public virtual async Task AssembleAsync(IPersistentCollection collection, ICollectionPersister persister, object owner)
1318
{
1419
await (collection.InitializeFromCacheAsync(persister, state, owner));
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
using System.Collections;
2+
using System.Collections.Generic;
3+
using System.Data.Common;
4+
using System.Diagnostics;
5+
using NHibernate.Cache;
6+
using NHibernate.Cache.Entry;
7+
using NHibernate.Collection;
8+
using NHibernate.Impl;
9+
using NHibernate.Persister.Collection;
10+
using System.Threading.Tasks;
11+
12+
namespace NHibernate.Engine.Loading
13+
{
14+
[System.CodeDom.Compiler.GeneratedCode("AsyncGenerator", "1.0.0")]
15+
public partial class CollectionLoadContext
16+
{
17+
/// <summary>
18+
/// Finish the process of collection-loading for this bound result set. Mainly this
19+
/// involves cleaning up resources and notifying the collections that loading is
20+
/// complete.
21+
/// </summary>
22+
/// <param name = "persister">The persister for which to complete loading. </param>
23+
public async Task EndLoadingCollectionsAsync(ICollectionPersister persister)
24+
{
25+
if (!loadContexts.HasLoadingCollectionEntries && (localLoadingCollectionKeys.Count == 0))
26+
{
27+
return;
28+
}
29+
30+
// in an effort to avoid concurrent-modification-exceptions (from
31+
// potential recursive calls back through here as a result of the
32+
// eventual call to PersistentCollection#endRead), we scan the
33+
// internal loadingCollections map for matches and store those matches
34+
// in a temp collection. the temp collection is then used to "drive"
35+
// the #endRead processing.
36+
List<CollectionKey> toRemove = new List<CollectionKey>();
37+
List<LoadingCollectionEntry> matches = new List<LoadingCollectionEntry>();
38+
foreach (CollectionKey collectionKey in localLoadingCollectionKeys)
39+
{
40+
ISessionImplementor session = LoadContext.PersistenceContext.Session;
41+
LoadingCollectionEntry lce = loadContexts.LocateLoadingCollectionEntry(collectionKey);
42+
if (lce == null)
43+
{
44+
log.Warn("In CollectionLoadContext#endLoadingCollections, localLoadingCollectionKeys contained [" + collectionKey + "], but no LoadingCollectionEntry was found in loadContexts");
45+
}
46+
else if (lce.ResultSet == resultSet && lce.Persister == persister)
47+
{
48+
matches.Add(lce);
49+
if (lce.Collection.Owner == null)
50+
{
51+
session.PersistenceContext.AddUnownedCollection(new CollectionKey(persister, lce.Key), lce.Collection);
52+
}
53+
54+
if (log.IsDebugEnabled)
55+
{
56+
log.Debug("removing collection load entry [" + lce + "]");
57+
}
58+
59+
// todo : i'd much rather have this done from #endLoadingCollection(CollectionPersister,LoadingCollectionEntry)...
60+
loadContexts.UnregisterLoadingCollectionXRef(collectionKey);
61+
toRemove.Add(collectionKey);
62+
}
63+
}
64+
65+
localLoadingCollectionKeys.ExceptWith(toRemove);
66+
await (EndLoadingCollectionsAsync(persister, matches));
67+
if ((localLoadingCollectionKeys.Count == 0))
68+
{
69+
// todo : hack!!!
70+
// NOTE : here we cleanup the load context when we have no more local
71+
// LCE entries. This "works" for the time being because really
72+
// only the collection load contexts are implemented. Long term,
73+
// this cleanup should become part of the "close result set"
74+
// processing from the (sandbox/jdbc) jdbc-container code.
75+
loadContexts.Cleanup(resultSet);
76+
}
77+
}
78+
79+
private async Task EndLoadingCollectionsAsync(ICollectionPersister persister, IList<LoadingCollectionEntry> matchedCollectionEntries)
80+
{
81+
if (matchedCollectionEntries == null || matchedCollectionEntries.Count == 0)
82+
{
83+
if (log.IsDebugEnabled)
84+
{
85+
log.Debug("no collections were found in result set for role: " + persister.Role);
86+
}
87+
88+
return;
89+
}
90+
91+
int count = matchedCollectionEntries.Count;
92+
if (log.IsDebugEnabled)
93+
{
94+
log.Debug(count + " collections were found in result set for role: " + persister.Role);
95+
}
96+
97+
for (int i = 0; i < count; i++)
98+
{
99+
await (EndLoadingCollectionAsync(matchedCollectionEntries[i], persister));
100+
}
101+
102+
if (log.IsDebugEnabled)
103+
{
104+
log.Debug(count + " collections initialized for role: " + persister.Role);
105+
}
106+
}
107+
108+
private async Task EndLoadingCollectionAsync(LoadingCollectionEntry lce, ICollectionPersister persister)
109+
{
110+
if (log.IsDebugEnabled)
111+
{
112+
log.Debug("ending loading collection [" + lce + "]");
113+
}
114+
115+
ISessionImplementor session = LoadContext.PersistenceContext.Session;
116+
bool statsEnabled = session.Factory.Statistics.IsStatisticsEnabled;
117+
var stopWath = new Stopwatch();
118+
if (statsEnabled)
119+
{
120+
stopWath.Start();
121+
}
122+
123+
bool hasNoQueuedAdds = lce.Collection.EndRead(persister); // warning: can cause a recursive calls! (proxy initialization)
124+
if (persister.CollectionType.HasHolder())
125+
{
126+
LoadContext.PersistenceContext.AddCollectionHolder(lce.Collection);
127+
}
128+
129+
CollectionEntry ce = LoadContext.PersistenceContext.GetCollectionEntry(lce.Collection);
130+
if (ce == null)
131+
{
132+
ce = LoadContext.PersistenceContext.AddInitializedCollection(persister, lce.Collection, lce.Key);
133+
}
134+
else
135+
{
136+
ce.PostInitialize(lce.Collection);
137+
}
138+
139+
bool addToCache = hasNoQueuedAdds && persister.HasCache && ((session.CacheMode & CacheMode.Put) == CacheMode.Put) && !ce.IsDoremove; // and this is not a forced initialization during flush
140+
if (addToCache)
141+
{
142+
await (AddCollectionToCacheAsync(lce, persister));
143+
}
144+
145+
if (log.IsDebugEnabled)
146+
{
147+
log.Debug("collection fully initialized: " + MessageHelper.CollectionInfoString(persister, lce.Collection, lce.Key, session));
148+
}
149+
150+
if (statsEnabled)
151+
{
152+
stopWath.Stop();
153+
session.Factory.StatisticsImplementor.LoadCollection(persister.Role, stopWath.Elapsed);
154+
}
155+
}
156+
157+
/// <summary> Add the collection to the second-level cache </summary>
158+
/// <param name = "lce">The entry representing the collection to add </param>
159+
/// <param name = "persister">The persister </param>
160+
private async Task AddCollectionToCacheAsync(LoadingCollectionEntry lce, ICollectionPersister persister)
161+
{
162+
ISessionImplementor session = LoadContext.PersistenceContext.Session;
163+
ISessionFactoryImplementor factory = session.Factory;
164+
if (log.IsDebugEnabled)
165+
{
166+
log.Debug("Caching collection: " + MessageHelper.CollectionInfoString(persister, lce.Collection, lce.Key, session));
167+
}
168+
169+
if (!(session.EnabledFilters.Count == 0) && persister.IsAffectedByEnabledFilters(session))
170+
{
171+
// some filters affecting the collection are enabled on the session, so do not do the put into the cache.
172+
log.Debug("Refusing to add to cache due to enabled filters");
173+
// todo : add the notion of enabled filters to the CacheKey to differentiate filtered collections from non-filtered;
174+
// but CacheKey is currently used for both collections and entities; would ideally need to define two separate ones;
175+
// currently this works in conjunction with the check on
176+
// DefaultInitializeCollectionEventHandler.initializeCollectionFromCache() (which makes sure to not read from
177+
// cache with enabled filters).
178+
return; // EARLY EXIT!!!!!
179+
}
180+
181+
IComparer versionComparator;
182+
object version;
183+
if (persister.IsVersioned)
184+
{
185+
versionComparator = persister.OwnerEntityPersister.VersionType.Comparator;
186+
object collectionOwner = LoadContext.PersistenceContext.GetCollectionOwner(lce.Key, persister);
187+
version = LoadContext.PersistenceContext.GetEntry(collectionOwner).Version;
188+
}
189+
else
190+
{
191+
version = null;
192+
versionComparator = null;
193+
}
194+
195+
CollectionCacheEntry entry = await (CollectionCacheEntry.CreateAsync(lce.Collection, persister));
196+
CacheKey cacheKey = session.GenerateCacheKey(lce.Key, persister.KeyType, persister.Role);
197+
bool put = persister.Cache.Put(cacheKey, persister.CacheEntryStructure.Structure(entry), session.Timestamp, version, versionComparator, factory.Settings.IsMinimalPutsEnabled && session.CacheMode != CacheMode.Refresh);
198+
if (put && factory.Statistics.IsStatisticsEnabled)
199+
{
200+
factory.StatisticsImplementor.SecondLevelCachePut(persister.Cache.RegionName);
201+
}
202+
}
203+
}
204+
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Antlr.Runtime;
4+
using Antlr.Runtime.Tree;
5+
using NHibernate.Engine;
6+
using NHibernate.Hql.Ast.ANTLR.Tree;
7+
using NHibernate.Hql.Ast.ANTLR.Util;
8+
using NHibernate.Id;
9+
using NHibernate.Param;
10+
using NHibernate.Persister.Collection;
11+
using NHibernate.Persister.Entity;
12+
using NHibernate.SqlCommand;
13+
using NHibernate.Type;
14+
using NHibernate.UserTypes;
15+
using NHibernate.Util;
16+
using System.Threading.Tasks;
17+
18+
namespace NHibernate.Hql.Ast.ANTLR
19+
{
20+
[System.CodeDom.Compiler.GeneratedCode("AsyncGenerator", "1.0.0")]
21+
public partial class HqlSqlWalker
22+
{
23+
async Task PostProcessInsertAsync(IASTNode insert)
24+
{
25+
var insertStatement = (InsertStatement)insert;
26+
insertStatement.Validate();
27+
SelectClause selectClause = insertStatement.SelectClause;
28+
var persister = insertStatement.IntoClause.Queryable;
29+
if (!insertStatement.IntoClause.IsExplicitIdInsertion)
30+
{
31+
// We need to generate ids as part of this bulk insert.
32+
//
33+
// Note that this is only supported for sequence-style generators and
34+
// post-insert-style generators; basically, only in-db generators
35+
IIdentifierGenerator generator = persister.IdentifierGenerator;
36+
if (!SupportsIdGenWithBulkInsertion(generator))
37+
{
38+
throw new QueryException("can only generate ids as part of bulk insert with either sequence or post-insert style generators");
39+
}
40+
41+
IASTNode idSelectExprNode = null;
42+
var seqGenerator = generator as SequenceGenerator;
43+
if (seqGenerator != null)
44+
{
45+
string seqName = seqGenerator.GeneratorKey();
46+
string nextval = SessionFactoryHelper.Factory.Dialect.GetSelectSequenceNextValString(seqName);
47+
idSelectExprNode = ASTFactory.CreateNode(SQL_TOKEN, nextval);
48+
}
49+
else
50+
{
51+
//Don't need this, because we should never ever be selecting no columns in an insert ... select...
52+
//and because it causes a bug on DB2
53+
/*String idInsertString = sessionFactoryHelper.getFactory().getDialect().getIdentityInsertString();
54+
if ( idInsertString != null ) {
55+
idSelectExprNode = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, idInsertString );
56+
}*/
57+
}
58+
59+
if (idSelectExprNode != null)
60+
{
61+
selectClause.InsertChild(0, idSelectExprNode);
62+
insertStatement.IntoClause.PrependIdColumnSpec();
63+
}
64+
}
65+
66+
bool includeVersionProperty = persister.IsVersioned && !insertStatement.IntoClause.IsExplicitVersionInsertion && persister.VersionPropertyInsertable;
67+
if (includeVersionProperty)
68+
{
69+
// We need to seed the version value as part of this bulk insert
70+
IVersionType versionType = persister.VersionType;
71+
IASTNode versionValueNode;
72+
if (SessionFactoryHelper.Factory.Dialect.SupportsParametersInInsertSelect)
73+
{
74+
versionValueNode = ASTFactory.CreateNode(PARAM, "?");
75+
IParameterSpecification paramSpec = new VersionTypeSeedParameterSpecification(versionType);
76+
((ParameterNode)versionValueNode).HqlParameterSpecification = paramSpec;
77+
_parameters.Insert(0, paramSpec);
78+
}
79+
else
80+
{
81+
if (IsIntegral(versionType))
82+
{
83+
try
84+
{
85+
object seedValue = await (versionType.SeedAsync(null));
86+
versionValueNode = ASTFactory.CreateNode(SQL_TOKEN, seedValue.ToString());
87+
}
88+
catch (Exception t)
89+
{
90+
throw new QueryException("could not determine seed value for version on bulk insert [" + versionType + "]", t);
91+
}
92+
}
93+
else if (IsDatabaseGeneratedTimestamp(versionType))
94+
{
95+
string functionName = SessionFactoryHelper.Factory.Dialect.CurrentTimestampSQLFunctionName;
96+
versionValueNode = ASTFactory.CreateNode(SQL_TOKEN, functionName);
97+
}
98+
else
99+
{
100+
throw new QueryException("cannot handle version type [" + versionType + "] on bulk inserts with dialects not supporting parameters in insert-select statements");
101+
}
102+
}
103+
104+
selectClause.InsertChild(0, versionValueNode);
105+
insertStatement.IntoClause.PrependVersionColumnSpec();
106+
}
107+
108+
if (insertStatement.IntoClause.IsDiscriminated)
109+
{
110+
string sqlValue = insertStatement.IntoClause.Queryable.DiscriminatorSQLValue;
111+
IASTNode discrimValue = ASTFactory.CreateNode(SQL_TOKEN, sqlValue);
112+
insertStatement.SelectClause.AddChild(discrimValue);
113+
}
114+
}
115+
}
116+
}

src/NHibernate/Async/Loader/Loader.cs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -259,12 +259,7 @@ internal async Task InitializeEntitiesAndCollectionsAsync(IList hydratedObjects,
259259
{
260260
if (collectionPersisters[i].IsArray)
261261
{
262-
//for arrays, we should end the collection load before resolving
263-
//the entities, since the actual array instances are not instantiated
264-
//during loading
265-
//TODO: or we could do this polymorphically, and have two
266-
// different operations implemented differently for arrays
267-
EndCollectionLoad(resultSetId, session, collectionPersisters[i]);
262+
await (EndCollectionLoadAsync(resultSetId, session, collectionPersisters[i]));
268263
}
269264
}
270265
}
@@ -304,16 +299,18 @@ internal async Task InitializeEntitiesAndCollectionsAsync(IList hydratedObjects,
304299
{
305300
if (!collectionPersisters[i].IsArray)
306301
{
307-
//for sets, we should end the collection load after resolving
308-
//the entities, since we might call hashCode() on the elements
309-
//TODO: or we could do this polymorphically, and have two
310-
// different operations implemented differently for arrays
311-
EndCollectionLoad(resultSetId, session, collectionPersisters[i]);
302+
await (EndCollectionLoadAsync(resultSetId, session, collectionPersisters[i]));
312303
}
313304
}
314305
}
315306
}
316307

308+
private static async Task EndCollectionLoadAsync(object resultSetId, ISessionImplementor session, ICollectionPersister collectionPersister)
309+
{
310+
//this is a query and we are loading multiple instances of the same collection role
311+
await (session.PersistenceContext.LoadContexts.GetCollectionLoadContext((DbDataReader)resultSetId).EndLoadingCollectionsAsync(collectionPersister));
312+
}
313+
317314
/// <summary>
318315
/// Get the actual object that is returned in the user-visible result list.
319316
/// </summary>

src/NHibernate/Engine/Loading/CollectionLoadContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ namespace NHibernate.Engine.Loading
1919
/// Another implementation option to consider is to not expose <see cref="DbDataReader">ResultSets</see>
2020
/// directly (in the JDBC redesign) but to always "wrap" them and apply a [series of] context[s] to that wrapper.
2121
/// </remarks>
22-
public class CollectionLoadContext
22+
public partial class CollectionLoadContext
2323
{
2424
private static readonly IInternalLogger log = LoggerProvider.LoggerFor(typeof(CollectionLoadContext));
2525
private readonly LoadContexts loadContexts;

src/NHibernate/NHibernate.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@
165165
<Compile Include="Async\Engine\IBatcher.cs" />
166166
<Compile Include="Async\Engine\IPersistenceContext.cs" />
167167
<Compile Include="Async\Engine\ISessionImplementor.cs" />
168+
<Compile Include="Async\Engine\Loading\CollectionLoadContext.cs" />
168169
<Compile Include="Async\Engine\Query\HQLQueryPlan.cs" />
169170
<Compile Include="Async\Engine\Query\NativeSQLQueryPlan.cs" />
170171
<Compile Include="Async\Engine\StatefulPersistenceContext.cs" />
@@ -235,6 +236,7 @@
235236
<Compile Include="Async\Hql\Ast\ANTLR\Exec\IStatementExecutor.cs" />
236237
<Compile Include="Async\Hql\Ast\ANTLR\Exec\MultiTableDeleteExecutor.cs" />
237238
<Compile Include="Async\Hql\Ast\ANTLR\Exec\MultiTableUpdateExecutor.cs" />
239+
<Compile Include="Async\Hql\Ast\ANTLR\HqlSqlWalker.cs" />
238240
<Compile Include="Async\Hql\Ast\ANTLR\QueryTranslatorImpl.cs" />
239241
<Compile Include="Async\Hql\IQueryTranslator.cs" />
240242
<Compile Include="Async\ICriteria.cs" />

0 commit comments

Comments
 (0)