diff --git a/src/NHibernate.Test/NHSpecificTest/NH3079/DomainClasses.cs b/src/NHibernate.Test/NHSpecificTest/NH3079/DomainClasses.cs new file mode 100644 index 00000000000..dd5951184c7 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/NH3079/DomainClasses.cs @@ -0,0 +1,220 @@ + + +using System; +using System.Collections.Generic; +namespace NHibernate.Test.NHSpecificTest.NH3079 +{ + public class PersonCpId + { + private Int32? idA; + public Int32? IdA + { + get { return idA; } + set { idA = value; } + } + + private Int32? idB; + public Int32? IdB + { + get { return idB; } + set { idB = value; } + } + + // override object.Equals + public override bool Equals(object obj) + { + if (obj == null || GetType() != obj.GetType()) + { + return false; + } + PersonCpId objCpId = (PersonCpId)obj; + return this.IdA == objCpId.IdA && this.IdB == this.IdB; + } + + // override object.GetHashCode + public override int GetHashCode() + { + return this.IdA.Value + this.IdB.Value; + } + } + public class Person + { + private PersonCpId cpId; + public virtual PersonCpId CpId + { + get { return cpId; } + set { cpId = value; } + } + + private String name; + public virtual String Name + { + get { return name; } + set { name = value; } + } + + private ICollection employmentList; + public virtual ICollection EmploymentList + { + get { return employmentList; } + set { employmentList = value; } + } + } + + public class EmployerCpId + { + private Int32? idA; + public virtual Int32? IdA + { + get { return idA; } + set { idA = value; } + } + + private Int32? idB; + public virtual Int32? IdB + { + get { return idB; } + set { idB = value; } + } + + // override object.Equals + public override bool Equals(object obj) + { + if (obj == null || GetType() != obj.GetType()) + { + return false; + } + EmployerCpId objCpId = (EmployerCpId)obj; + return this.IdA == objCpId.IdA && this.IdB == this.IdB; + } + + // override object.GetHashCode + public override int GetHashCode() + { + return this.IdA.Value + this.IdB.Value; + } + } + + public class Employer + { + private EmployerCpId cpId; + public virtual EmployerCpId CpId + { + get { return cpId; } + set { cpId = value; } + } + + private String name; + public virtual String Name + { + get { return name; } + set { name = value; } + } + + private ICollection employmentList; + public virtual ICollection EmploymentList + { + get { return employmentList; } + set { employmentList = value; } + } + } + + public class EmploymentCpId + { + private Int32? id; + public virtual Int32? Id + { + get { return id; } + set { id = value; } + } + + private Person personObj; + public virtual Person PersonObj + { + get { return personObj; } + set { personObj = value; } + } + + private Employer employerObj; + public virtual Employer EmployerObj + { + get { return employerObj; } + set { employerObj = value; } + } + + // override object.Equals + public override bool Equals(object obj) + { + if (obj == null || GetType() != obj.GetType()) + { + return false; + } + EmploymentCpId objCpId = (EmploymentCpId)obj; + return this.Id == objCpId.Id && this.PersonObj.CpId == this.PersonObj.CpId && this.EmployerObj.CpId == this.EmployerObj.CpId; + } + + // override object.GetHashCode + public override int GetHashCode() + { + return this.Id.Value + this.PersonObj.CpId.GetHashCode() + this.EmployerObj.CpId.GetHashCode(); + } + } + + public class Employment + { + private EmploymentCpId cpId; + public virtual EmploymentCpId CpId + { + get { return cpId; } + set { cpId = value; } + } + + private String name; + public virtual String Name + { + get { return name; } + set { name = value; } + } + } + + public class PersonNoComponent + { + private Int32? idA; + public virtual Int32? IdA + { + get { return idA; } + set { idA = value; } + } + + private Int32? idB; + public virtual Int32? IdB + { + get { return idB; } + set { idB = value; } + } + + private String name; + public virtual String Name + { + get { return name; } + set { name = value; } + } + + // override object.Equals + public override bool Equals(object obj) + { + if (obj == null || GetType() != obj.GetType()) + { + return false; + } + PersonCpId objCpId = (PersonCpId)obj; + return this.IdA == objCpId.IdA && this.IdB == this.IdB; + } + + // override object.GetHashCode + public override int GetHashCode() + { + return this.IdA.Value + this.IdB.Value; + } + } +} \ No newline at end of file diff --git a/src/NHibernate.Test/NHSpecificTest/NH3079/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH3079/Fixture.cs new file mode 100644 index 00000000000..89be5c5310c --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/NH3079/Fixture.cs @@ -0,0 +1,301 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using NHibernate.Dialect; +using NUnit.Framework; +using NHibernate.Test.NHSpecificTest; +using Iesi.Collections.Generic; +using NHibernate; +using System.Data; +using NHibernate.Criterion; + +namespace NHibernate.Test.NHSpecificTest.NH3079 +{ + /// + /// + /// + /// + [TestFixture] + public class Fixture : BugTestCase + { + protected override void Configure(NHibernate.Cfg.Configuration configuration) + { + #region removing possible second-level-cache configs + configuration.Properties.Remove(NHibernate.Cfg.Environment.CacheProvider); + configuration.Properties.Remove(NHibernate.Cfg.Environment.UseQueryCache); + configuration.Properties.Add(NHibernate.Cfg.Environment.UseQueryCache, "true"); + configuration.Properties.Remove(NHibernate.Cfg.Environment.UseSecondLevelCache); + #endregion + + base.Configure(configuration); + } + + protected override void OnTearDown() + { + base.OnTearDown(); + using (ISession s = OpenSession()) + { + int countUpdate = 0; + + countUpdate = + s + .CreateSQLQuery("DELETE FROM T_EMPLOYMENT") + .ExecuteUpdate(); + Assert.AreEqual(4, countUpdate); + + countUpdate = + s + .CreateSQLQuery("DELETE FROM T_PERSON") + .ExecuteUpdate(); + Assert.AreEqual(3, countUpdate); + + countUpdate = + s + .CreateSQLQuery("DELETE FROM T_EMPLOYER") + .ExecuteUpdate(); + Assert.AreEqual(3, countUpdate); + + countUpdate = + s + .CreateSQLQuery("DELETE FROM T_PERSON_NO_COMP") + .ExecuteUpdate(); + Assert.AreEqual(3, countUpdate); + + s.Flush(); + } + } + + protected override void OnSetUp() + { + base.OnSetUp(); + + using (ISession session = this.OpenSession()) + using (ITransaction tx = session.BeginTransaction()) + { + List personList = new List(); + List employerList = new List(); + + //Global id to avoid false positive assertion with positional parameter + int gId = 1; + + //BEGIN: Person count: 3 + for (int i = 0; i < 3; i++) + { + PersonCpId personCpId = new PersonCpId() { IdA = gId++, IdB = gId++ }; + Person personObj = new Person() { CpId = personCpId, Name = "PERSON_" + personCpId.IdA + "_" + personCpId.IdB }; + session.Save(personObj); + session.Flush(); + personList.Add(personObj); + } + //END: Person count: 3 + + //BEGIN: Employer count: 3 + for (int i = 0; i < 3; i++) + { + EmployerCpId employerCpId = new EmployerCpId() { IdA = gId++, IdB = gId++ }; + Employer employerObj = new Employer() { CpId = employerCpId, Name = "EMPLOYER_" + employerCpId.IdA + "_" + employerCpId.IdB }; + session.Save(employerObj); + session.Flush(); + employerList.Add(employerObj); + } + //END: Employer count: 3 + //BEGIN: employment count: 4 + int[] employmentIdAraay = new int[] { + gId++, + gId++, + gId++, + gId++, + }; + string[] employmentNameArray = new string[] + { + //P1 + E1 + "EMPLOYMENT_" + employmentIdAraay[0] + "_" + + personList[0].CpId.IdA + "_" + personList[0].CpId.IdA + "_" + + employerList[0].CpId.IdA + "_" + employerList[0].CpId.IdB, + //P1 + E2 + "EMPLOYMENT_" + employmentIdAraay[1] + "_" + + personList[0].CpId.IdA + "_" + personList[0].CpId.IdA + "_" + + employerList[1].CpId.IdA + "_" + employerList[1].CpId.IdB, + //P2 + E2 + "EMPLOYMENT_" + employmentIdAraay[2] + "_" + + personList[1].CpId.IdA + "_" + personList[1].CpId.IdA + "_" + + employerList[1].CpId.IdA + "_" + employerList[1].CpId.IdB, + //P2 + E3 + "EMPLOYMENT_" + employmentIdAraay[2] + "_" + + personList[1].CpId.IdA + "_" + personList[1].CpId.IdA + "_" + + employerList[2].CpId.IdA + "_" + employerList[2].CpId.IdB + }; + Person[] employemenPersonArray = new Person[] { + personList[0], + personList[0], + personList[1], + personList[1] + }; + Employer[] employemenEmployerArray = new Employer[] { + employerList[0], + employerList[1], + employerList[1], + employerList[2] + }; + //persinting Employment's + for (int k = 0; k < employmentIdAraay.Length; k++) + { + EmploymentCpId employmentCpId = new EmploymentCpId() { + Id = employmentIdAraay [k], + PersonObj = employemenPersonArray[k], + EmployerObj = employemenEmployerArray[k] + }; + Employment employmentObj = new Employment() { CpId = employmentCpId, Name = employmentNameArray[k] }; + session.Save(employmentObj); + session.Flush(); + } + //END: employment count: 4 + + //BEGIN: PersonNoComponent count: 3 + for (int i = 0; i < 3; i++) + { + PersonNoComponent personNoComponentObj = new PersonNoComponent() { IdA = gId++, IdB = gId++}; + personNoComponentObj.Name = "PERSON_NO_COMPONENT_" + personNoComponentObj.IdA + "_" + personNoComponentObj.IdB; + session.Save(personNoComponentObj); + session.Flush(); + } + //END: PersonNoComponent count: 3 + + tx.Commit(); + } + } + + protected override bool AppliesTo(global::NHibernate.Dialect.Dialect dialect) + { + //return dialect as MsSql2005Dialect != null; + return base.AppliesTo(dialect); + } + + /// + /// Test that reproduces the problem. + /// + [Test] + public void GetPersonTest() + { + using (ISession session = this.OpenSession()) + { + Person person1_2 = session.Get(new PersonCpId() { IdA = 1, IdB = 2 }); + Assert.AreEqual("PERSON_1_2", person1_2.Name); + String[] expetedArray = new String[] { "EMPLOYMENT_13_1_1_7_8", "EMPLOYMENT_14_1_1_9_10" }; + for (int i = 0; i < person1_2.EmploymentList.Count; i++) + { + Assert.AreEqual(expetedArray[i], new List(person1_2.EmploymentList)[i].Name); + } + } + } + + /// + /// Test that reproduces the problem. + /// + [Test] + public void GetEmployerTest() + { + using (ISession session = this.OpenSession()) + { + Employer employer7_8 = session.Get(new EmployerCpId() { IdA = 7, IdB = 8 }); + + Assert.AreEqual("EMPLOYER_7_8", employer7_8.Name); + String[] expetedArray = new String[] { "EMPLOYMENT_13_1_1_7_8", "EMPLOYMENT_13_1_1_7_8" }; + for (int i = 0; i < employer7_8.EmploymentList.Count; i++) + { + Assert.AreEqual(expetedArray[i], new List(employer7_8.EmploymentList)[i].Name); + } + } + + using (ISession session = this.OpenSession()) + { + Employer employer7_8 = session.Get(new EmployerCpId() { IdA = 7, IdB = 8 }); + + Assert.AreEqual("EMPLOYER_7_8", employer7_8.Name); + String[] expetedArray = new String[] { "EMPLOYMENT_13_1_1_7_8", "EMPLOYMENT_13_1_1_7_8" }; + for (int i = 0; i < employer7_8.EmploymentList.Count; i++) + { + Assert.AreEqual(expetedArray[i], new List(employer7_8.EmploymentList)[i].Name); + } + } + } + + [Test] + public void GetEmploymentTest() + { + using (ISession session = this.OpenSession()) + { + Employment employment_13_1_2_7_8 = + session.Get( + new EmploymentCpId() + { + Id = 13, + PersonObj = + new Person() + { + CpId = new PersonCpId() { IdA = 1, IdB = 2 } + }, + EmployerObj = + new Employer() + { + CpId = new EmployerCpId() { IdA = 7, IdB = 8 } + } + }); + Assert.AreEqual("EMPLOYMENT_13_1_1_7_8", employment_13_1_2_7_8.Name); + } + } + + /// + /// Test that reproduces the problem. + /// + [Test] + public void HQLpersonPositional() + { + using (ISession session = this.OpenSession()) + { + IList personList = + session + .GetNamedQuery("personPositional") + .SetParameter(0, new PersonCpId() { IdA = 1, IdB = 2 }) + .SetParameter(1, new PersonCpId() { IdA = 3, IdB = 4 }) + .List(); + String[] expetedArray = new String[] { "PERSON_1_2", "PERSON_3_4" }; + for (int i = 0; i < personList.Count; i++) + { + Assert.AreEqual(expetedArray[i], personList[i].Name); + } + } + } + + [Test] + public void HQLpersonNamed() + { + using (ISession session = this.OpenSession()) + { + IList personList = + session + .GetNamedQuery("personNamed") + .SetParameter("id1", new PersonCpId() { IdA = 1, IdB = 2 }) + .SetParameter("id2", new PersonCpId() { IdA = 3, IdB = 4 }) + .List(); + String[] expetedArray = new String[] { "PERSON_1_2", "PERSON_3_4" }; + for (int i = 0; i < personList.Count; i++) + { + Assert.AreEqual(expetedArray[i], personList[i].Name); + } + } + } + + + [Test] + public void GetPersonNoComponent() + { + using (ISession session = this.OpenSession()) + { + PersonNoComponent person17_18 = session.Get(new PersonNoComponent() { IdA = 17, IdB = 18 }); + Assert.AreEqual("PERSON_NO_COMPONENT_17_18", person17_18.Name); + } + } + } +} \ No newline at end of file diff --git a/src/NHibernate.Test/NHSpecificTest/NH3079/Mappings.hbm.xml b/src/NHibernate.Test/NHSpecificTest/NH3079/Mappings.hbm.xml new file mode 100644 index 00000000000..27009516a62 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/NH3079/Mappings.hbm.xml @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/NHibernate.Test/NHibernate.Test.csproj b/src/NHibernate.Test/NHibernate.Test.csproj index ed517b32aa0..ab1e0724c05 100644 --- a/src/NHibernate.Test/NHibernate.Test.csproj +++ b/src/NHibernate.Test/NHibernate.Test.csproj @@ -675,6 +675,8 @@ + + @@ -2930,6 +2932,7 @@ + diff --git a/src/NHibernate/Impl/AbstractQueryImpl.cs b/src/NHibernate/Impl/AbstractQueryImpl.cs index 56c408f7aae..80d89c9ba8c 100644 --- a/src/NHibernate/Impl/AbstractQueryImpl.cs +++ b/src/NHibernate/Impl/AbstractQueryImpl.cs @@ -71,9 +71,24 @@ public bool HasNamedParameters get { return parameterMetadata.NamedParameterNames.Count > 0; } } - protected internal virtual void VerifyParameters() - { - VerifyParameters(false); + protected internal virtual void VerifyParameters() + { + VerifyParameters(reserveFirstParameter: false, componentsParametersWillBeFlattened: false); + } + + /// + /// + /// + /// + /// FIX TO NH3079: Must be true when using positional parameters and + /// value one or more parameter values can be component with no change of + /// parameter placemarkers count. This is because on native sql queries + /// 'components parameter' must always be positioned with as much + /// parameter placemarks as ordinal values on components. + /// + protected internal virtual void VerifyParameters(bool componentsParametersWillBeFlattened) + { + VerifyParameters(reserveFirstParameter: false, componentsParametersWillBeFlattened: componentsParametersWillBeFlattened); } /// @@ -83,7 +98,14 @@ protected internal virtual void VerifyParameters() /// if true, the first ? will not be verified since /// its needed for e.g. callable statements returning a out parameter /// - protected internal virtual void VerifyParameters(bool reserveFirstParameter) + /// + /// FIX TO NH3079: Must be true when using positional parameters and + /// value one or more parameter values can be component with no change of + /// parameter placemarkers count. This is because on native sql queries + /// 'components parameter' must always be positioned with as much + /// parameter placemarks as ordinal values on components. + /// + protected internal virtual void VerifyParameters(bool reserveFirstParameter, bool componentsParametersWillBeFlattened) { if (parameterMetadata.NamedParameterNames.Count != namedParameters.Count + namedParameterLists.Count) { @@ -108,7 +130,15 @@ protected internal virtual void VerifyParameters(bool reserveFirstParameter) throw new QueryException("Unset positional parameter at position: " + i, QueryString); } } - positionalValueSpan++; + //FIX TO NH3079 + if (componentsParametersWillBeFlattened) + { + positionalValueSpan += ((IType)obj).GetColumnSpan(session.Factory); + } + else + { + positionalValueSpan++; + } } if (parameterMetadata.OrdinalParameterCount != positionalValueSpan) diff --git a/src/NHibernate/Impl/CollectionFilterImpl.cs b/src/NHibernate/Impl/CollectionFilterImpl.cs index 9846747aa8b..19d285d674d 100644 --- a/src/NHibernate/Impl/CollectionFilterImpl.cs +++ b/src/NHibernate/Impl/CollectionFilterImpl.cs @@ -21,28 +21,32 @@ public CollectionFilterImpl(string queryString, object collection, ISessionImple public override IEnumerable Enumerable() { - VerifyParameters(); + //FIX TO NH3079 + VerifyParameters(componentsParametersWillBeFlattened: false); IDictionary namedParams = NamedParams; return Session.EnumerableFilter(collection, ExpandParameterLists(namedParams), GetQueryParameters(namedParams)); } public override IEnumerable Enumerable() { - VerifyParameters(); + //FIX TO NH3079 + VerifyParameters(componentsParametersWillBeFlattened: false); IDictionary namedParams = NamedParams; return Session.EnumerableFilter(collection, ExpandParameterLists(namedParams), GetQueryParameters(namedParams)); } public override IList List() { - VerifyParameters(); + //FIX TO NH3079 + VerifyParameters(componentsParametersWillBeFlattened: false); IDictionary namedParams = NamedParams; return Session.ListFilter(collection, ExpandParameterLists(namedParams), GetQueryParameters(namedParams)); } public override IList List() { - VerifyParameters(); + //FIX TO NH3079 + VerifyParameters(componentsParametersWillBeFlattened: false); IDictionary namedParams = NamedParams; return Session.ListFilter(collection, ExpandParameterLists(namedParams), GetQueryParameters(namedParams)); } diff --git a/src/NHibernate/Impl/ExpressionQueryImpl.cs b/src/NHibernate/Impl/ExpressionQueryImpl.cs index 0fa0a3a7604..30d592cb036 100644 --- a/src/NHibernate/Impl/ExpressionQueryImpl.cs +++ b/src/NHibernate/Impl/ExpressionQueryImpl.cs @@ -53,7 +53,8 @@ public override IEnumerable Enumerable() public override IList List() { - VerifyParameters(); + //FIX TO NH3079 + VerifyParameters(componentsParametersWillBeFlattened: false); IDictionary namedParams = NamedParams; Before(); try @@ -132,7 +133,8 @@ public override void List(IList results) public override IList List() { - VerifyParameters(); + //FIX TO NH3079 + VerifyParameters(componentsParametersWillBeFlattened: false); var namedParams = NamedParams; Before(); try diff --git a/src/NHibernate/Impl/QueryImpl.cs b/src/NHibernate/Impl/QueryImpl.cs index 581033e496b..5d3a842d80d 100644 --- a/src/NHibernate/Impl/QueryImpl.cs +++ b/src/NHibernate/Impl/QueryImpl.cs @@ -26,7 +26,8 @@ public QueryImpl(string queryString, ISessionImplementor session, ParameterMetad public override IEnumerable Enumerable() { - VerifyParameters(); + //FIX TO NH3079 + VerifyParameters(componentsParametersWillBeFlattened: false); IDictionary namedParams = NamedParams; Before(); try @@ -41,7 +42,8 @@ public override IEnumerable Enumerable() public override IEnumerable Enumerable() { - VerifyParameters(); + //FIX TO NH3079 + VerifyParameters(componentsParametersWillBeFlattened: false); IDictionary namedParams = NamedParams; Before(); try @@ -56,7 +58,8 @@ public override IEnumerable Enumerable() public override IList List() { - VerifyParameters(); + //FIX TO NH3079 + VerifyParameters(componentsParametersWillBeFlattened: false); IDictionary namedParams = NamedParams; Before(); try @@ -71,7 +74,8 @@ public override IList List() public override void List(IList results) { - VerifyParameters(); + //FIX TO NH3079 + VerifyParameters(componentsParametersWillBeFlattened: false); IDictionary namedParams = NamedParams; Before(); try @@ -86,7 +90,8 @@ public override void List(IList results) public override IList List() { - VerifyParameters(); + //FIX TO NH3079 + VerifyParameters(componentsParametersWillBeFlattened: false); IDictionary namedParams = NamedParams; Before(); try @@ -112,7 +117,8 @@ protected internal override IDictionary LockModes public override int ExecuteUpdate() { - VerifyParameters(); + //FIX TO NH3079 + VerifyParameters(componentsParametersWillBeFlattened: false); IDictionary namedParams = NamedParams; Before(); try diff --git a/src/NHibernate/Impl/SqlQueryImpl.cs b/src/NHibernate/Impl/SqlQueryImpl.cs index ba81dec34fd..e3a80f9631b 100644 --- a/src/NHibernate/Impl/SqlQueryImpl.cs +++ b/src/NHibernate/Impl/SqlQueryImpl.cs @@ -116,7 +116,8 @@ public override IType[] ReturnTypes public override IList List() { - VerifyParameters(); + //FIX TO NH3079 + VerifyParameters(componentsParametersWillBeFlattened: true); IDictionary namedParams = NamedParams; NativeSQLQuerySpecification spec = GenerateQuerySpecification(namedParams); QueryParameters qp = GetQueryParameters(namedParams); @@ -134,7 +135,8 @@ public override IList List() public override void List(IList results) { - VerifyParameters(); + //FIX TO NH3079 + VerifyParameters(componentsParametersWillBeFlattened: true); IDictionary namedParams = NamedParams; NativeSQLQuerySpecification spec = GenerateQuerySpecification(namedParams); QueryParameters qp = GetQueryParameters(namedParams); @@ -152,7 +154,8 @@ public override void List(IList results) public override IList List() { - VerifyParameters(); + //FIX TO NH3079 + VerifyParameters(componentsParametersWillBeFlattened: true); IDictionary namedParams = NamedParams; NativeSQLQuerySpecification spec = GenerateQuerySpecification(namedParams); QueryParameters qp = GetQueryParameters(namedParams); @@ -265,11 +268,18 @@ public ISQLQuery SetResultSetMapping(string name) queryReturns.Add(returns[index]); } return this; - } - - protected internal override void VerifyParameters() + } + + protected internal override void VerifyParameters() + { + //FIX TO NH3079 + VerifyParameters(componentsParametersWillBeFlattened: true); + } + + protected internal override void VerifyParameters(bool componentsParametersWillBeFlattened) { - base.VerifyParameters(); + //FIX TO NH3079 + base.VerifyParameters(reserveFirstParameter: false, componentsParametersWillBeFlattened: true); bool noReturns = queryReturns == null || queryReturns.Count == 0; if (noReturns) { diff --git a/src/NHibernate/Loader/Custom/CustomLoader.cs b/src/NHibernate/Loader/Custom/CustomLoader.cs index e4155c5666b..849e33d3d5e 100644 --- a/src/NHibernate/Loader/Custom/CustomLoader.cs +++ b/src/NHibernate/Loader/Custom/CustomLoader.cs @@ -323,6 +323,104 @@ protected override void AutoDiscoverTypes(IDataReader rs) transformerAliases = aliases.ToArray(); } + public override ISqlCommand CreateSqlCommand(QueryParameters queryParameters, ISessionImplementor session) + { + // FIX TO NH3079: + if (queryParameters.NamedParameters.Count == 0 && queryParameters.PositionalParameterTypes.Length > 0) + { + IType[] flattenedPositionalParameterTypes = + this.FlattenComponentParameterTypes( + queryParameters.PositionalParameterTypes, + session); + object[] flattenedPositionalParameterValues = + this.FlattenComponentParameterValues( + queryParameters.PositionalParameterTypes, + queryParameters.PositionalParameterValues, + session); + queryParameters.PositionalParameterTypes = flattenedPositionalParameterTypes; + queryParameters.PositionalParameterValues = flattenedPositionalParameterValues; + } + return base.CreateSqlCommand(queryParameters, session); + } + + // FIX TO NH3079: + protected internal virtual IType[] FlattenComponentParameterTypes(IType[] positionalParameterTypes, ISessionImplementor session) + { + List typesResult = new List(); + for (int i = 0; i < positionalParameterTypes.Length; i++) + { + IType typeItem = positionalParameterTypes[i]; + + int loopCount = 0; + while (typeItem.IsEntityType) + { + EntityType entityTypeItem = (EntityType)typeItem; + typeItem = entityTypeItem.GetIdentifierType(session); + + if (loopCount++ > 200) + { + throw new HibernateException("unexpected situation here 'loopCount': " + loopCount); + } + } + + if (typeItem.IsComponentType) + { + IAbstractComponentType componentTypeItem = (IAbstractComponentType)typeItem; + IType[] subcalues = + this.FlattenComponentParameterTypes( + componentTypeItem.Subtypes, + session); + typesResult.AddRange(subcalues); + } + else + { + typesResult.Add(typeItem); + } + } + + return typesResult.ToArray(); + } + + // FIX TO NH3079: + protected internal virtual object[] FlattenComponentParameterValues(IType[] positionalParameterTypes, object[] positionalParameterValues, ISessionImplementor session) + { + List valuesResult = new List(); + for (int i = 0; i < positionalParameterTypes.Length; i++) + { + IType typeItem = positionalParameterTypes[i]; + object valueItem = positionalParameterValues[i]; + + int loopCount = 0; + while (typeItem.IsEntityType) + { + EntityType entityTypeItem = (EntityType)typeItem; + typeItem = entityTypeItem.GetIdentifierType(session); + valueItem = entityTypeItem.GetIdentifier(valueItem, session); + if (loopCount++ > 200) + { + throw new HibernateException("unexpected situation here 'loopCount': " + loopCount); + } + } + + if (typeItem.IsComponentType) + { + IAbstractComponentType componentTypeItem = (IAbstractComponentType)typeItem; + object[] subValues = + this.FlattenComponentParameterValues( + componentTypeItem.Subtypes, + componentTypeItem.GetPropertyValues(valueItem, session), + session); + valuesResult.AddRange(subValues); + } + else + { + valuesResult.Add(valueItem); + } + } + + return valuesResult.ToArray(); + } + protected override void ResetEffectiveExpectedType(IEnumerable parameterSpecs, QueryParameters queryParameters) { parameterSpecs.ResetEffectiveExpectedType(queryParameters);