diff --git a/src/NHibernate.Test/SqlTest/Query/NativeSQLQueries.hbm.xml b/src/NHibernate.Test/SqlTest/Query/NativeSQLQueries.hbm.xml
index 08590d63b2a..929bd86fa7d 100644
--- a/src/NHibernate.Test/SqlTest/Query/NativeSQLQueries.hbm.xml
+++ b/src/NHibernate.Test/SqlTest/Query/NativeSQLQueries.hbm.xml
@@ -1,13 +1,13 @@
+ namespace="NHibernate.Test.SqlTest"
+ assembly="NHibernate.Test">
@@ -27,7 +27,6 @@
-
@@ -116,7 +115,6 @@
-
@@ -149,14 +147,14 @@
fld_name as name,
fld_model as model,
fld_speed as speed,
- fld_length as flength,
+ fld_length as length,
fld_width as width,
fld_length * fld_width as surface,
fld_length * fld_width *10 as volume
from SpaceShip
-
+
SELECT org.NAME FROM ORGANIZATION org
@@ -204,56 +202,75 @@
ORDER BY STARTDATE ASC, EMPLOYEE ASC
-
+
-
-
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
+
+
- SELECT org.ORGID as orgid,
- org.NAME as name,
- emp.EMPLOYER as employer,
- emp.EMPID as empid,
- emp.EMPLOYEE as employee,
- emp.EMPLOYER as employer,
- emp.STARTDATE as xstartDate,
- emp.ENDDATE as endDate,
- emp.REGIONCODE as regionCode,
- emp.AVALUE as AVALUE,
- emp.CURRENCY as CURRENCY
+ SELECT org.ORGID as org_id,
+ org.NAME as org_name,
+ emp.EMPLOYER as emp_employer,
+ emp.EMPID as emp_id,
+ emp.EMPLOYEE as emp_employee,
+ emp.STARTDATE as emp_startDate,
+ emp.ENDDATE as emp_endDate,
+ emp.REGIONCODE as emp_regionCode,
+ emp.AVALUE as emp_avalue,
+ emp.CURRENCY as emp_currency
FROM ORGANIZATION org
LEFT OUTER JOIN EMPLOYMENT emp ON org.ORGID = emp.EMPLOYER
-
-
+
- SELECT org.ORGID as orgid,
- org.NAME as name,
- emp.EMPLOYER as employer,
- emp.EMPID as empid,
- emp.EMPLOYEE as employee,
- emp.EMPLOYER as employer,
- emp.STARTDATE as startDate,
- emp.ENDDATE as endDate,
- emp.REGIONCODE as regionCode,
+ SELECT org.ORGID as ORGID,
+ org.NAME as NAME,
+ emp.EMPLOYER as EMPLOYER,
+ emp.EMPID as EMPID,
+ emp.EMPLOYEE as EMPLOYEE,
+ emp.STARTDATE as STARTDATE,
+ emp.ENDDATE as ENDDATE,
+ emp.REGIONCODE as REGIONCODE,
emp.AVALUE as AVALUE,
emp.CURRENCY as CURRENCY
FROM ORGANIZATION org
LEFT OUTER JOIN EMPLOYMENT emp ON org.ORGID = emp.EMPLOYER
+
+
+
+
+
+
+
+
+
+ SELECT org.ORGID as ORGANISATION_ID,
+ org.NAME as NAME,
+ emp.EMPID as EMPLOYMENT_ID,
+ emp.EMPLOYEE as EMPLOYEE,
+ emp.EMPLOYER as EMPLOYER,
+ emp.STARTDATE as STARTDATE,
+ emp.ENDDATE as ENDDATE,
+ emp.REGIONCODE as REGIONCODE,
+ emp.AVALUE as AVALUE,
+ emp.CURRENCY as CURRENCY
+ FROM ORGANIZATION org
+ LEFT OUTER JOIN EMPLOYMENT emp ON org.ORGID = emp.EMPLOYER
+
diff --git a/src/NHibernate.Test/SqlTest/Query/NativeSQLQueriesFixture.cs b/src/NHibernate.Test/SqlTest/Query/NativeSQLQueriesFixture.cs
index 362c245e611..64d34270582 100644
--- a/src/NHibernate.Test/SqlTest/Query/NativeSQLQueriesFixture.cs
+++ b/src/NHibernate.Test/SqlTest/Query/NativeSQLQueriesFixture.cs
@@ -1,29 +1,14 @@
+using System;
using System.Collections;
+using NHibernate.Criterion;
using NHibernate.Transform;
using NUnit.Framework;
-using NHibernate.Criterion;
namespace NHibernate.Test.SqlTest.Query
{
[TestFixture]
public class GeneralTest : TestCase
{
- protected const string OrganizationFetchJoinEmploymentSQL =
- "SELECT org.ORGID as {org.id}, " +
- " org.NAME as {org.name}, " +
- " emp.EMPLOYER as {emp.key}, " +
- " emp.EMPID as {emp.element}, " +
- " {emp.element.*} " +
- "FROM ORGANIZATION org " +
- " LEFT OUTER JOIN EMPLOYMENT emp ON org.ORGID = emp.EMPLOYER";
-
- protected const string OrganizationJoinEmploymentSQL =
- "SELECT org.ORGID as {org.id}, " +
- " org.NAME as {org.name}, " +
- " {emp.*} " +
- "FROM ORGANIZATION org " +
- " LEFT OUTER JOIN EMPLOYMENT emp ON org.ORGID = emp.EMPLOYER";
-
protected const string EmploymentSQL = "SELECT * FROM EMPLOYMENT";
protected string EmploymentSQLMixedScalarEntity =
@@ -295,7 +280,7 @@ public void MappedAliasStrategy()
s = OpenSession();
t = s.BeginTransaction();
- sqlQuery = s.GetNamedQuery("organizationreturnproperty");
+ sqlQuery = s.GetNamedQuery("organization-using-manual-aliases");
sqlQuery.SetResultTransformer(CriteriaSpecification.AliasToEntityMap);
list = sqlQuery.List();
Assert.AreEqual(2, list.Count);
@@ -452,9 +437,9 @@ public void AutoDetectAliasing()
// TODO H3: H3.2 can guess the return column type so they can use just addScalar("employerid"),
// but NHibernate currently can't do it.
- list =
- s.CreateSQLQuery(EmploymentSQLMixedScalarEntity).AddScalar("employerid", NHibernateUtil.Int64).AddEntity(
- typeof(Employment)).List();
+ list = s.CreateSQLQuery(EmploymentSQLMixedScalarEntity)
+ .AddScalar("employerid", NHibernateUtil.Int64)
+ .AddEntity(typeof(Employment)).List();
Assert.AreEqual(1, list.Count);
o = (object[]) list[0];
Assert.AreEqual(2, o.Length);
@@ -467,34 +452,6 @@ public void AutoDetectAliasing()
list = queryWithCollection.List();
Assert.AreEqual(list.Count, 1);
- s.Clear();
-
- list = s.CreateSQLQuery(OrganizationJoinEmploymentSQL)
- .AddEntity("org", typeof(Organization))
- .AddJoin("emp", "org.employments")
- .List();
- Assert.AreEqual(2, list.Count);
-
- s.Clear();
-
- list = s.CreateSQLQuery(OrganizationFetchJoinEmploymentSQL)
- .AddEntity("org", typeof(Organization))
- .AddJoin("emp", "org.employments")
- .List();
- Assert.AreEqual(2, list.Count);
-
- s.Clear();
-
- // TODO : why twice?
- s.GetNamedQuery("organizationreturnproperty").List();
- list = s.GetNamedQuery("organizationreturnproperty").List();
- Assert.AreEqual(2, list.Count);
-
- s.Clear();
-
- list = s.GetNamedQuery("organizationautodetect").List();
- Assert.AreEqual(2, list.Count);
-
t.Commit();
s.Close();
@@ -538,6 +495,99 @@ public void AutoDetectAliasing()
s.Close();
}
+ public void CanQueryWithGeneratedAliasesOnly_UsingWildcard()
+ {
+ const string SQL =
+ "SELECT org.ORGID as {org.id}, " +
+ " org.NAME as {org.name}, " +
+ " {emp.*} " +
+ "FROM ORGANIZATION org " +
+ " LEFT OUTER JOIN EMPLOYMENT emp ON org.ORGID = emp.EMPLOYER";
+
+ VerifyOrganisationQuery(session => session.CreateSQLQuery(SQL)
+ .AddEntity("org", typeof(Organization))
+ .AddJoin("emp", "org.employments"));
+ }
+
+ [Test]
+ public void CanQueryWithGeneratedAliasesOnly_UsingCollectionElementWildcard()
+ {
+ const string SQL =
+ "SELECT org.ORGID as {org.id}, " +
+ " org.NAME as {org.name}, " +
+ " emp.EMPLOYER as {emp.key}, " +
+ " emp.EMPID as {emp.element}, " +
+ " {emp.element.*} " +
+ "FROM ORGANIZATION org " +
+ " LEFT OUTER JOIN EMPLOYMENT emp ON org.ORGID = emp.EMPLOYER";
+
+ VerifyOrganisationQuery(session => session.CreateSQLQuery(SQL)
+ .AddEntity("org", typeof(Organization))
+ .AddJoin("emp", "org.employments"));
+ }
+
+ [Test]
+ public void CanQueryWithColumnNamesOnly()
+ {
+ VerifyOrganisationQuery(session => session.GetNamedQuery("organization-using-manual-aliases"));
+ }
+
+ [Test]
+ public void CanQueryWithManualAliasesOnly()
+ {
+ VerifyOrganisationQuery(session => session.GetNamedQuery("organization-using-column-names"));
+ }
+
+ [Test]
+ public void CanQueryWithMixOfColumnNamesAndManualAliases()
+ {
+ VerifyOrganisationQuery(session => session.GetNamedQuery("organization-using-column-names-and-manual-aliases"));
+ }
+
+ private void VerifyOrganisationQuery(Func queryFactory)
+ {
+ using (ISession s = OpenSession())
+ using (ITransaction t = s.BeginTransaction())
+ {
+ var ifa = new Organization("IFA");
+ var jboss = new Organization("JBoss");
+ var gavin = new Person("Gavin");
+ var emp = new Employment(gavin, jboss, "AU");
+ s.Save(jboss);
+ s.Save(ifa);
+ s.Save(gavin);
+ s.Save(emp);
+
+ var list = queryFactory(s).List();
+ Assert.AreEqual(2, list.Count);
+ }
+ }
+
+ [Test]
+ public void CanQueryWithManualComponentPropertyAliases()
+ {
+ using (ISession s = OpenSession())
+ using (ITransaction t = s.BeginTransaction())
+ {
+ SpaceShip enterprise = new SpaceShip();
+ enterprise.Model = "USS";
+ enterprise.Name = "Entreprise";
+ enterprise.Speed = 50d;
+ Dimension d = new Dimension(45, 10);
+ enterprise.Dimensions = d;
+ s.Save(enterprise);
+
+ s.Flush();
+ s.Clear();
+
+ object[] result = (object[])s.GetNamedQuery("spaceship").UniqueResult();
+ enterprise = (SpaceShip)result[0];
+ Assert.AreEqual(50d, enterprise.Speed, "Speed");
+ Assert.AreEqual(45, enterprise.Dimensions.Length, "Dimensions.Length");
+ Assert.AreEqual(10, enterprise.Dimensions.Width, "Dimensions.Width");
+ }
+ }
+
[Test]
public void MixAndMatchEntityScalar()
{
diff --git a/src/NHibernate/Loader/BasicLoader.cs b/src/NHibernate/Loader/BasicLoader.cs
index a9958c88666..d5b07ad15bf 100644
--- a/src/NHibernate/Loader/BasicLoader.cs
+++ b/src/NHibernate/Loader/BasicLoader.cs
@@ -1,4 +1,5 @@
using NHibernate.Engine;
+using NHibernate.Loader.Custom;
using NHibernate.Persister.Collection;
using NHibernate.Persister.Entity;
using NHibernate.Type;
diff --git a/src/NHibernate/Loader/Custom/CollectionFetchReturn.cs b/src/NHibernate/Loader/Custom/CollectionFetchReturn.cs
deleted file mode 100644
index 6de23a77010..00000000000
--- a/src/NHibernate/Loader/Custom/CollectionFetchReturn.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-namespace NHibernate.Loader.Custom
-{
- /// Spefically a fetch return that refers to a collection association.
- public class CollectionFetchReturn : FetchReturn
- {
- private readonly ICollectionAliases collectionAliases;
- private readonly IEntityAliases elementEntityAliases;
-
- public CollectionFetchReturn(string alias, NonScalarReturn owner, string ownerProperty,
- ICollectionAliases collectionAliases, IEntityAliases elementEntityAliases,
- LockMode lockMode) : base(owner, ownerProperty, alias, lockMode)
- {
- this.collectionAliases = collectionAliases;
- this.elementEntityAliases = elementEntityAliases;
- }
-
- public ICollectionAliases CollectionAliases
- {
- get { return collectionAliases; }
- }
-
- public IEntityAliases ElementEntityAliases
- {
- get { return elementEntityAliases; }
- }
- }
-}
\ No newline at end of file
diff --git a/src/NHibernate/Loader/Custom/CollectionReturn.cs b/src/NHibernate/Loader/Custom/CollectionReturn.cs
deleted file mode 100644
index de45101f5cf..00000000000
--- a/src/NHibernate/Loader/Custom/CollectionReturn.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-namespace NHibernate.Loader.Custom
-{
- ///
- /// Represents a return which names a collection role; it
- /// is used in defining a custom query for loading an entity's
- /// collection in non-fetching scenarios (i.e., loading the collection
- /// itself as the "root" of the result).
- ///
- public class CollectionReturn : NonScalarReturn
- {
- private readonly string ownerEntityName;
- private readonly string ownerProperty;
- private readonly ICollectionAliases collectionAliases;
- private readonly IEntityAliases elementEntityAliases;
-
- public CollectionReturn(string alias, string ownerEntityName, string ownerProperty,
- ICollectionAliases collectionAliases, IEntityAliases elementEntityAliases, LockMode lockMode)
- : base(alias, lockMode)
- {
- this.ownerEntityName = ownerEntityName;
- this.ownerProperty = ownerProperty;
- this.collectionAliases = collectionAliases;
- this.elementEntityAliases = elementEntityAliases;
- }
-
- /// Returns the class owning the collection.
- public string OwnerEntityName
- {
- get { return ownerEntityName; }
- }
-
- /// Returns the name of the property representing the collection from the .
- public string OwnerProperty
- {
- get { return ownerProperty; }
- }
-
- public ICollectionAliases CollectionAliases
- {
- get { return collectionAliases; }
- }
-
- public IEntityAliases ElementEntityAliases
- {
- get { return elementEntityAliases; }
- }
- }
-}
\ No newline at end of file
diff --git a/src/NHibernate/Loader/Custom/ColumnCollectionAliases.cs b/src/NHibernate/Loader/Custom/ColumnCollectionAliases.cs
index 22d6e406455..b0cd2486556 100644
--- a/src/NHibernate/Loader/Custom/ColumnCollectionAliases.cs
+++ b/src/NHibernate/Loader/Custom/ColumnCollectionAliases.cs
@@ -21,13 +21,35 @@ public ColumnCollectionAliases(IDictionary userProvidedAliases
{
this.userProvidedAliases = userProvidedAliases;
- keyAliases = GetUserProvidedAliases("key", persister.KeyColumnNames);
+ this.keyAliases = GetUserProvidedAliases("key", persister.KeyColumnNames);
+ this.indexAliases = GetUserProvidedAliases("index", persister.IndexColumnNames);
- indexAliases = GetUserProvidedAliases("index", persister.IndexColumnNames);
+ // NH-1612: Add aliases for all composite element properties to support access
+ // to individual composite element properties in elements.
+ this.elementAliases = persister.ElementType.IsComponentType
+ ? GetUserProvidedCompositeElementAliases(persister.ElementColumnNames)
+ : GetUserProvidedAliases("element", persister.ElementColumnNames);
- elementAliases = GetUserProvidedAliases("element", persister.ElementColumnNames);
+ this.identifierAlias = GetUserProvidedAlias("id", persister.IdentifierColumnName);
+ }
- identifierAlias = GetUserProvidedAlias("id", persister.IdentifierColumnName);
+ private string[] GetUserProvidedCompositeElementAliases(string[] defaultAliases)
+ {
+ if (userProvidedAliases != null)
+ {
+ var aliases = new List();
+ foreach (var userProvidedAlias in userProvidedAliases)
+ {
+ if (userProvidedAlias.Key.StartsWith("element."))
+ {
+ aliases.AddRange(userProvidedAlias.Value);
+ }
+ }
+
+ if (aliases.Count > 0) return aliases.ToArray();
+ }
+
+ return defaultAliases;
}
///
@@ -96,27 +118,17 @@ private static string Join(IEnumerable aliases)
private string[] GetUserProvidedAliases(string propertyPath, string[] defaultAliases)
{
string[] result;
- if (!userProvidedAliases.TryGetValue(propertyPath, out result))
- {
- return defaultAliases;
- }
- else
- {
- return result;
- }
+ return userProvidedAliases == null || !userProvidedAliases.TryGetValue(propertyPath, out result)
+ ? defaultAliases
+ : result;
}
private string GetUserProvidedAlias(string propertyPath, string defaultAlias)
{
string[] columns;
- if (!userProvidedAliases.TryGetValue(propertyPath, out columns))
- {
- return defaultAlias;
- }
- else
- {
- return columns[0];
- }
+ return userProvidedAliases == null || !userProvidedAliases.TryGetValue(propertyPath, out columns)
+ ? defaultAlias
+ : columns[0];
}
}
}
diff --git a/src/NHibernate/Loader/Custom/ColumnEntityAliases.cs b/src/NHibernate/Loader/Custom/ColumnEntityAliases.cs
index bfcf2cb2096..5a4ba94b7b9 100644
--- a/src/NHibernate/Loader/Custom/ColumnEntityAliases.cs
+++ b/src/NHibernate/Loader/Custom/ColumnEntityAliases.cs
@@ -8,8 +8,8 @@ namespace NHibernate.Loader.Custom
///
public class ColumnEntityAliases : DefaultEntityAliases
{
- public ColumnEntityAliases(IDictionary returnProperties, ILoadable persister, string suffix)
- : base(returnProperties, persister, suffix) {}
+ public ColumnEntityAliases(IDictionary returnProperties, ILoadable persister)
+ : base(returnProperties, persister, null) {}
protected override string[] GetIdentifierAliases(ILoadable persister, string suffix)
{
diff --git a/src/NHibernate/Loader/Custom/CustomLoader.cs b/src/NHibernate/Loader/Custom/CustomLoader.cs
index fa59fb50aca..8757fbfaf21 100644
--- a/src/NHibernate/Loader/Custom/CustomLoader.cs
+++ b/src/NHibernate/Loader/Custom/CustomLoader.cs
@@ -1,4 +1,3 @@
-using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
@@ -11,8 +10,6 @@
using NHibernate.SqlCommand;
using NHibernate.Transform;
using NHibernate.Type;
-using NHibernate.Util;
-using IQueryable = NHibernate.Persister.Entity.IQueryable;
namespace NHibernate.Loader.Custom
{
@@ -25,13 +22,13 @@ public class CustomLoader : Loader
private readonly SqlString sql;
private readonly ISet querySpaces = new HashSet();
- private List parametersSpecifications;
+ private readonly List parametersSpecifications;
- private readonly IQueryable[] entityPersisters;
+ private readonly ILoadable[] entityPersisters;
private readonly int[] entityOwners;
private readonly IEntityAliases[] entityAliases;
- private readonly IQueryableCollection[] collectionPersisters;
+ private readonly ICollectionPersister[] collectionPersisters;
private readonly int[] collectionOwners;
private readonly ICollectionAliases[] collectionAliases;
@@ -47,120 +44,68 @@ public CustomLoader(ICustomQuery customQuery, ISessionFactoryImplementor factory
querySpaces.UnionWith(customQuery.QuerySpaces);
parametersSpecifications = customQuery.CollectedParametersSpecifications.ToList();
- List entitypersisters = new List();
+ List entitypersisters = new List();
List entityowners = new List();
List entityaliases = new List();
- List collectionpersisters = new List();
+ List collectionpersisters = new List();
List collectionowners = new List();
List collectionaliases = new List();
List lockmodes = new List();
List resultColumnProcessors = new List();
- List nonScalarReturnList = new List();
List resulttypes = new List();
- List specifiedAliases = new List();
+ List transformeraliases = new List();
int returnableCounter = 0;
bool hasScalars = false;
foreach (IReturn rtn in customQuery.CustomQueryReturns)
{
+ transformeraliases.Add(rtn.Alias);
+
if (rtn is ScalarReturn)
{
- ScalarReturn scalarRtn = (ScalarReturn) rtn;
- resulttypes.Add(scalarRtn.Type);
- specifiedAliases.Add(scalarRtn.ColumnAlias);
- resultColumnProcessors.Add(new ScalarResultColumnProcessor(scalarRtn.ColumnAlias, scalarRtn.Type));
+ resulttypes.Add(rtn.Type);
+ resultColumnProcessors.Add(new ScalarResultColumnProcessor(rtn.Alias, rtn.Type));
hasScalars = true;
+ continue;
}
- else if (rtn is RootReturn)
- {
- RootReturn rootRtn = (RootReturn) rtn;
- IQueryable persister = (IQueryable) factory.GetEntityPersister(rootRtn.EntityName);
- entitypersisters.Add(persister);
- lockmodes.Add(rootRtn.LockMode);
- resultColumnProcessors.Add(new NonScalarResultColumnProcessor(returnableCounter++));
- nonScalarReturnList.Add(rtn);
- entityowners.Add(-1);
- resulttypes.Add(persister.Type);
- specifiedAliases.Add(rootRtn.Alias);
- entityaliases.Add(rootRtn.EntityAliases);
- querySpaces.UnionWith(persister.QuerySpaces);
- }
- else if (rtn is CollectionReturn)
+
+ var nonScalarRtn = rtn as NonScalarReturn;
+ if (nonScalarRtn != null)
{
- CollectionReturn collRtn = (CollectionReturn) rtn;
- string role = collRtn.OwnerEntityName + "." + collRtn.OwnerProperty;
- IQueryableCollection persister = (IQueryableCollection) factory.GetCollectionPersister(role);
- collectionpersisters.Add(persister);
- lockmodes.Add(collRtn.LockMode);
- resultColumnProcessors.Add(new NonScalarResultColumnProcessor(returnableCounter++));
- nonScalarReturnList.Add(rtn);
- collectionowners.Add(-1);
- resulttypes.Add(persister.Type);
- specifiedAliases.Add(collRtn.Alias);
- collectionaliases.Add(collRtn.CollectionAliases);
- // determine if the collection elements are entities...
- IType elementType = persister.ElementType;
- if (elementType.IsEntityType)
+ lockmodes.Add(nonScalarRtn.LockMode);
+
+ var ownerIndex = nonScalarRtn.Owner != null
+ ? entitypersisters.IndexOf(nonScalarRtn.Owner.EntityPersister)
+ : -1;
+ if (nonScalarRtn.EntityPersister != null)
{
- IQueryable elementPersister = (IQueryable) ((EntityType) elementType).GetAssociatedJoinable(factory);
- entitypersisters.Add(elementPersister);
- entityowners.Add(-1);
- entityaliases.Add(collRtn.ElementEntityAliases);
- querySpaces.UnionWith(elementPersister.QuerySpaces);
+ entitypersisters.Add(nonScalarRtn.EntityPersister);
+ entityaliases.Add(nonScalarRtn.EntityAliases);
+ entityowners.Add(ownerIndex);
+ querySpaces.UnionWith(nonScalarRtn.EntityPersister.QuerySpaces);
}
- }
- else if (rtn is EntityFetchReturn)
- {
- EntityFetchReturn fetchRtn = (EntityFetchReturn) rtn;
- NonScalarReturn ownerDescriptor = fetchRtn.Owner;
- int ownerIndex = nonScalarReturnList.IndexOf(ownerDescriptor);
- entityowners.Add(ownerIndex);
- lockmodes.Add(fetchRtn.LockMode);
- IQueryable ownerPersister = DetermineAppropriateOwnerPersister(ownerDescriptor);
- EntityType fetchedType = (EntityType) ownerPersister.GetPropertyType(fetchRtn.OwnerProperty);
- string entityName = fetchedType.GetAssociatedEntityName(Factory);
- IQueryable persister = (IQueryable) factory.GetEntityPersister(entityName);
- entitypersisters.Add(persister);
- nonScalarReturnList.Add(rtn);
- specifiedAliases.Add(fetchRtn.Alias);
- entityaliases.Add(fetchRtn.EntityAliases);
- querySpaces.UnionWith(persister.QuerySpaces);
- }
- else if (rtn is CollectionFetchReturn)
- {
- CollectionFetchReturn fetchRtn = (CollectionFetchReturn) rtn;
- NonScalarReturn ownerDescriptor = fetchRtn.Owner;
- int ownerIndex = nonScalarReturnList.IndexOf(ownerDescriptor);
- collectionowners.Add(ownerIndex);
- lockmodes.Add(fetchRtn.LockMode);
- IQueryable ownerPersister = DetermineAppropriateOwnerPersister(ownerDescriptor);
- string role = ownerPersister.EntityName + '.' + fetchRtn.OwnerProperty;
- IQueryableCollection persister = (IQueryableCollection) factory.GetCollectionPersister(role);
- collectionpersisters.Add(persister);
- nonScalarReturnList.Add(rtn);
- specifiedAliases.Add(fetchRtn.Alias);
- collectionaliases.Add(fetchRtn.CollectionAliases);
- // determine if the collection elements are entities...
- IType elementType = persister.ElementType;
- if (elementType.IsEntityType)
+ if (nonScalarRtn.CollectionPersister != null)
{
- IQueryable elementPersister = (IQueryable) ((EntityType) elementType).GetAssociatedJoinable(factory);
- entitypersisters.Add(elementPersister);
- entityowners.Add(ownerIndex);
- entityaliases.Add(fetchRtn.ElementEntityAliases);
- querySpaces.UnionWith(elementPersister.QuerySpaces);
+ collectionpersisters.Add(nonScalarRtn.CollectionPersister);
+ collectionaliases.Add(nonScalarRtn.CollectionAliases);
+ collectionowners.Add(ownerIndex);
}
+ if (nonScalarRtn.Owner == null)
+ {
+ resulttypes.Add(nonScalarRtn.Type);
+ resultColumnProcessors.Add(new NonScalarResultColumnProcessor(returnableCounter++));
+ }
+
+ continue;
}
- else
- {
- throw new HibernateException("unexpected custom query return type : " + rtn.GetType().FullName);
- }
+
+ throw new HibernateException("unexpected custom query return type : " + rtn.GetType().FullName);
}
- entityPersisters = entitypersisters.ToArray();
+ entityPersisters = entitypersisters.Cast().ToArray();
entityOwners = entityowners.ToArray();
entityAliases = entityaliases.ToArray();
collectionPersisters = collectionpersisters.ToArray();
@@ -168,7 +113,7 @@ public CustomLoader(ICustomQuery customQuery, ISessionFactoryImplementor factory
collectionAliases = collectionaliases.ToArray();
lockModes = lockmodes.ToArray();
resultTypes = resulttypes.ToArray();
- transformerAliases = specifiedAliases.ToArray();
+ transformerAliases = transformeraliases.ToArray();
rowProcessor = new ResultRowProcessor(hasScalars, resultColumnProcessors.ToArray());
}
@@ -182,6 +127,10 @@ protected override int[] CollectionOwners
get { return collectionOwners; }
}
+ ///
+ /// An array of indexes of the entity that owns a one-to-one association
+ /// to the entity at the given index (-1 if there is no "owner")
+ ///
protected override int[] Owners
{
get { return entityOwners; }
@@ -202,49 +151,6 @@ protected override ICollectionAliases[] CollectionAliases
get { return collectionAliases; }
}
- private IQueryable DetermineAppropriateOwnerPersister(NonScalarReturn ownerDescriptor)
- {
- string entityName = null;
- RootReturn odrr = ownerDescriptor as RootReturn;
- if (odrr != null)
- {
- entityName = odrr.EntityName;
- }
- else if (ownerDescriptor is CollectionReturn)
- {
- CollectionReturn collRtn = (CollectionReturn) ownerDescriptor;
- string role = collRtn.OwnerEntityName + "." + collRtn.OwnerProperty;
- ICollectionPersister persister = Factory.GetCollectionPersister(role);
- EntityType ownerType = (EntityType) persister.ElementType;
- entityName = ownerType.GetAssociatedEntityName(Factory);
- }
- else if (ownerDescriptor is FetchReturn)
- {
- FetchReturn fetchRtn = (FetchReturn) ownerDescriptor;
- IQueryable persister = DetermineAppropriateOwnerPersister(fetchRtn.Owner);
- IType ownerType = persister.GetPropertyType(fetchRtn.OwnerProperty);
- if (ownerType.IsEntityType)
- {
- entityName = ((EntityType) ownerType).GetAssociatedEntityName(Factory);
- }
- else if (ownerType.IsCollectionType)
- {
- IType ownerCollectionElementType = ((CollectionType) ownerType).GetElementType(Factory);
- if (ownerCollectionElementType.IsEntityType)
- {
- entityName = ((EntityType) ownerCollectionElementType).GetAssociatedEntityName(Factory);
- }
- }
- }
-
- if (entityName == null)
- {
- throw new HibernateException("Could not determine fetch owner : " + ownerDescriptor);
- }
-
- return (IQueryable) Factory.GetEntityPersister(entityName);
- }
-
public override string QueryIdentifier
{
get { return sql.ToString(); }
@@ -283,32 +189,21 @@ protected override object GetResultColumnOrRow(object[] row, IResultTransformer
return rowProcessor.BuildResultRow(row, rs, resultTransformer != null, session);
}
-
- protected override IResultTransformer ResolveResultTransformer(IResultTransformer resultTransformer)
- {
- return HolderInstantiator.ResolveResultTransformer(null, resultTransformer);
- }
-
public override IList GetResultList(IList results, IResultTransformer resultTransformer)
{
// meant to handle dynamic instantiation queries...(Copy from QueryLoader)
HolderInstantiator holderInstantiator =
HolderInstantiator.GetHolderInstantiator(null, resultTransformer, ReturnAliasesForTransformer);
- if (holderInstantiator.IsRequired)
- {
- for (int i = 0; i < results.Count; i++)
- {
- object[] row = (object[]) results[i];
- object result = holderInstantiator.Instantiate(row);
- results[i] = result;
- }
+ if (!holderInstantiator.IsRequired) return results;
- return resultTransformer.TransformList(results);
- }
- else
+ for (int i = 0; i < results.Count; i++)
{
- return results;
+ object[] row = (object[]) results[i];
+ object result = holderInstantiator.Instantiate(row);
+ results[i] = result;
}
+
+ return resultTransformer.TransformList(results);
}
protected override void AutoDiscoverTypes(IDataReader rs)
diff --git a/src/NHibernate/Loader/Custom/EntityFetchReturn.cs b/src/NHibernate/Loader/Custom/EntityFetchReturn.cs
deleted file mode 100644
index 516fd5b347b..00000000000
--- a/src/NHibernate/Loader/Custom/EntityFetchReturn.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-namespace NHibernate.Loader.Custom
-{
- /// Specifically a fetch return that refers to an entity association.
- public class EntityFetchReturn : FetchReturn
- {
- private readonly IEntityAliases entityAliases;
-
- public EntityFetchReturn(string alias, IEntityAliases entityAliases, NonScalarReturn owner, string ownerProperty,
- LockMode lockMode) : base(owner, ownerProperty, alias, lockMode)
- {
- this.entityAliases = entityAliases;
- }
-
- public IEntityAliases EntityAliases
- {
- get { return entityAliases; }
- }
- }
-}
diff --git a/src/NHibernate/Loader/Custom/FetchReturn.cs b/src/NHibernate/Loader/Custom/FetchReturn.cs
deleted file mode 100644
index dc92f040d26..00000000000
--- a/src/NHibernate/Loader/Custom/FetchReturn.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-namespace NHibernate.Loader.Custom
-{
- /// Represents a return which names a fetched association.
- public abstract class FetchReturn : NonScalarReturn
- {
- private readonly NonScalarReturn owner;
- private readonly string ownerProperty;
-
- public FetchReturn(NonScalarReturn owner, string ownerProperty, string alias, LockMode lockMode)
- : base(alias, lockMode)
- {
- this.owner = owner;
- this.ownerProperty = ownerProperty;
- }
-
- /// Retrieves the return descriptor for the owner of this fetch.
- public NonScalarReturn Owner
- {
- get { return owner; }
- }
-
- /// The name of the property on the owner which represents this association.
- public string OwnerProperty
- {
- get { return ownerProperty; }
- }
- }
-}
\ No newline at end of file
diff --git a/src/NHibernate/Loader/GeneratedCollectionAliases.cs b/src/NHibernate/Loader/Custom/GeneratedCollectionAliases.cs
similarity index 76%
rename from src/NHibernate/Loader/GeneratedCollectionAliases.cs
rename to src/NHibernate/Loader/Custom/GeneratedCollectionAliases.cs
index 2252f8efdda..0a3d68bdee9 100644
--- a/src/NHibernate/Loader/GeneratedCollectionAliases.cs
+++ b/src/NHibernate/Loader/Custom/GeneratedCollectionAliases.cs
@@ -2,7 +2,7 @@
using NHibernate.Persister.Collection;
using NHibernate.Util;
-namespace NHibernate.Loader
+namespace NHibernate.Loader.Custom
{
///
/// CollectionAliases which handles the logic of selecting user provided aliases (via return-property),
@@ -17,8 +17,7 @@ public class GeneratedCollectionAliases : ICollectionAliases
private readonly string identifierAlias;
private readonly IDictionary userProvidedAliases;
- public GeneratedCollectionAliases(IDictionary userProvidedAliases, ICollectionPersister persister,
- string suffix)
+ public GeneratedCollectionAliases(IDictionary userProvidedAliases, ICollectionPersister persister, string suffix)
{
this.suffix = suffix;
this.userProvidedAliases = userProvidedAliases;
@@ -30,8 +29,8 @@ public GeneratedCollectionAliases(IDictionary userProvidedAlia
// NH-1612: Add aliases for all composite element properties to support access
// to individual composite element properties in elements.
elementAliases = persister.ElementType.IsComponentType
- ? GetUserProvidedCompositeElementAliases(persister.GetElementColumnAliases(suffix))
- : GetUserProvidedAliases("element", persister.GetElementColumnAliases(suffix));
+ ? GetUserProvidedCompositeElementAliases(persister.GetElementColumnAliases(suffix))
+ : GetUserProvidedAliases("element", persister.GetElementColumnAliases(suffix));
identifierAlias = GetUserProvidedAlias("id", persister.GetIdentifierColumnAlias(suffix));
}
@@ -41,16 +40,21 @@ public GeneratedCollectionAliases(ICollectionPersister persister, string str)
private string[] GetUserProvidedCompositeElementAliases(string[] defaultAliases)
{
- var aliases = new List();
- foreach (KeyValuePair userProvidedAlias in userProvidedAliases)
+ if (userProvidedAliases != null)
{
- if (userProvidedAlias.Key.StartsWith("element."))
+ var aliases = new List();
+ foreach (var userProvidedAlias in userProvidedAliases)
{
- aliases.AddRange(userProvidedAlias.Value);
+ if (userProvidedAlias.Key.StartsWith("element."))
+ {
+ aliases.AddRange(userProvidedAlias.Value);
+ }
}
+
+ if (aliases.Count > 0) return aliases.ToArray();
}
- return aliases.Count > 0 ? aliases.ToArray() : defaultAliases;
+ return defaultAliases;
}
///
@@ -104,38 +108,23 @@ public override string ToString()
private static string Join(IEnumerable aliases)
{
- if (aliases == null)
- {
- return null;
- }
-
- return StringHelper.Join(", ", aliases);
+ return aliases == null ? null : StringHelper.Join(", ", aliases);
}
private string[] GetUserProvidedAliases(string propertyPath, string[] defaultAliases)
{
string[] result;
- if (!userProvidedAliases.TryGetValue(propertyPath, out result))
- {
- return defaultAliases;
- }
- else
- {
- return result;
- }
+ return userProvidedAliases == null || !userProvidedAliases.TryGetValue(propertyPath, out result)
+ ? defaultAliases
+ : result;
}
private string GetUserProvidedAlias(string propertyPath, string defaultAlias)
{
string[] columns;
- if (!userProvidedAliases.TryGetValue(propertyPath, out columns))
- {
- return defaultAlias;
- }
- else
- {
- return columns[0];
- }
+ return userProvidedAliases == null || !userProvidedAliases.TryGetValue(propertyPath, out columns)
+ ? defaultAlias
+ : columns[0];
}
}
}
diff --git a/src/NHibernate/Loader/Custom/IReturn.cs b/src/NHibernate/Loader/Custom/IReturn.cs
index 5012044b696..1d13f8910e5 100644
--- a/src/NHibernate/Loader/Custom/IReturn.cs
+++ b/src/NHibernate/Loader/Custom/IReturn.cs
@@ -1,7 +1,11 @@
+using NHibernate.Type;
+
namespace NHibernate.Loader.Custom
{
/// Represents a return in a custom query.
public interface IReturn
{
+ string Alias { get; }
+ IType Type { get; }
}
}
\ No newline at end of file
diff --git a/src/NHibernate/Loader/Custom/NonScalarReturn.cs b/src/NHibernate/Loader/Custom/NonScalarReturn.cs
index 1776cbc8fca..6dcca5b3941 100644
--- a/src/NHibernate/Loader/Custom/NonScalarReturn.cs
+++ b/src/NHibernate/Loader/Custom/NonScalarReturn.cs
@@ -1,29 +1,106 @@
+using System;
+using NHibernate.Loader.Custom.Sql;
+using NHibernate.Persister.Collection;
+using NHibernate.Persister.Entity;
+using NHibernate.Type;
+
namespace NHibernate.Loader.Custom
{
/// Represents some non-scalar (entity/collection) return within the query result.
- public abstract class NonScalarReturn : IReturn
+ internal class NonScalarReturn : IReturn
{
private readonly string alias;
private readonly LockMode lockMode;
+ private readonly NonScalarReturn owner;
+ private readonly ISqlLoadable entityPersister;
+ private readonly IEntityAliases entityAliases;
+ private readonly ISqlLoadableCollection collectionPersister;
+ private readonly ICollectionAliases collectionAliases;
+
+ public NonScalarReturn(SQLQueryContext context, bool queryHasAliases, string alias, LockMode lockMode)
+ : this(context, queryHasAliases, alias, lockMode, null)
+ {}
- public NonScalarReturn(string alias, LockMode lockMode)
+ public NonScalarReturn(SQLQueryContext context, bool queryHasAliases, string alias, LockMode lockMode, NonScalarReturn owner)
{
- this.alias = alias;
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
if (string.IsNullOrEmpty(alias))
{
throw new HibernateException("alias must be specified");
}
+
+ this.alias = alias;
this.lockMode = lockMode;
+ this.owner = owner;
+
+ this.collectionPersister = context.GetCollectionPersister(alias);
+ if (this.collectionPersister != null)
+ {
+ var collectionPropertyResultMap = context.GetCollectionPropertyResultsMap(alias);
+ this.collectionAliases = queryHasAliases
+ ? new GeneratedCollectionAliases(collectionPropertyResultMap, this.collectionPersister, context.GetCollectionSuffix(alias))
+ : (ICollectionAliases)new ColumnCollectionAliases(collectionPropertyResultMap, this.collectionPersister);
+ }
+
+ if (this.collectionPersister == null || this.CollectionPersister.ElementType.IsEntityType)
+ {
+ this.entityPersister = context.GetEntityPersister(alias);
+ if (this.entityPersister != null)
+ {
+ var entityPropertyResultMap = context.GetEntityPropertyResultsMap(alias);
+ this.entityAliases = queryHasAliases
+ ? new DefaultEntityAliases(entityPropertyResultMap, this.entityPersister, context.GetEntitySuffix(alias))
+ : new ColumnEntityAliases(entityPropertyResultMap, this.entityPersister);
+ }
+ }
}
public string Alias
{
- get { return alias; }
+ get { return this.alias; }
}
public LockMode LockMode
{
- get { return lockMode; }
+ get { return this.lockMode; }
+ }
+
+ public NonScalarReturn Owner
+ {
+ get { return this.owner; }
+ }
+
+ public ICollectionPersister CollectionPersister
+ {
+ get { return this.collectionPersister; }
+ }
+
+ public ICollectionAliases CollectionAliases
+ {
+ get { return this.collectionAliases; }
+ }
+
+ public ISqlLoadable EntityPersister
+ {
+ get { return this.entityPersister; }
+ }
+
+ public IEntityAliases EntityAliases
+ {
+ get { return this.entityAliases; }
+ }
+
+ public IType Type
+ {
+ get
+ {
+ if (this.collectionPersister != null) return this.collectionPersister.CollectionType;
+ if (this.entityPersister != null) return this.entityPersister.EntityMetamodel.EntityType;
+ return null;
+ }
}
}
}
\ No newline at end of file
diff --git a/src/NHibernate/Loader/Custom/RootReturn.cs b/src/NHibernate/Loader/Custom/RootReturn.cs
deleted file mode 100644
index 4337934a56d..00000000000
--- a/src/NHibernate/Loader/Custom/RootReturn.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-namespace NHibernate.Loader.Custom
-{
- ///
- /// Represents a return which names a "root" entity.
- ///
- ///
- /// A root entity means it is explicitly a "column" in the result, as opposed to
- /// a fetched association.
- ///
- public class RootReturn : NonScalarReturn
- {
- private readonly string entityName;
- private readonly IEntityAliases entityAliases;
-
- public RootReturn(string alias, string entityName, IEntityAliases entityAliases, LockMode lockMode)
- : base(alias, lockMode)
- {
- this.entityName = entityName;
- this.entityAliases = entityAliases;
- }
-
- public string EntityName
- {
- get { return entityName; }
- }
-
- public IEntityAliases EntityAliases
- {
- get { return entityAliases; }
- }
- }
-}
\ No newline at end of file
diff --git a/src/NHibernate/Loader/Custom/ScalarReturn.cs b/src/NHibernate/Loader/Custom/ScalarReturn.cs
index 5193d4fbbd0..9d30538d2f2 100644
--- a/src/NHibernate/Loader/Custom/ScalarReturn.cs
+++ b/src/NHibernate/Loader/Custom/ScalarReturn.cs
@@ -3,7 +3,7 @@
namespace NHibernate.Loader.Custom
{
/// Represent a scalar (AKA simple value) return within a query result.
- public class ScalarReturn : IReturn
+ internal class ScalarReturn : IReturn
{
private readonly IType type;
private readonly string columnAlias;
@@ -19,7 +19,7 @@ public IType Type
get { return type; }
}
- public string ColumnAlias
+ public string Alias
{
get { return columnAlias; }
}
diff --git a/src/NHibernate/Loader/Custom/Sql/SQLCustomQuery.cs b/src/NHibernate/Loader/Custom/Sql/SQLCustomQuery.cs
index 2fb3371d46f..7426dd37dd6 100644
--- a/src/NHibernate/Loader/Custom/Sql/SQLCustomQuery.cs
+++ b/src/NHibernate/Loader/Custom/Sql/SQLCustomQuery.cs
@@ -4,10 +4,7 @@
using NHibernate.Engine;
using NHibernate.Engine.Query.Sql;
using NHibernate.Param;
-using NHibernate.Persister.Collection;
-using NHibernate.Persister.Entity;
using NHibernate.SqlCommand;
-using NHibernate.Util;
namespace NHibernate.Loader.Custom.Sql
{
@@ -17,22 +14,21 @@ public class SQLCustomQuery : ICustomQuery
{
private static readonly IInternalLogger log = LoggerProvider.LoggerFor(typeof (SQLCustomQuery));
- private readonly List customQueryReturns = new List();
+ private readonly List customQueryReturns;
private readonly ISet querySpaces = new HashSet();
private readonly SqlString sql;
private readonly List parametersSpecifications;
public SQLCustomQuery(INativeSQLQueryReturn[] queryReturns, string sqlQuery, ICollection additionalQuerySpaces,
- ISessionFactoryImplementor factory)
+ ISessionFactoryImplementor factory)
{
log.Debug("starting processing of sql query [" + sqlQuery + "]");
- SQLQueryReturnProcessor processor = new SQLQueryReturnProcessor(queryReturns, factory);
- SQLQueryReturnProcessor.ResultAliasContext aliasContext = processor.Process();
+ var processor = new SQLQueryContext(queryReturns, factory);
- SQLQueryParser parser = new SQLQueryParser(factory, sqlQuery, new ParserContext(aliasContext));
- sql = parser.Process();
- ArrayHelper.AddAll(customQueryReturns, processor.GenerateCustomReturns(parser.QueryHasAliases));
- parametersSpecifications = parser.CollectedParametersSpecifications.ToList();
+ var parser = new SQLQueryParser(factory, sqlQuery, processor);
+ this.sql = parser.Process();
+ this.customQueryReturns = GenerateCustomReturns(queryReturns, parser.QueryHasAliases, processor).ToList();
+ this.parametersSpecifications = parser.CollectedParametersSpecifications.ToList();
if (additionalQuerySpaces != null)
{
@@ -64,53 +60,39 @@ public IList CustomQueryReturns
#endregion
- private class ParserContext : SQLQueryParser.IParserContext
- {
- private readonly SQLQueryReturnProcessor.ResultAliasContext aliasContext;
-
- public ParserContext(SQLQueryReturnProcessor.ResultAliasContext aliasContext)
- {
- this.aliasContext = aliasContext;
- }
-
- #region IParserContext Members
-
- public bool IsEntityAlias(string alias)
- {
- return GetEntityPersisterByAlias(alias) != null;
- }
-
- public ISqlLoadable GetEntityPersisterByAlias(string alias)
- {
- return aliasContext.GetEntityPersister(alias);
- }
-
- public string GetEntitySuffixByAlias(string alias)
- {
- return aliasContext.GetEntitySuffix(alias);
- }
-
- public bool IsCollectionAlias(string alias)
- {
- return GetCollectionPersisterByAlias(alias) != null;
- }
-
- public ISqlLoadableCollection GetCollectionPersisterByAlias(string alias)
- {
- return aliasContext.GetCollectionPersister(alias);
- }
+ #region private methods
- public string GetCollectionSuffixByAlias(string alias)
- {
- return aliasContext.GetCollectionSuffix(alias);
- }
+ private static IEnumerable GenerateCustomReturns(IEnumerable queryReturns, bool queryHadAliases, SQLQueryContext context)
+ {
+ IDictionary customReturnsByAlias = new Dictionary();
- public IDictionary GetPropertyResultsMapByAlias(string alias)
+ foreach (var nativeRtn in queryReturns)
{
- return aliasContext.GetPropertyResultsMap(alias);
+ var nativeScalarRtn = nativeRtn as NativeSQLQueryScalarReturn;
+ if (nativeScalarRtn != null)
+ {
+ yield return new ScalarReturn(nativeScalarRtn.Type, nativeScalarRtn.ColumnAlias);
+ continue;
+ }
+
+ var nativeJoinRtn = nativeRtn as NativeSQLQueryJoinReturn;
+ if (nativeJoinRtn != null)
+ {
+ var owner = customReturnsByAlias[nativeJoinRtn.OwnerAlias];
+ var fetchReturn = new NonScalarReturn(context, queryHadAliases, nativeJoinRtn.Alias, nativeJoinRtn.LockMode, owner);
+ yield return customReturnsByAlias[fetchReturn.Alias] = fetchReturn;
+ continue;
+ }
+
+ var nativeNonScalarRtn = nativeRtn as NativeSQLQueryNonScalarReturn;
+ if (nativeNonScalarRtn != null)
+ {
+ var nonFetchReturn = new NonScalarReturn(context, queryHadAliases, nativeNonScalarRtn.Alias, nativeNonScalarRtn.LockMode);
+ yield return customReturnsByAlias[nonFetchReturn.Alias] = nonFetchReturn;
+ }
}
-
- #endregion
}
+
+ #endregion
}
}
\ No newline at end of file
diff --git a/src/NHibernate/Loader/Custom/Sql/SQLQueryContext.cs b/src/NHibernate/Loader/Custom/Sql/SQLQueryContext.cs
new file mode 100644
index 00000000000..f3b569048a4
--- /dev/null
+++ b/src/NHibernate/Loader/Custom/Sql/SQLQueryContext.cs
@@ -0,0 +1,357 @@
+using System.Collections.Generic;
+using NHibernate.Engine;
+using NHibernate.Engine.Query.Sql;
+using NHibernate.Persister.Collection;
+using NHibernate.Persister.Entity;
+using NHibernate.Type;
+
+namespace NHibernate.Loader.Custom.Sql
+{
+ ///
+ /// Provides mappings from entity and collection aliases to persisters, suffixes
+ /// and custom property result maps.
+ ///
+ internal class SQLQueryContext
+ {
+ private static readonly IInternalLogger log = LoggerProvider.LoggerFor(typeof (SQLQueryContext));
+
+ #region Instance fields
+
+ private readonly Dictionary alias2Return =
+ new Dictionary();
+
+ private readonly Dictionary alias2OwnerAlias = new Dictionary();
+
+ private readonly Dictionary alias2EntityPersister = new Dictionary();
+ private readonly Dictionary alias2EntitySuffix = new Dictionary();
+ private readonly Dictionary> entityPropertyResultMaps =
+ new Dictionary>();
+
+ private readonly Dictionary alias2CollectionPersister =
+ new Dictionary();
+ private readonly Dictionary alias2CollectionSuffix = new Dictionary();
+ private readonly Dictionary> collectionPropertyResultMaps =
+ new Dictionary>();
+
+ private readonly ISessionFactoryImplementor factory;
+
+ private int entitySuffixSeed;
+ private int collectionSuffixSeed;
+
+ #endregion
+
+ #region .ctor
+
+ public SQLQueryContext(INativeSQLQueryReturn[] queryReturns, ISessionFactoryImplementor factory)
+ {
+ this.factory = factory;
+
+ // first, break down the returns into maps keyed by alias
+ // so that role returns can be more easily resolved to their owners
+ foreach (INativeSQLQueryReturn rtn in queryReturns)
+ {
+ var nonScalarRtn = rtn as NativeSQLQueryNonScalarReturn;
+ if (nonScalarRtn != null)
+ {
+ alias2Return[nonScalarRtn.Alias] = rtn;
+ var joinRtn = rtn as NativeSQLQueryJoinReturn;
+ if (joinRtn != null)
+ {
+ alias2OwnerAlias[joinRtn.Alias] = joinRtn.OwnerAlias;
+ }
+ }
+ }
+
+ // Now, process the returns
+ foreach (INativeSQLQueryReturn rtn in queryReturns)
+ {
+ ProcessReturn(rtn);
+ }
+ }
+
+ #endregion
+
+ #region ISQLQueryAliasContext implementation
+
+ public bool IsEntityAlias(string alias)
+ {
+ return alias2EntityPersister.ContainsKey(alias);
+ }
+
+ public ISqlLoadable GetEntityPersister(string alias)
+ {
+ ISqlLoadable result;
+ alias2EntityPersister.TryGetValue(alias, out result);
+ return result;
+ }
+
+ public string GetEntitySuffix(string alias)
+ {
+ string result;
+ alias2EntitySuffix.TryGetValue(alias, out result);
+ return result;
+ }
+
+ public IDictionary GetEntityPropertyResultsMap(string alias)
+ {
+ IDictionary result;
+ entityPropertyResultMaps.TryGetValue(alias, out result);
+ return result;
+ }
+
+ public bool IsCollectionAlias(string alias)
+ {
+ return alias2CollectionPersister.ContainsKey(alias);
+ }
+
+ public ISqlLoadableCollection GetCollectionPersister(string alias)
+ {
+ ISqlLoadableCollection result;
+ alias2CollectionPersister.TryGetValue(alias, out result);
+ return result;
+ }
+
+ public string GetCollectionSuffix(string alias)
+ {
+ string result;
+ alias2CollectionSuffix.TryGetValue(alias, out result);
+ return result;
+ }
+
+ public IDictionary GetCollectionPropertyResultsMap(string alias)
+ {
+ IDictionary result;
+ collectionPropertyResultMaps.TryGetValue(alias, out result);
+ return result;
+ }
+
+ #endregion
+
+ #region Private methods
+
+ private ISqlLoadable GetSQLLoadable(string entityName)
+ {
+ IEntityPersister persister = factory.GetEntityPersister(entityName);
+ var persisterAsSqlLoadable = persister as ISqlLoadable;
+ if (persisterAsSqlLoadable == null)
+ {
+ throw new MappingException("class persister is not ISqlLoadable: " + entityName);
+ }
+ return persisterAsSqlLoadable;
+ }
+
+ private string GenerateEntitySuffix()
+ {
+ return BasicLoader.GenerateSuffixes(entitySuffixSeed++, 1)[0];
+ }
+
+ private string GenerateCollectionSuffix()
+ {
+ return collectionSuffixSeed++ + "__";
+ }
+
+ private void ProcessReturn(INativeSQLQueryReturn rtn)
+ {
+ if (rtn is NativeSQLQueryScalarReturn)
+ {
+ ProcessScalarReturn((NativeSQLQueryScalarReturn) rtn);
+ }
+ else if (rtn is NativeSQLQueryRootReturn)
+ {
+ ProcessRootReturn((NativeSQLQueryRootReturn) rtn);
+ }
+ else if (rtn is NativeSQLQueryCollectionReturn)
+ {
+ ProcessCollectionReturn((NativeSQLQueryCollectionReturn) rtn);
+ }
+ else
+ {
+ ProcessJoinReturn((NativeSQLQueryJoinReturn) rtn);
+ }
+ }
+
+ private void ProcessScalarReturn(NativeSQLQueryScalarReturn typeReturn) {}
+
+ private void ProcessRootReturn(NativeSQLQueryRootReturn rootReturn)
+ {
+ if (alias2EntityPersister.ContainsKey(rootReturn.Alias))
+ {
+ // already been processed...
+ return;
+ }
+
+ ISqlLoadable persister = GetSQLLoadable(rootReturn.ReturnEntityName);
+ AddPersister(rootReturn.Alias, rootReturn.PropertyResultsMap, persister);
+ }
+
+ private void AddPersister(string alias, IDictionary propertyResultMap, ISqlLoadable persister)
+ {
+ alias2EntityPersister[alias] = persister;
+ string suffix = GenerateEntitySuffix();
+ log.Debug("mapping alias [" + alias + "] to entity-suffix [" + suffix + "]");
+ alias2EntitySuffix[alias] = suffix;
+ if (propertyResultMap != null && propertyResultMap.Count > 0)
+ {
+ entityPropertyResultMaps[alias] = GroupComponentAliases(propertyResultMap, persister);
+ }
+ }
+
+ private void AddCollection(string role, string alias, IDictionary propertyResultMap)
+ {
+ ISqlLoadableCollection collectionPersister = (ISqlLoadableCollection) factory.GetCollectionPersister(role);
+ alias2CollectionPersister[alias] = collectionPersister;
+ string suffix = GenerateCollectionSuffix();
+ log.Debug("mapping alias [" + alias + "] to collection-suffix [" + suffix + "]");
+ alias2CollectionSuffix[alias] = suffix;
+
+ if (propertyResultMap != null && propertyResultMap.Count > 0)
+ {
+ collectionPropertyResultMaps[alias] = FilterCollectionProperties(propertyResultMap);
+ }
+ if (collectionPersister.IsOneToMany)
+ {
+ var persister = (ISqlLoadable)collectionPersister.ElementPersister;
+ AddPersister(alias, FilterElementProperties(propertyResultMap), persister);
+ }
+ }
+
+ private IDictionary FilterCollectionProperties(IDictionary propertyResults)
+ {
+ if (propertyResults.Count == 0) return propertyResults;
+
+ var result = new Dictionary(propertyResults.Count);
+ foreach (KeyValuePair element in propertyResults)
+ {
+ if (element.Key.IndexOf('.') < 0)
+ {
+ result.Add(element.Key, element.Value);
+ }
+ }
+ return result;
+ }
+
+ private IDictionary FilterElementProperties(IDictionary propertyResults)
+ {
+ const string PREFIX = "element.";
+
+ if (propertyResults.Count == 0) return propertyResults;
+
+ var result = new Dictionary(propertyResults.Count);
+ foreach (KeyValuePair element in propertyResults)
+ {
+ string path = element.Key;
+ if (path.StartsWith(PREFIX))
+ {
+ result.Add(path.Substring(PREFIX.Length), element.Value);
+ }
+ }
+ return result;
+ }
+
+ private IDictionary GroupComponentAliases(IDictionary propertyResults, ILoadable persister)
+ {
+ if (propertyResults.Count == 0) return propertyResults;
+
+ var result = new Dictionary(propertyResults.Count);
+
+ foreach (var propertyResult in propertyResults)
+ {
+ var path = propertyResult.Key;
+ var dotIndex = path.IndexOf('.');
+ if (dotIndex >= 0)
+ {
+ var propertyPath = path.Substring(0, dotIndex);
+ if (!result.ContainsKey(propertyPath))
+ {
+ var aliases = GetUserProvidedAliases(propertyResults, propertyPath, persister.GetPropertyType(propertyPath));
+ if (aliases != null) result.Add(propertyPath, aliases);
+ }
+ continue;
+ }
+ result.Add(propertyResult.Key, propertyResult.Value);
+ }
+ return result;
+ }
+
+ private string[] GetUserProvidedAliases(IDictionary propertyResults, string propertyPath, IType propertyType)
+ {
+ string[] result;
+ if (propertyResults.TryGetValue(propertyPath, out result)) return result;
+
+ var aliases = new List();
+ AppendUserProvidedAliases(propertyResults, propertyPath, propertyType, aliases);
+ return aliases.Count > 0
+ ? aliases.ToArray()
+ : null;
+ }
+
+ private void AppendUserProvidedAliases(IDictionary propertyResults, string propertyPath, IType propertyType, List result)
+ {
+ string[] aliases;
+ if (propertyResults.TryGetValue(propertyPath, out aliases))
+ {
+ result.AddRange(aliases);
+ return;
+ }
+
+ var componentType = propertyType as IAbstractComponentType;
+ // TODO: throw exception when no mapping is found for property name
+ if (componentType == null) return;
+
+ for (int i = 0; i < componentType.PropertyNames.Length; i++)
+ {
+ AppendUserProvidedAliases(propertyResults, propertyPath + '.' + componentType.PropertyNames[i], componentType.Subtypes[i], result);
+ }
+ }
+
+ private void ProcessCollectionReturn(NativeSQLQueryCollectionReturn collectionReturn)
+ {
+ // we are initializing an owned collection
+ string role = collectionReturn.OwnerEntityName + '.' + collectionReturn.OwnerProperty;
+ AddCollection(role, collectionReturn.Alias, collectionReturn.PropertyResultsMap);
+ }
+
+ private void ProcessJoinReturn(NativeSQLQueryJoinReturn fetchReturn)
+ {
+ string alias = fetchReturn.Alias;
+ if (alias2EntityPersister.ContainsKey(alias) || alias2CollectionPersister.ContainsKey(alias))
+ {
+ // already been processed...
+ return;
+ }
+
+ string ownerAlias = fetchReturn.OwnerAlias;
+
+ // Make sure the owner alias is known...
+ INativeSQLQueryReturn ownerReturn;
+ if (!alias2Return.TryGetValue(ownerAlias, out ownerReturn))
+ {
+ throw new HibernateException(string.Format("Owner alias [{0}] is unknown for alias [{1}]", ownerAlias, alias));
+ }
+
+ // If this return's alias has not been processed yet, do so b4 further processing of this return
+ if (!alias2EntityPersister.ContainsKey(ownerAlias))
+ {
+ ProcessReturn(ownerReturn);
+ }
+
+ var ownerPersister = alias2EntityPersister[ownerAlias];
+ var returnType = ownerPersister.GetPropertyType(fetchReturn.OwnerProperty);
+
+ if (returnType.IsCollectionType)
+ {
+ string role = ownerPersister.EntityName + '.' + fetchReturn.OwnerProperty;
+ AddCollection(role, alias, fetchReturn.PropertyResultsMap);
+ }
+ else if (returnType.IsEntityType)
+ {
+ EntityType eType = (EntityType) returnType;
+ string returnEntityName = eType.GetAssociatedEntityName();
+ ISqlLoadable persister = GetSQLLoadable(returnEntityName);
+ AddPersister(alias, fetchReturn.PropertyResultsMap, persister);
+ }
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/src/NHibernate/Loader/Custom/Sql/SQLQueryParser.cs b/src/NHibernate/Loader/Custom/Sql/SQLQueryParser.cs
index 979debbc647..34fad2f3f2f 100644
--- a/src/NHibernate/Loader/Custom/Sql/SQLQueryParser.cs
+++ b/src/NHibernate/Loader/Custom/Sql/SQLQueryParser.cs
@@ -1,4 +1,3 @@
-using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -11,27 +10,16 @@
namespace NHibernate.Loader.Custom.Sql
{
- public class SQLQueryParser
+ internal class SQLQueryParser
{
- public interface IParserContext
- {
- bool IsEntityAlias(string aliasName);
- ISqlLoadable GetEntityPersisterByAlias(string alias);
- string GetEntitySuffixByAlias(string alias);
- bool IsCollectionAlias(string aliasName);
- ISqlLoadableCollection GetCollectionPersisterByAlias(string alias);
- string GetCollectionSuffixByAlias(string alias);
- IDictionary GetPropertyResultsMapByAlias(string alias);
- }
-
private readonly ISessionFactoryImplementor factory;
private readonly string originalQueryString;
- private readonly IParserContext context;
+ private readonly SQLQueryContext context;
private long aliasesFound;
private IEnumerable parametersSpecifications;
- public SQLQueryParser(ISessionFactoryImplementor factory, string sqlQuery, IParserContext context)
+ public SQLQueryParser(ISessionFactoryImplementor factory, string sqlQuery, SQLQueryContext context)
{
this.factory = factory;
originalQueryString = sqlQuery;
@@ -53,7 +41,7 @@ public IEnumerable CollectedParametersSpecifications
get { return parametersSpecifications; }
}
- // TODO: should "record" how many properties we have reffered to - and if we
+ // TODO: should "record" how many properties we have refered to - and if we
// don't get'em'all we throw an exception! Way better than trial and error ;)
private string SubstituteBrackets()
{
@@ -131,16 +119,16 @@ private string SubstituteBrackets()
private string ResolveCollectionProperties(string aliasName, string propertyName)
{
- IDictionary fieldResults = context.GetPropertyResultsMapByAlias(aliasName);
- ISqlLoadableCollection collectionPersister = context.GetCollectionPersisterByAlias(aliasName);
- string collectionSuffix = context.GetCollectionSuffixByAlias(aliasName);
+ IDictionary fieldResults = context.GetCollectionPropertyResultsMap(aliasName);
+ ISqlLoadableCollection collectionPersister = context.GetCollectionPersister(aliasName);
+ string collectionSuffix = context.GetCollectionSuffix(aliasName);
// NH Different behavior for NH-1612
if ("*".Equals(propertyName))
{
- if (fieldResults.Count != 0)
+ if (fieldResults != null)
{
- throw new QueryException("Using return-propertys together with * syntax is not supported.");
+ throw new QueryException("Using return-property elements together with * syntax is not supported.");
}
string selectFragment = collectionPersister.SelectFragment(aliasName, collectionSuffix);
@@ -161,7 +149,7 @@ private string ResolveCollectionProperties(string aliasName, string propertyName
{
return ResolveProperties(aliasName, elementPropertyName);
}
- else if (elementPropertyName == "*")
+ if (elementPropertyName == "*")
{
throw new QueryException("Using element.* syntax is only supported for entity elements.");
}
@@ -170,7 +158,7 @@ private string ResolveCollectionProperties(string aliasName, string propertyName
string[] columnAliases;
// Let return-propertys override whatever the persister has for aliases.
- if (!fieldResults.TryGetValue(propertyName, out columnAliases))
+ if (fieldResults == null || !fieldResults.TryGetValue(propertyName, out columnAliases))
{
columnAliases = collectionPersister.GetCollectionPropertyColumnAliases(propertyName, collectionSuffix);
}
@@ -193,44 +181,43 @@ private string ResolveCollectionProperties(string aliasName, string propertyName
private string ResolveProperties(string aliasName, string propertyName)
{
- IDictionary fieldResults = context.GetPropertyResultsMapByAlias(aliasName);
- ISqlLoadable persister = context.GetEntityPersisterByAlias(aliasName);
- string suffix = context.GetEntitySuffixByAlias(aliasName);
+ IDictionary fieldResults = context.GetEntityPropertyResultsMap(aliasName);
+ ISqlLoadable persister = context.GetEntityPersister(aliasName);
+ string suffix = context.GetEntitySuffix(aliasName);
if ("*".Equals(propertyName))
{
- if (fieldResults.Count != 0)
+ if (fieldResults != null)
{
- throw new QueryException("Using return-propertys together with * syntax is not supported.");
+ throw new QueryException("Using return-property elements together with * syntax is not supported.");
}
aliasesFound++;
return persister.SelectFragment(aliasName, suffix);
}
- else
- {
- string[] columnAliases;
- // Let return-propertys override whatever the persister has for aliases.
- if (!fieldResults.TryGetValue(propertyName, out columnAliases))
- {
- columnAliases = persister.GetSubclassPropertyColumnAliases(propertyName, suffix);
- }
+ string[] columnAliases;
- if (columnAliases == null || columnAliases.Length == 0)
- {
- throw new QueryException("No column name found for property [" + propertyName + "] for alias [" + aliasName + "]",
- originalQueryString);
- }
- if (columnAliases.Length != 1)
- {
- // TODO: better error message since we actually support composites if names are explicitly listed.
- throw new QueryException(
- "SQL queries only support properties mapped to a single column - property [" + propertyName + "] is mapped to "
- + columnAliases.Length + " columns.", originalQueryString);
- }
- aliasesFound++;
- return columnAliases[0];
+ // Let return-property elements override whatever the persister has for aliases.
+ if (fieldResults == null || !fieldResults.TryGetValue(propertyName, out columnAliases))
+ {
+ columnAliases = persister.GetSubclassPropertyColumnAliases(propertyName, suffix);
+ }
+
+ if (columnAliases == null || columnAliases.Length == 0)
+ {
+ throw new QueryException("No column name found for property [" + propertyName + "] for alias [" + aliasName + "]",
+ originalQueryString);
+ }
+ if (columnAliases.Length != 1)
+ {
+ // TODO: better error message since we actually support composites if names are explicitly listed.
+ throw new QueryException(
+ "SQL queries only support properties mapped to a single column - property [" + propertyName + "] is mapped to "
+ + columnAliases.Length + " columns.", originalQueryString);
}
+ aliasesFound++;
+
+ return columnAliases[0];
}
///
diff --git a/src/NHibernate/Loader/Custom/Sql/SQLQueryReturnProcessor.cs b/src/NHibernate/Loader/Custom/Sql/SQLQueryReturnProcessor.cs
deleted file mode 100644
index 20c0c0fba65..00000000000
--- a/src/NHibernate/Loader/Custom/Sql/SQLQueryReturnProcessor.cs
+++ /dev/null
@@ -1,409 +0,0 @@
-using System.Collections;
-using System.Collections.Generic;
-
-using NHibernate.Engine;
-using NHibernate.Engine.Query.Sql;
-using NHibernate.Persister.Collection;
-using NHibernate.Persister.Entity;
-using NHibernate.Type;
-
-namespace NHibernate.Loader.Custom.Sql
-{
- public class SQLQueryReturnProcessor
- {
- private static readonly IInternalLogger log = LoggerProvider.LoggerFor(typeof (SQLQueryReturnProcessor));
-
- private readonly INativeSQLQueryReturn[] queryReturns;
-
- private readonly Dictionary alias2Return =
- new Dictionary();
-
- private readonly Dictionary alias2OwnerAlias = new Dictionary();
-
- private readonly Dictionary alias2Persister = new Dictionary();
- private readonly Dictionary alias2Suffix = new Dictionary();
-
- private readonly Dictionary alias2CollectionPersister =
- new Dictionary();
-
- private readonly Dictionary alias2CollectionSuffix = new Dictionary();
-
- private readonly Dictionary> entityPropertyResultMaps =
- new Dictionary>();
-
- private readonly Dictionary> collectionPropertyResultMaps =
- new Dictionary>();
-
- private readonly ISessionFactoryImplementor factory;
-
- private int entitySuffixSeed = 0;
- private int collectionSuffixSeed = 0;
-
- private ISessionFactoryImplementor Factory
- {
- get { return factory; }
- }
-
- public SQLQueryReturnProcessor(INativeSQLQueryReturn[] queryReturns, ISessionFactoryImplementor factory)
- {
- this.queryReturns = queryReturns;
- this.factory = factory;
- }
-
- public class ResultAliasContext
- {
- private readonly SQLQueryReturnProcessor parent;
-
- public ResultAliasContext(SQLQueryReturnProcessor parent)
- {
- this.parent = parent;
- }
-
- public ISqlLoadable GetEntityPersister(string alias)
- {
- ISqlLoadable result;
- parent.alias2Persister.TryGetValue(alias, out result);
- return result;
- }
-
- public ISqlLoadableCollection GetCollectionPersister(string alias)
- {
- ISqlLoadableCollection result;
- parent.alias2CollectionPersister.TryGetValue(alias, out result);
- return result;
- }
-
- public string GetEntitySuffix(string alias)
- {
- string result;
- parent.alias2Suffix.TryGetValue(alias, out result);
- return result;
- }
-
- public string GetCollectionSuffix(string alias)
- {
- string result;
- parent.alias2CollectionSuffix.TryGetValue(alias, out result);
- return result;
- }
-
- public string GetOwnerAlias(string alias)
- {
- string result;
- parent.alias2OwnerAlias.TryGetValue(alias, out result);
- return result;
- }
-
- public IDictionary GetPropertyResultsMap(string alias)
- {
- return parent.InternalGetPropertyResultsMap(alias);
- }
- }
-
- private IDictionary InternalGetPropertyResultsMap(string alias)
- {
- NativeSQLQueryNonScalarReturn rtn = alias2Return[alias] as NativeSQLQueryNonScalarReturn;
- return rtn != null ? rtn.PropertyResultsMap : null;
- }
-
- private bool HasPropertyResultMap(string alias)
- {
- IDictionary propertyMaps = InternalGetPropertyResultsMap(alias);
- return propertyMaps != null && propertyMaps.Count != 0;
- }
-
- public ResultAliasContext Process()
- {
- // first, break down the returns into maps keyed by alias
- // so that role returns can be more easily resolved to their owners
- for (int i = 0; i < queryReturns.Length; i++)
- {
- var rtn = queryReturns[i] as NativeSQLQueryNonScalarReturn;
- if (rtn != null)
- {
- alias2Return[rtn.Alias] = rtn;
- var roleReturn = queryReturns[i] as NativeSQLQueryJoinReturn;
- if (roleReturn != null)
- {
- alias2OwnerAlias[roleReturn.Alias] = roleReturn.OwnerAlias;
- }
- }
- }
-
- // Now, process the returns
- for (int i = 0; i < queryReturns.Length; i++)
- {
- ProcessReturn(queryReturns[i]);
- }
-
- return new ResultAliasContext(this);
- }
-
- private ISqlLoadable GetSQLLoadable(string entityName)
- {
- IEntityPersister persister = factory.GetEntityPersister(entityName);
- var persisterAsSqlLoadable = persister as ISqlLoadable;
- if (persisterAsSqlLoadable == null)
- {
- throw new MappingException("class persister is not ISqlLoadable: " + entityName);
- }
- return persisterAsSqlLoadable;
- }
-
- private string GenerateEntitySuffix()
- {
- return BasicLoader.GenerateSuffixes(entitySuffixSeed++, 1)[0];
- }
-
- private string GenerateCollectionSuffix()
- {
- return collectionSuffixSeed++ + "__";
- }
-
- private void ProcessReturn(INativeSQLQueryReturn rtn)
- {
- if (rtn is NativeSQLQueryScalarReturn)
- {
- ProcessScalarReturn((NativeSQLQueryScalarReturn) rtn);
- }
- else if (rtn is NativeSQLQueryRootReturn)
- {
- ProcessRootReturn((NativeSQLQueryRootReturn) rtn);
- }
- else if (rtn is NativeSQLQueryCollectionReturn)
- {
- ProcessCollectionReturn((NativeSQLQueryCollectionReturn) rtn);
- }
- else
- {
- ProcessJoinReturn((NativeSQLQueryJoinReturn) rtn);
- }
- }
-
- private void ProcessScalarReturn(NativeSQLQueryScalarReturn typeReturn) {}
-
- private void ProcessRootReturn(NativeSQLQueryRootReturn rootReturn)
- {
- if (alias2Persister.ContainsKey(rootReturn.Alias))
- {
- // already been processed...
- return;
- }
-
- ISqlLoadable persister = GetSQLLoadable(rootReturn.ReturnEntityName);
- AddPersister(rootReturn.Alias, rootReturn.PropertyResultsMap, persister);
- }
-
- private void AddPersister(string alias, IDictionary propertyResult, ISqlLoadable persister)
- {
- alias2Persister[alias] = persister;
- string suffix = GenerateEntitySuffix();
- log.Debug("mapping alias [" + alias + "] to entity-suffix [" + suffix + "]");
- alias2Suffix[alias] = suffix;
- entityPropertyResultMaps[alias] = propertyResult;
- }
-
- private void AddCollection(string role, string alias, IDictionary propertyResults)
- {
- ISqlLoadableCollection collectionPersister = (ISqlLoadableCollection) Factory.GetCollectionPersister(role);
- alias2CollectionPersister[alias] = collectionPersister;
- string suffix = GenerateCollectionSuffix();
- log.Debug("mapping alias [" + alias + "] to collection-suffix [" + suffix + "]");
- alias2CollectionSuffix[alias] = suffix;
- collectionPropertyResultMaps[alias] = propertyResults;
-
- if (collectionPersister.IsOneToMany)
- {
- ISqlLoadable persister = (ISqlLoadable) collectionPersister.ElementPersister;
- AddPersister(alias, Filter(propertyResults), persister);
- }
- }
-
- private IDictionary Filter(IDictionary propertyResults)
- {
- Dictionary result = new Dictionary(propertyResults.Count);
-
- string keyPrefix = "element.";
-
- foreach (KeyValuePair element in propertyResults)
- {
- string path = element.Key;
- if (path.StartsWith(keyPrefix))
- {
- result[path.Substring(keyPrefix.Length)] = element.Value;
- }
- }
-
- return result;
- }
-
- private void ProcessCollectionReturn(NativeSQLQueryCollectionReturn collectionReturn)
- {
- // we are initializing an owned collection
- string role = collectionReturn.OwnerEntityName + '.' + collectionReturn.OwnerProperty;
- AddCollection(role, collectionReturn.Alias, collectionReturn.PropertyResultsMap);
- }
-
- private void ProcessJoinReturn(NativeSQLQueryJoinReturn fetchReturn)
- {
- string alias = fetchReturn.Alias;
- if (alias2Persister.ContainsKey(alias) || alias2CollectionPersister.ContainsKey(alias))
- {
- // already been processed...
- return;
- }
-
- string ownerAlias = fetchReturn.OwnerAlias;
-
- // Make sure the owner alias is known...
- if (!alias2Return.ContainsKey(ownerAlias))
- {
- throw new HibernateException(string.Format("Owner alias [{0}] is unknown for alias [{1}]", ownerAlias, alias));
- }
-
- // If this return's alias has not been processed yet, do so b4 further processing of this return
- if (!alias2Persister.ContainsKey(ownerAlias))
- {
- ProcessReturn(alias2Return[ownerAlias]);
- }
-
- ISqlLoadable ownerPersister = alias2Persister[ownerAlias];
- IType returnType = ownerPersister.GetPropertyType(fetchReturn.OwnerProperty);
-
- if (returnType.IsCollectionType)
- {
- string role = ownerPersister.EntityName + '.' + fetchReturn.OwnerProperty;
- AddCollection(role, alias, fetchReturn.PropertyResultsMap);
- }
- else if (returnType.IsEntityType)
- {
- EntityType eType = (EntityType) returnType;
- string returnEntityName = eType.GetAssociatedEntityName();
- ISqlLoadable persister = GetSQLLoadable(returnEntityName);
- AddPersister(alias, fetchReturn.PropertyResultsMap, persister);
- }
- }
-
- public IList GenerateCustomReturns(bool queryHadAliases)
- {
- IList customReturns = new List