You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
|
Apr
(248) |
May
(82) |
Jun
(90) |
Jul
(177) |
Aug
(253) |
Sep
(157) |
Oct
(151) |
Nov
(143) |
Dec
(278) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
(152) |
Feb
(107) |
Mar
(177) |
Apr
(133) |
May
(259) |
Jun
(81) |
Jul
(119) |
Aug
(306) |
Sep
(416) |
Oct
(240) |
Nov
(329) |
Dec
(206) |
2006 |
Jan
(466) |
Feb
(382) |
Mar
(153) |
Apr
(162) |
May
(133) |
Jun
(21) |
Jul
(18) |
Aug
(37) |
Sep
(97) |
Oct
(114) |
Nov
(110) |
Dec
(28) |
2007 |
Jan
(74) |
Feb
(65) |
Mar
(49) |
Apr
(76) |
May
(43) |
Jun
(15) |
Jul
(68) |
Aug
(55) |
Sep
(63) |
Oct
(59) |
Nov
(70) |
Dec
(66) |
2008 |
Jan
(71) |
Feb
(60) |
Mar
(120) |
Apr
(31) |
May
(48) |
Jun
(81) |
Jul
(107) |
Aug
(51) |
Sep
(80) |
Oct
(83) |
Nov
(83) |
Dec
(79) |
2009 |
Jan
(83) |
Feb
(110) |
Mar
(97) |
Apr
(91) |
May
(291) |
Jun
(250) |
Jul
(197) |
Aug
(58) |
Sep
(54) |
Oct
(122) |
Nov
(68) |
Dec
(34) |
2010 |
Jan
(50) |
Feb
(17) |
Mar
(63) |
Apr
(61) |
May
(84) |
Jun
(81) |
Jul
(138) |
Aug
(144) |
Sep
(78) |
Oct
(26) |
Nov
(30) |
Dec
(61) |
2011 |
Jan
(33) |
Feb
(35) |
Mar
(166) |
Apr
(221) |
May
(109) |
Jun
(76) |
Jul
(27) |
Aug
(37) |
Sep
(1) |
Oct
(4) |
Nov
(2) |
Dec
(1) |
2012 |
Jan
|
Feb
|
Mar
(2) |
Apr
(2) |
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
(1) |
Oct
|
Nov
(1) |
Dec
|
2013 |
Jan
|
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
(1) |
Sep
(3) |
Oct
(2) |
Nov
|
Dec
(1) |
2014 |
Jan
(1) |
Feb
(1) |
Mar
(3) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <pa...@us...> - 2011-06-04 05:53:36
|
Revision: 5904 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5904&view=rev Author: patearl Date: 2011-06-04 05:53:30 +0000 (Sat, 04 Jun 2011) Log Message: ----------- Don't try to set parameter locations for parameters that have been removed from the SQL. Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Param/ParametersBackTrackExtensions.cs Modified: trunk/nhibernate/src/NHibernate/Param/ParametersBackTrackExtensions.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Param/ParametersBackTrackExtensions.cs 2011-06-04 05:07:45 UTC (rev 5903) +++ trunk/nhibernate/src/NHibernate/Param/ParametersBackTrackExtensions.cs 2011-06-04 05:53:30 UTC (rev 5904) @@ -52,13 +52,16 @@ { string firstParameterId = specification.GetIdsForBackTrack(factory).First(); int[] effectiveParameterLocations = sqlQueryParametersList.GetEffectiveParameterLocations(firstParameterId).ToArray(); - int firstParamNameIndex = effectiveParameterLocations.First(); - foreach (int location in effectiveParameterLocations) + if (effectiveParameterLocations.Length > 0) // Parameters previously present might have been removed from the SQL at a later point. { - int parameterSpan = specification.ExpectedType.GetColumnSpan(factory); - for (int j = 0; j < parameterSpan; j++) + int firstParamNameIndex = effectiveParameterLocations.First(); + foreach (int location in effectiveParameterLocations) { - sqlQueryParametersList[location + j].ParameterPosition = firstParamNameIndex + j; + int parameterSpan = specification.ExpectedType.GetColumnSpan(factory); + for (int j = 0; j < parameterSpan; j++) + { + sqlQueryParametersList[location + j].ParameterPosition = firstParamNameIndex + j; + } } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pa...@us...> - 2011-06-04 05:07:51
|
Revision: 5903 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5903&view=rev Author: patearl Date: 2011-06-04 05:07:45 +0000 (Sat, 04 Jun 2011) Log Message: ----------- Hql: Minor simplification to limit string generation that keeps the bulk of the logic in one place in the code and makes it easier to convert parameter limits into constant limits later. Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/SqlGenerator.cs Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/SqlGenerator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/SqlGenerator.cs 2011-06-02 15:16:15 UTC (rev 5902) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/SqlGenerator.cs 2011-06-04 05:07:45 UTC (rev 5903) @@ -325,23 +325,6 @@ private SqlString GetSqlStringWithLimitsIfNeeded(QueryWriter queryWriter) { - SqlString sqlString = queryWriter.ToSqlString(); - var skipIsParameter = queryWriter.SkipParameter != null; - var takeIsParameter = queryWriter.TakeParameter != null; - var hqlQueryHasLimits = queryWriter.Take.HasValue || queryWriter.Skip.HasValue || skipIsParameter || takeIsParameter; - if (!hqlQueryHasLimits) - { - return sqlString; - } - - var dialect = sessionFactory.Dialect; - - // Skip-Take in HQL should be supported just for Dialect supporting variable limits at least when users use parameters for skip-take. - if (!dialect.SupportsVariableLimit && (skipIsParameter || takeIsParameter)) - { - throw new NotSupportedException("The dialect " + dialect.GetType().FullName + " does not supports variable limits"); - } - Parameter skipParameter = null; Parameter takeParameter = null; if(queryWriter.SkipParameter != null) @@ -358,8 +341,9 @@ } // We allow the user to specify either constants or parameters for their limits. - // The dialect can move the given parameters where he need, what it can't do is generates new parameters loosing the BackTrack. - return dialect.GetLimitString(sqlString, + // The dialect can move the given parameters where he need, what it can't do is generates new parameters, losing the BackTrack. + var dialect = sessionFactory.Dialect; + return dialect.GetLimitString(queryWriter.ToSqlString(), queryWriter.Skip.HasValue ? (int?) dialect.GetOffsetValue(queryWriter.Skip.Value) : null, queryWriter.Take.HasValue ? (int?) dialect.GetLimitValue(queryWriter.Skip ?? 0, queryWriter.Take.Value) : null, skipParameter, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jul...@us...> - 2011-06-02 15:16:22
|
Revision: 5902 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5902&view=rev Author: julian-maughan Date: 2011-06-02 15:16:15 +0000 (Thu, 02 Jun 2011) Log Message: ----------- Minor dialect- and dialect-related documentation corrections and improvements Modified Paths: -------------- trunk/nhibernate/doc/reference/modules/configuration.xml trunk/nhibernate/src/NHibernate/Driver/ASA10ClientDriver.cs trunk/nhibernate/src/NHibernate/Driver/ASAClientDriver.cs Modified: trunk/nhibernate/doc/reference/modules/configuration.xml =================================================================== --- trunk/nhibernate/doc/reference/modules/configuration.xml 2011-05-31 19:56:28 UTC (rev 5901) +++ trunk/nhibernate/doc/reference/modules/configuration.xml 2011-06-02 15:16:15 UTC (rev 5902) @@ -686,7 +686,7 @@ <entry></entry> </row> <row> - <entry>Oracle </entry> + <entry>Oracle</entry> <entry><literal>NHibernate.Dialect.Oracle8iDialect</literal></entry> <entry></entry> </row> @@ -701,16 +701,38 @@ <entry></entry> </row> <row> - <entry>Sybase Adaptive Server Enterprise</entry> - <entry><literal>NHibernate.Dialect.SybaseDialect</literal></entry> + <entry>Sybase Adaptive Server Enterprise 15</entry> + <entry><literal>NHibernate.Dialect.SybaseASE15Dialect</literal></entry> <entry></entry> </row> <row> - <entry>Sybase Adaptive Server Anywhere</entry> - <entry><literal>NHibernate.Dialect.SybaseAnywhereDialect</literal></entry> + <entry>Sybase Adaptive Server Anywhere 9</entry> + <entry><literal>NHibernate.Dialect.SybaseASA9Dialect</literal></entry> <entry></entry> </row> <row> + <entry>Sybase Adaptive Server Anywhere 10</entry> + <entry><literal>NHibernate.Dialect.SybaseASA10Dialect</literal></entry> + <entry> + Deprecated. Use the Sybase SQL Anywhere 10 Dialect instead. + </entry> + </row> + <row> + <entry>Sybase SQL Anywhere 10</entry> + <entry><literal>NHibernate.Dialect.SybaseSQLAnywhere10Dialect</literal></entry> + <entry></entry> + </row> + <row> + <entry>Sybase SQL Anywhere 11</entry> + <entry><literal>NHibernate.Dialect.SybaseSQLAnywhere11Dialect</literal></entry> + <entry></entry> + </row> + <row> + <entry>Microsoft SQL Server 7</entry> + <entry><literal>NHibernate.Dialect.MsSql7Dialect</literal></entry> + <entry></entry> + </row> + <row> <entry>Microsoft SQL Server 2000</entry> <entry><literal>NHibernate.Dialect.MsSql2000Dialect</literal></entry> <entry></entry> @@ -718,17 +740,16 @@ <row> <entry>Microsoft SQL Server 2005</entry> <entry><literal>NHibernate.Dialect.MsSql2005Dialect</literal></entry> - <entry> - </entry> + <entry></entry> </row> <row> - <entry>Microsoft SQL Server 2005 Everywhere Edition</entry> - <entry><literal>NHibernate.Dialect.MsSqlCeDialect</literal></entry> + <entry>Microsoft SQL Server 2008</entry> + <entry><literal>NHibernate.Dialect.MsSql2008Dialect</literal></entry> + <entry></entry> </row> <row> - <entry>Microsoft SQL Server 7</entry> - <entry><literal>NHibernate.Dialect.MsSql7Dialect</literal></entry> - <entry></entry> + <entry>Microsoft SQL Server Compact Edition</entry> + <entry><literal>NHibernate.Dialect.MsSqlCeDialect</literal></entry> </row> <row> <entry>Firebird</entry> @@ -748,11 +769,6 @@ for System.Data.SQLite provider for .NET 2.0. </entry> </row> - <row> - <entry>Ingres 3.0</entry> - <entry><literal>NHibernate.Dialect.IngresDialect</literal></entry> - <entry></entry> - </row> </tbody> </tgroup> </table> Modified: trunk/nhibernate/src/NHibernate/Driver/ASA10ClientDriver.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Driver/ASA10ClientDriver.cs 2011-05-31 19:56:28 UTC (rev 5901) +++ trunk/nhibernate/src/NHibernate/Driver/ASA10ClientDriver.cs 2011-06-02 15:16:15 UTC (rev 5902) @@ -2,7 +2,7 @@ namespace NHibernate.Driver { - [Obsolete("Please use SybaseSQLAnywhereDriver instead. This dialect will be removed in a future release.")] + [Obsolete("Please use SybaseSQLAnywhereDriver instead. This driver will be removed in a future release.")] public class ASA10ClientDriver : SybaseSQLAnywhereDriver { public ASA10ClientDriver() : base() { } Modified: trunk/nhibernate/src/NHibernate/Driver/ASAClientDriver.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Driver/ASAClientDriver.cs 2011-05-31 19:56:28 UTC (rev 5901) +++ trunk/nhibernate/src/NHibernate/Driver/ASAClientDriver.cs 2011-06-02 15:16:15 UTC (rev 5902) @@ -2,7 +2,7 @@ namespace NHibernate.Driver { - [Obsolete("Please use SybaseASADriver instead. This dialect will be removed in a future release.")] + [Obsolete("Please use SybaseAsaClientDriver instead. This driver will be removed in a future release.")] public class ASAClientDriver : SybaseAsaClientDriver { public ASAClientDriver() : base() { } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-05-31 19:56:35
|
Revision: 5901 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5901&view=rev Author: fabiomaulo Date: 2011-05-31 19:56:28 +0000 (Tue, 31 May 2011) Log Message: ----------- usage of IParameterSpecification for Criteria (step 2) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Criterion/BetweenExpression.cs trunk/nhibernate/src/NHibernate/Criterion/ConstantProjection.cs trunk/nhibernate/src/NHibernate/Criterion/ICriteriaQuery.cs trunk/nhibernate/src/NHibernate/Criterion/IdentifierEqExpression.cs trunk/nhibernate/src/NHibernate/Criterion/InExpression.cs trunk/nhibernate/src/NHibernate/Criterion/InsensitiveLikeExpression.cs trunk/nhibernate/src/NHibernate/Criterion/LikeExpression.cs trunk/nhibernate/src/NHibernate/Criterion/SimpleExpression.cs trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs trunk/nhibernate/src/NHibernate/NHibernate.csproj trunk/nhibernate/src/NHibernate.Test/Criteria/AddNumberProjection.cs Added Paths: ----------- trunk/nhibernate/src/NHibernate/Param/CriteriaNamedParameterSpecification.cs Modified: trunk/nhibernate/src/NHibernate/Criterion/BetweenExpression.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/BetweenExpression.cs 2011-05-31 17:46:14 UTC (rev 5900) +++ trunk/nhibernate/src/NHibernate/Criterion/BetweenExpression.cs 2011-05-31 19:56:28 UTC (rev 5901) @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.Linq; using NHibernate.Engine; using NHibernate.SqlCommand; +using NHibernate.Type; namespace NHibernate.Criterion { @@ -49,7 +51,9 @@ //TODO: add a default capacity SqlStringBuilder sqlBuilder = new SqlStringBuilder(); - //IType propertyType = criteriaQuery.GetTypeUsingProjection( criteria, _propertyName ); + IType[] parametersTypes = GetTypedValues(criteria, criteriaQuery).Select(x=> x.Type).ToArray(); + IType lowType = parametersTypes[0]; + IType highType = parametersTypes[1]; SqlString[] columnNames = CriterionUtil.GetColumnNames(_propertyName, _projection, criteriaQuery, criteria, enabledFilters); @@ -58,14 +62,15 @@ sqlBuilder .Add(columnNames[0]) .Add(" between ") - .Add(criteriaQuery.NewQueryParameter()) + .Add(criteriaQuery.NewQueryParameter(lowType).Single()) .Add(" and ") - .Add(criteriaQuery.NewQueryParameter()); + .Add(criteriaQuery.NewQueryParameter(highType).Single()); } else { bool andNeeded = false; + var lowParameters = criteriaQuery.NewQueryParameter(lowType).ToArray(); for (int i = 0; i < columnNames.Length; i++) { if (andNeeded) @@ -76,15 +81,16 @@ sqlBuilder.Add(columnNames[i]) .Add(" >= ") - .Add(criteriaQuery.NewQueryParameter()); + .Add(lowParameters[i]); } + var highParameters = criteriaQuery.NewQueryParameter(highType).ToArray(); for (int i = 0; i < columnNames.Length; i++) { sqlBuilder.Add(" AND ") .Add(columnNames[i]) .Add(" <= ") - .Add(criteriaQuery.NewQueryParameter()); + .Add(highParameters[i]); } } Modified: trunk/nhibernate/src/NHibernate/Criterion/ConstantProjection.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/ConstantProjection.cs 2011-05-31 17:46:14 UTC (rev 5900) +++ trunk/nhibernate/src/NHibernate/Criterion/ConstantProjection.cs 2011-05-31 19:56:28 UTC (rev 5901) @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using NHibernate.Engine; using NHibernate.SqlCommand; using NHibernate.Type; @@ -43,7 +44,7 @@ public override SqlString ToSqlString(ICriteria criteria, int position, ICriteriaQuery criteriaQuery, IDictionary<string, IFilter> enabledFilters) { return new SqlStringBuilder() - .Add(criteriaQuery.NewQueryParameter()) + .Add(criteriaQuery.NewQueryParameter(type).Single()) .Add(" as ") .Add(GetColumnAliases(position)[0]) .ToSqlString(); Modified: trunk/nhibernate/src/NHibernate/Criterion/ICriteriaQuery.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/ICriteriaQuery.cs 2011-05-31 17:46:14 UTC (rev 5900) +++ trunk/nhibernate/src/NHibernate/Criterion/ICriteriaQuery.cs 2011-05-31 19:56:28 UTC (rev 5901) @@ -1,6 +1,5 @@ using System.Collections.Generic; using NHibernate.Engine; -using NHibernate.Param; using NHibernate.SqlCommand; using NHibernate.Type; @@ -72,8 +71,9 @@ /// <summary> /// Create a new query parameter to use in a <see cref="ICriterion"/> /// </summary> + /// <param name="parameterType">The expected type of the parameter.</param> /// <returns>A new instance of a query parameter to be added to a <see cref="SqlString"/>.</returns> - Parameter NewQueryParameter(); + IEnumerable<Parameter> NewQueryParameter(IType parameterType); /// <summary> /// Creates a dummy parameter index for the supplied paged value. Modified: trunk/nhibernate/src/NHibernate/Criterion/IdentifierEqExpression.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/IdentifierEqExpression.cs 2011-05-31 17:46:14 UTC (rev 5900) +++ trunk/nhibernate/src/NHibernate/Criterion/IdentifierEqExpression.cs 2011-05-31 19:56:28 UTC (rev 5901) @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.Linq; using NHibernate.Engine; using NHibernate.SqlCommand; +using NHibernate.Type; using NHibernate.Util; namespace NHibernate.Criterion @@ -32,6 +34,8 @@ { //Implementation changed from H3.2 to use SqlString string[] columns = criteriaQuery.GetIdentifierColumns(criteria); + Parameter[] parameters = GetTypedValues(criteria, criteriaQuery).Select(x => x.Type).SelectMany(t => criteriaQuery.NewQueryParameter(t)).ToArray(); + SqlStringBuilder result = new SqlStringBuilder(4 * columns.Length + 2); if (columns.Length > 1) { @@ -48,7 +52,7 @@ result.Add(columns[i]) .Add(" = "); - AddValueOrProjection(criteria, criteriaQuery, enabledFilters, result); + AddValueOrProjection(parameters, i, criteria, criteriaQuery, enabledFilters, result); } if (columns.Length > 1) @@ -58,15 +62,15 @@ return result.ToSqlString(); } - private void AddValueOrProjection(ICriteria criteria, ICriteriaQuery criteriaQuery, IDictionary<string, IFilter> enabledFilters, SqlStringBuilder result) + private void AddValueOrProjection(Parameter[] parameters, int paramIndex, ICriteria criteria, ICriteriaQuery criteriaQuery, IDictionary<string, IFilter> enabledFilters, SqlStringBuilder result) { if (_projection == null) { - result.Add(criteriaQuery.NewQueryParameter()); + result.Add(parameters[paramIndex]); } else { - SqlString sql = _projection.ToSqlString(criteria, GetHashCode(),criteriaQuery, enabledFilters); + SqlString sql = _projection.ToSqlString(criteria, GetHashCode(), criteriaQuery, enabledFilters); result.Add(StringHelper.RemoveAsAliasesFromSql(sql)); } } Modified: trunk/nhibernate/src/NHibernate/Criterion/InExpression.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/InExpression.cs 2011-05-31 17:46:14 UTC (rev 5900) +++ trunk/nhibernate/src/NHibernate/Criterion/InExpression.cs 2011-05-31 19:56:28 UTC (rev 5901) @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Linq; using NHibernate.Engine; using NHibernate.SqlCommand; using NHibernate.Type; @@ -68,6 +69,7 @@ // Generate SqlString of the form: // columnName1 in (values) and columnName2 in (values) and ... + Parameter[] parameters = GetTypedValues(criteria, criteriaQuery).Select(x => x.Type).SelectMany(t => criteriaQuery.NewQueryParameter(t)).ToArray(); for (int columnIndex = 0; columnIndex < columnNames.Length; columnIndex++) { @@ -88,7 +90,7 @@ { result.Add(StringHelper.CommaSpace); } - result.Add(criteriaQuery.NewQueryParameter()); + result.Add(parameters[i]); } result.Add(")"); Modified: trunk/nhibernate/src/NHibernate/Criterion/InsensitiveLikeExpression.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/InsensitiveLikeExpression.cs 2011-05-31 17:46:14 UTC (rev 5900) +++ trunk/nhibernate/src/NHibernate/Criterion/InsensitiveLikeExpression.cs 2011-05-31 19:56:28 UTC (rev 5901) @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using NHibernate.Dialect; using NHibernate.Engine; using NHibernate.SqlCommand; @@ -84,7 +85,7 @@ .Add(" like "); } - sqlBuilder.Add(criteriaQuery.NewQueryParameter()); + sqlBuilder.Add(criteriaQuery.NewQueryParameter(NHibernateUtil.String).Single()); return sqlBuilder.ToSqlString(); } Modified: trunk/nhibernate/src/NHibernate/Criterion/LikeExpression.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/LikeExpression.cs 2011-05-31 17:46:14 UTC (rev 5900) +++ trunk/nhibernate/src/NHibernate/Criterion/LikeExpression.cs 2011-05-31 19:56:28 UTC (rev 5901) @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using NHibernate.Engine; using NHibernate.SqlCommand; using NHibernate.Util; @@ -79,11 +80,11 @@ lhs.Add(" like ") .Add(dialect.LowercaseFunction) .Add(StringHelper.OpenParen) - .Add(criteriaQuery.NewQueryParameter()) + .Add(criteriaQuery.NewQueryParameter(NHibernateUtil.String).Single()) .Add(StringHelper.ClosedParen); } else - lhs.Add(" like ").Add(criteriaQuery.NewQueryParameter()); + lhs.Add(" like ").Add(criteriaQuery.NewQueryParameter(NHibernateUtil.String).Single()); if (escapeChar.HasValue) lhs.Add(" escape '" + escapeChar + "'"); Modified: trunk/nhibernate/src/NHibernate/Criterion/SimpleExpression.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/SimpleExpression.cs 2011-05-31 17:46:14 UTC (rev 5900) +++ trunk/nhibernate/src/NHibernate/Criterion/SimpleExpression.cs 2011-05-31 19:56:28 UTC (rev 5901) @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.Linq; using NHibernate.Engine; using NHibernate.SqlCommand; +using NHibernate.Type; using NHibernate.Util; namespace NHibernate.Criterion @@ -86,6 +88,8 @@ this, value); + Parameter[] parameters = GetTypedValues(criteria, criteriaQuery).Select(x => x.Type).SelectMany(t => criteriaQuery.NewQueryParameter(t)).ToArray(); + if (ignoreCase) { if (columnNames.Length != 1) @@ -101,7 +105,7 @@ .Add(columnNames[0]) .Add(StringHelper.ClosedParen) .Add(Op) - .Add(criteriaQuery.NewQueryParameter()) + .Add(parameters.FirstOrDefault()) .ToSqlString(); } else @@ -117,7 +121,7 @@ sqlBuilder.Add(columnNames[i]) .Add(Op) - .Add(criteriaQuery.NewQueryParameter()); + .Add(parameters[i]); } return sqlBuilder.ToSqlString(); } Modified: trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs 2011-05-31 17:46:14 UTC (rev 5900) +++ trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs 2011-05-31 19:56:28 UTC (rev 5901) @@ -8,6 +8,7 @@ using NHibernate.Engine; using NHibernate.Hql.Util; using NHibernate.Impl; +using NHibernate.Param; using NHibernate.Persister.Collection; using NHibernate_Persister_Entity = NHibernate.Persister.Entity; using NHibernate.SqlCommand; @@ -19,10 +20,10 @@ public class CriteriaQueryTranslator : ICriteriaQuery { public static readonly string RootSqlAlias = CriteriaSpecification.RootAlias + '_'; - private static readonly IInternalLogger logger = LoggerProvider.LoggerFor(typeof(CriteriaQueryTranslator)); private const int AliasCount = 0; + private readonly string queryTranslatorId = Guid.NewGuid().ToString("N"); private readonly ICriteriaQuery outerQueryTranslator; private readonly CriteriaImpl rootCriteria; @@ -44,6 +45,7 @@ private readonly IDictionary<string, ICriteria> associationPathCriteriaMap = new LinkedHashMap<string, ICriteria>(); private readonly IDictionary<string, JoinType> associationPathJoinTypesMap = new LinkedHashMap<string, JoinType>(); private readonly IDictionary<string, ICriterion> withClauseMap = new Dictionary<string, ICriterion>(); + private readonly IList<IParameterSpecification> collectedParameterSpecifications = new List<IParameterSpecification>(); private readonly ISessionFactoryImplementor sessionFactory; private SessionFactoryHelper helper; @@ -772,9 +774,18 @@ return indexForAlias++; } - public Parameter NewQueryParameter() + public IEnumerable<Parameter> NewQueryParameter(IType parameterType) { - return Parameter.Placeholder; + // the queryTranslatorId is to avoid possible conflicts using sub-queries + string parameterName = string.Format("cr_{0}_p{1}", queryTranslatorId, collectedParameterSpecifications.Count); + var specification = new CriteriaNamedParameterSpecification(parameterName, parameterType); + collectedParameterSpecifications.Add(specification); + return specification.GetIdsForBackTrack(Factory).Select(x => + { + Parameter p = Parameter.Placeholder; + p.BackTrack = x; + return p; + }); } public int? CreatePagingParameter(int value) Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj =================================================================== --- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-05-31 17:46:14 UTC (rev 5900) +++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-05-31 19:56:28 UTC (rev 5901) @@ -496,6 +496,7 @@ <Compile Include="NonUniqueResultException.cs" /> <Compile Include="ObjectDeletedException.cs" /> <Compile Include="ObjectNotFoundException.cs" /> + <Compile Include="Param\CriteriaNamedParameterSpecification.cs" /> <Compile Include="Param\ParametersBackTrackExtensions.cs" /> <Compile Include="Param\QuerySkipParameterSpecification.cs" /> <Compile Include="Param\QueryTakeParameterSpecification.cs" /> Added: trunk/nhibernate/src/NHibernate/Param/CriteriaNamedParameterSpecification.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Param/CriteriaNamedParameterSpecification.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Param/CriteriaNamedParameterSpecification.cs 2011-05-31 19:56:28 UTC (rev 5901) @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using NHibernate.Engine; +using NHibernate.SqlCommand; +using NHibernate.Type; + +namespace NHibernate.Param +{ + public class CriteriaNamedParameterSpecification : IParameterSpecification + { + private const string CriteriaNamedParameterIdTemplate = "<criteria-nh{0}_span{1}>"; + private readonly string name; + + public CriteriaNamedParameterSpecification(string name, IType expectedType) + { + this.name = name; + ExpectedType = expectedType; + } + + #region IParameterSpecification Members + + public void Bind(IDbCommand command, IList<Parameter> sqlQueryParametersList, QueryParameters queryParameters, ISessionImplementor session) + { + TypedValue typedValue = queryParameters.NamedParameters[name]; + string backTrackId = GetIdsForBackTrack(session.Factory).First(); + foreach (int position in sqlQueryParametersList.GetEffectiveParameterLocations(backTrackId)) + { + ExpectedType.NullSafeSet(command, typedValue.Value, position, session); + } + } + + public IType ExpectedType { get; set; } + + public string RenderDisplayInfo() + { + const string format = "criteria: parameter-name={0}, expectedType={1}"; + return ExpectedType != null ? string.Format(format, name, ExpectedType) : string.Format(format, name, "Unknow"); + } + + public IEnumerable<string> GetIdsForBackTrack(IMapping sessionFactory) + { + int paremeterSpan = GetParemeterSpan(sessionFactory); + for (int i = 0; i < paremeterSpan; i++) + { + yield return string.Format(CriteriaNamedParameterIdTemplate, name, i); + } + } + + #endregion + + protected int GetParemeterSpan(IMapping sessionFactory) + { + if (sessionFactory == null) + { + throw new ArgumentNullException("sessionFactory"); + } + return ExpectedType.GetColumnSpan(sessionFactory); + } + + public override bool Equals(object obj) + { + return base.Equals(obj as CriteriaNamedParameterSpecification); + } + + public bool Equals(CriteriaNamedParameterSpecification other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + if (ReferenceEquals(this, other)) + { + return true; + } + return Equals(other.name, name); + } + + public override int GetHashCode() + { + return name.GetHashCode() ^ 211; + } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/AddNumberProjection.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Criteria/AddNumberProjection.cs 2011-05-31 17:46:14 UTC (rev 5900) +++ trunk/nhibernate/src/NHibernate.Test/Criteria/AddNumberProjection.cs 2011-05-31 19:56:28 UTC (rev 5901) @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using NHibernate.Engine; using NHibernate.Criterion; using NHibernate.SqlCommand; @@ -31,7 +32,7 @@ .Add("(") .Add(projection[0]) .Add(" + ") - .Add(criteriaQuery.NewQueryParameter()) + .Add(criteriaQuery.NewQueryParameter(NHibernateUtil.Int32).Single()) .Add(") as ") .Add(GetColumnAliases(0)[0]) .ToSqlString(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-05-31 17:46:21
|
Revision: 5900 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5900&view=rev Author: fabiomaulo Date: 2011-05-31 17:46:14 +0000 (Tue, 31 May 2011) Log Message: ----------- Starting usage of IParameterSpecification for Criteria Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Criterion/BetweenExpression.cs trunk/nhibernate/src/NHibernate/Criterion/ConstantProjection.cs trunk/nhibernate/src/NHibernate/Criterion/ICriteriaQuery.cs trunk/nhibernate/src/NHibernate/Criterion/IdentifierEqExpression.cs trunk/nhibernate/src/NHibernate/Criterion/InExpression.cs trunk/nhibernate/src/NHibernate/Criterion/InsensitiveLikeExpression.cs trunk/nhibernate/src/NHibernate/Criterion/LikeExpression.cs trunk/nhibernate/src/NHibernate/Criterion/SimpleExpression.cs trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs trunk/nhibernate/src/NHibernate/SqlCommand/SqlStringBuilder.cs trunk/nhibernate/src/NHibernate.Test/Criteria/AddNumberProjection.cs Modified: trunk/nhibernate/src/NHibernate/Criterion/BetweenExpression.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/BetweenExpression.cs 2011-05-31 17:08:07 UTC (rev 5899) +++ trunk/nhibernate/src/NHibernate/Criterion/BetweenExpression.cs 2011-05-31 17:46:14 UTC (rev 5900) @@ -58,9 +58,9 @@ sqlBuilder .Add(columnNames[0]) .Add(" between ") - .AddParameter() + .Add(criteriaQuery.NewQueryParameter()) .Add(" and ") - .AddParameter(); + .Add(criteriaQuery.NewQueryParameter()); } else { @@ -76,7 +76,7 @@ sqlBuilder.Add(columnNames[i]) .Add(" >= ") - .AddParameter(); + .Add(criteriaQuery.NewQueryParameter()); } for (int i = 0; i < columnNames.Length; i++) @@ -84,7 +84,7 @@ sqlBuilder.Add(" AND ") .Add(columnNames[i]) .Add(" <= ") - .AddParameter(); + .Add(criteriaQuery.NewQueryParameter()); } } Modified: trunk/nhibernate/src/NHibernate/Criterion/ConstantProjection.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/ConstantProjection.cs 2011-05-31 17:08:07 UTC (rev 5899) +++ trunk/nhibernate/src/NHibernate/Criterion/ConstantProjection.cs 2011-05-31 17:46:14 UTC (rev 5900) @@ -43,7 +43,7 @@ public override SqlString ToSqlString(ICriteria criteria, int position, ICriteriaQuery criteriaQuery, IDictionary<string, IFilter> enabledFilters) { return new SqlStringBuilder() - .AddParameter() + .Add(criteriaQuery.NewQueryParameter()) .Add(" as ") .Add(GetColumnAliases(position)[0]) .ToSqlString(); Modified: trunk/nhibernate/src/NHibernate/Criterion/ICriteriaQuery.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/ICriteriaQuery.cs 2011-05-31 17:08:07 UTC (rev 5899) +++ trunk/nhibernate/src/NHibernate/Criterion/ICriteriaQuery.cs 2011-05-31 17:46:14 UTC (rev 5900) @@ -1,4 +1,7 @@ +using System.Collections.Generic; using NHibernate.Engine; +using NHibernate.Param; +using NHibernate.SqlCommand; using NHibernate.Type; namespace NHibernate.Criterion @@ -67,6 +70,12 @@ int GetIndexForAlias(); /// <summary> + /// Create a new query parameter to use in a <see cref="ICriterion"/> + /// </summary> + /// <returns>A new instance of a query parameter to be added to a <see cref="SqlString"/>.</returns> + Parameter NewQueryParameter(); + + /// <summary> /// Creates a dummy parameter index for the supplied paged value. /// Returns null if the Dialect does not support limit parameters /// </summary> Modified: trunk/nhibernate/src/NHibernate/Criterion/IdentifierEqExpression.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/IdentifierEqExpression.cs 2011-05-31 17:08:07 UTC (rev 5899) +++ trunk/nhibernate/src/NHibernate/Criterion/IdentifierEqExpression.cs 2011-05-31 17:46:14 UTC (rev 5900) @@ -62,7 +62,7 @@ { if (_projection == null) { - result.AddParameter(); + result.Add(criteriaQuery.NewQueryParameter()); } else { Modified: trunk/nhibernate/src/NHibernate/Criterion/InExpression.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/InExpression.cs 2011-05-31 17:08:07 UTC (rev 5899) +++ trunk/nhibernate/src/NHibernate/Criterion/InExpression.cs 2011-05-31 17:46:14 UTC (rev 5900) @@ -88,7 +88,7 @@ { result.Add(StringHelper.CommaSpace); } - result.AddParameter(); + result.Add(criteriaQuery.NewQueryParameter()); } result.Add(")"); Modified: trunk/nhibernate/src/NHibernate/Criterion/InsensitiveLikeExpression.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/InsensitiveLikeExpression.cs 2011-05-31 17:08:07 UTC (rev 5899) +++ trunk/nhibernate/src/NHibernate/Criterion/InsensitiveLikeExpression.cs 2011-05-31 17:46:14 UTC (rev 5900) @@ -84,7 +84,7 @@ .Add(" like "); } - sqlBuilder.AddParameter(); + sqlBuilder.Add(criteriaQuery.NewQueryParameter()); return sqlBuilder.ToSqlString(); } Modified: trunk/nhibernate/src/NHibernate/Criterion/LikeExpression.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/LikeExpression.cs 2011-05-31 17:08:07 UTC (rev 5899) +++ trunk/nhibernate/src/NHibernate/Criterion/LikeExpression.cs 2011-05-31 17:46:14 UTC (rev 5900) @@ -79,11 +79,11 @@ lhs.Add(" like ") .Add(dialect.LowercaseFunction) .Add(StringHelper.OpenParen) - .AddParameter() + .Add(criteriaQuery.NewQueryParameter()) .Add(StringHelper.ClosedParen); } else - lhs.Add(" like ").AddParameter(); + lhs.Add(" like ").Add(criteriaQuery.NewQueryParameter()); if (escapeChar.HasValue) lhs.Add(" escape '" + escapeChar + "'"); Modified: trunk/nhibernate/src/NHibernate/Criterion/SimpleExpression.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/SimpleExpression.cs 2011-05-31 17:08:07 UTC (rev 5899) +++ trunk/nhibernate/src/NHibernate/Criterion/SimpleExpression.cs 2011-05-31 17:46:14 UTC (rev 5900) @@ -101,7 +101,7 @@ .Add(columnNames[0]) .Add(StringHelper.ClosedParen) .Add(Op) - .AddParameter() + .Add(criteriaQuery.NewQueryParameter()) .ToSqlString(); } else @@ -117,7 +117,7 @@ sqlBuilder.Add(columnNames[i]) .Add(Op) - .AddParameter(); + .Add(criteriaQuery.NewQueryParameter()); } return sqlBuilder.ToSqlString(); } Modified: trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs 2011-05-31 17:08:07 UTC (rev 5899) +++ trunk/nhibernate/src/NHibernate/Loader/Criteria/CriteriaQueryTranslator.cs 2011-05-31 17:46:14 UTC (rev 5900) @@ -772,6 +772,11 @@ return indexForAlias++; } + public Parameter NewQueryParameter() + { + return Parameter.Placeholder; + } + public int? CreatePagingParameter(int value) { if (!Factory.Dialect.SupportsVariableLimit) Modified: trunk/nhibernate/src/NHibernate/SqlCommand/SqlStringBuilder.cs =================================================================== --- trunk/nhibernate/src/NHibernate/SqlCommand/SqlStringBuilder.cs 2011-05-31 17:08:07 UTC (rev 5899) +++ trunk/nhibernate/src/NHibernate/SqlCommand/SqlStringBuilder.cs 2011-05-31 17:46:14 UTC (rev 5900) @@ -110,11 +110,6 @@ return Add(Parameter.Placeholder); } - public SqlStringBuilder AddParameter(int position) - { - return Add(Parameter.WithIndex(position)); - } - /// <summary> /// Attempts to discover what type of object this is and calls the appropriate /// method. Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/AddNumberProjection.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Criteria/AddNumberProjection.cs 2011-05-31 17:08:07 UTC (rev 5899) +++ trunk/nhibernate/src/NHibernate.Test/Criteria/AddNumberProjection.cs 2011-05-31 17:46:14 UTC (rev 5900) @@ -31,7 +31,7 @@ .Add("(") .Add(projection[0]) .Add(" + ") - .AddParameter() + .Add(criteriaQuery.NewQueryParameter()) .Add(") as ") .Add(GetColumnAliases(0)[0]) .ToSqlString(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-05-31 17:08:13
|
Revision: 5899 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5899&view=rev Author: fabiomaulo Date: 2011-05-31 17:08:07 +0000 (Tue, 31 May 2011) Log Message: ----------- Removed not needed code to prevent addition of meaningless Parameter Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/SqlGenerator.cs Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/SqlGenerator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/SqlGenerator.cs 2011-05-31 15:51:16 UTC (rev 5898) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/SqlGenerator.cs 2011-05-31 17:08:07 UTC (rev 5899) @@ -418,11 +418,6 @@ generator.GetStringBuilder().Add(clause); } - public void Parameter() - { - generator.GetStringBuilder().AddParameter(); - } - public void PushParameter(Parameter parameter) { generator.GetStringBuilder().Add(parameter); @@ -464,11 +459,6 @@ builder.Add(clause); } - public void Parameter() - { - builder.AddParameter(); - } - public void PushParameter(Parameter parameter) { builder.Add(parameter); @@ -533,18 +523,6 @@ } } - public void Parameter() - { - if (argInd == args.Count) - { - args.Add(new SqlString(SqlCommand.Parameter.Placeholder)); - } - else - { - args[argInd] = args[argInd].Append(new SqlString(SqlCommand.Parameter.Placeholder)); - } - } - public void PushParameter(Parameter parameter) { if (argInd == args.Count) @@ -576,7 +554,6 @@ { void Clause(string clause); void Clause(SqlString clause); - void Parameter(); void PushParameter(Parameter parameter); /** * todo remove this hack This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jul...@us...> - 2011-05-31 15:51:28
|
Revision: 5898 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5898&view=rev Author: julian-maughan Date: 2011-05-31 15:51:16 +0000 (Tue, 31 May 2011) Log Message: ----------- Test for NH-2415 Modified Paths: -------------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/BasicClassFixture.cs Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/BasicClassFixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/BasicClassFixture.cs 2011-05-31 15:06:16 UTC (rev 5897) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/BasicClassFixture.cs 2011-05-31 15:51:16 UTC (rev 5898) @@ -33,8 +33,8 @@ using (ITransaction tx = s.BeginTransaction()) { BasicClass bc = new BasicClass(); - if (!TestDialect.SupportsNullCharactersInUtfStrings) - bc.CharacterProperty = 'a'; + if (!TestDialect.SupportsNullCharactersInUtfStrings) + bc.CharacterProperty = 'a'; bc.Id = 1; bc.ValueOfPrivateField = 5; s.Save(bc); @@ -50,7 +50,7 @@ tx.Commit(); } } - + [Test] public void Caching() { @@ -58,8 +58,8 @@ using (ITransaction tx = s.BeginTransaction()) { BasicClass bc = new BasicClass(); - if (!TestDialect.SupportsNullCharactersInUtfStrings) - bc.CharacterProperty = 'a'; + if (!TestDialect.SupportsNullCharactersInUtfStrings) + bc.CharacterProperty = 'a'; bc.Id = 1; s.Save(bc); tx.Commit(); @@ -320,7 +320,7 @@ index++; - // VERIFY PREVIOUS UPDATE & PERFORM DELETE + // VERIFY PREVIOUS UPDATE & PERFORM DELETE s[index] = OpenSession(); t[index] = s[index].BeginTransaction(); @@ -385,7 +385,7 @@ index++; - // VERIFY PREVIOUS UPDATE & PERFORM DELETE + // VERIFY PREVIOUS UPDATE & PERFORM DELETE s[index] = OpenSession(); t[index] = s[index].BeginTransaction(); @@ -404,7 +404,6 @@ AssertDelete(id); } - [Test] public void TestPrimitiveArrayCRUD() { @@ -456,7 +455,7 @@ index++; - // VERIFY PREVIOUS UPDATE & PERFORM DELETE + // VERIFY PREVIOUS UPDATE & PERFORM DELETE s[index] = OpenSession(); t[index] = s[index].BeginTransaction(); @@ -526,7 +525,7 @@ index++; - // VERIFY PREVIOUS UPDATE & PERFORM DELETE + // VERIFY PREVIOUS UPDATE & PERFORM DELETE s[index] = OpenSession(); t[index] = s[index].BeginTransaction(); @@ -595,7 +594,7 @@ index++; - // VERIFY PREVIOUS UPDATE & PERFORM DELETE + // VERIFY PREVIOUS UPDATE & PERFORM DELETE s[index] = OpenSession(); t[index] = s[index].BeginTransaction(); @@ -680,7 +679,7 @@ index++; - // VERIFY PREVIOUS UPDATE & PERFORM DELETE + // VERIFY PREVIOUS UPDATE & PERFORM DELETE s[index] = OpenSession(); t[index] = s[index].BeginTransaction(); @@ -798,7 +797,7 @@ index++; - // VERIFY PREVIOUS UPDATE & PERFORM DELETE + // VERIFY PREVIOUS UPDATE & PERFORM DELETE s[index] = OpenSession(); t[index] = s[index].BeginTransaction(); @@ -823,8 +822,8 @@ ISession s = OpenSession(); ITransaction t = s.BeginTransaction(); BasicClass bc = new BasicClass(); - if (!TestDialect.SupportsNullCharactersInUtfStrings) - bc.CharacterProperty = 'a'; + if (!TestDialect.SupportsNullCharactersInUtfStrings) + bc.CharacterProperty = 'a'; int id = 1; @@ -904,6 +903,29 @@ trans.Commit(); } } + + /// <summary> + /// Test for NH-2415 + /// </summary> + [Test] + public void TestHqlParameterizedDictionaryLookupProducesCorrectSqlParameterOrder() + { + var bc = InsertBasicClass(1); + + using (var session = OpenSession()) + using (var trans = session.BeginTransaction()) + { + var hql = "from BasicClass bc where (bc.StringProperty = :prop) and (bc.StringMap[:key] = :value)"; + bc = session.CreateQuery(hql) + .SetParameter("prop", "string property") + .SetParameter("key", "keyZero") + .SetParameter("value", "string zero") + .UniqueResult<BasicClass>(); + Assert.NotNull(bc); + session.Delete(bc); + trans.Commit(); + } + } internal void AssertDelete(int id) { @@ -944,7 +966,6 @@ return bc; } - /// <summary> /// Compares the non Collection Properties of the BasicClass /// </summary> @@ -963,6 +984,7 @@ /// </summary> /// <param name="expected">The expected values.</param> /// <param name="actual">The Actual values.</param> + /// <param name="includeCollections"></param> internal void AssertPropertiesEqual(BasicClass expected, BasicClass actual, bool includeCollections) { Assert.AreEqual(expected.Id, actual.Id, "Id"); @@ -990,7 +1012,6 @@ } } - private void InitializeBasicClass(int id, ref BasicClass basicClass) { basicClass.Id = id; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-05-31 15:06:28
|
Revision: 5897 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5897&view=rev Author: fabiomaulo Date: 2011-05-31 15:06:16 +0000 (Tue, 31 May 2011) Log Message: ----------- - Fix NH-2753 - added <key> column mapping by code Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/CollectionBinder.cs trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs trunk/nhibernate/src/NHibernate/Mapping/ByCode/IListIndexMapper.cs trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/ListIndexMapper.cs trunk/nhibernate/src/NHibernate/Properties/IndexPropertyAccessor.cs trunk/nhibernate/src/NHibernate/Type/ListType.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Domain.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/FixtureUsingList.cs Modified: trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/CollectionBinder.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/CollectionBinder.cs 2011-05-31 12:12:20 UTC (rev 5896) +++ trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/CollectionBinder.cs 2011-05-31 15:06:16 UTC (rev 5897) @@ -517,6 +517,20 @@ { model.BaseIndex = Convert.ToInt32(listMapping.ListIndex.@base); } + + if (model.IsOneToMany && !model.Key.IsNullable && !model.IsInverse) + { + string entityName = ((OneToMany)model.Element).ReferencedEntityName; + PersistentClass referenced = mappings.GetClass(entityName); + var ib = new IndexBackref(); + ib.Name = '_' + model.OwnerEntityName + "." + listMapping.Name + "IndexBackref"; + ib.IsUpdateable = false; + ib.IsSelectable = false; + ib.CollectionRole = model.Role; + ib.EntityName = model.Owner.EntityName; + ib.Value = model.Index; + referenced.AddProperty(ib); + } } private void BindArraySecondPass(HbmArray arrayMapping, List model, @@ -664,6 +678,21 @@ BindIndexManyToAny(indexManyToAnyMapping, any, model.IsOneToMany); model.Index = any; } + + bool indexIsFormula = model.Index.ColumnIterator.Any(x=> x.IsFormula); + if (model.IsOneToMany && !model.Key.IsNullable && !model.IsInverse && !indexIsFormula) + { + string entityName = ((OneToMany)model.Element).ReferencedEntityName; + PersistentClass referenced = mappings.GetClass(entityName); + var ib = new IndexBackref(); + ib.Name = '_' + model.OwnerEntityName + "." + mapMapping.Name + "IndexBackref"; + ib.IsUpdateable = false; + ib.IsSelectable = false; + ib.CollectionRole = model.Role; + ib.EntityName = model.Owner.EntityName; + ib.Value = model.Index; + referenced.AddProperty(ib); + } } private void BindIndexManyToAny(HbmIndexManyToAny indexManyToAnyMapping, Any any, bool isNullable) Modified: trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs 2011-05-31 12:12:20 UTC (rev 5896) +++ trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs 2011-05-31 15:06:16 UTC (rev 5897) @@ -1191,12 +1191,12 @@ //there maybe more than one parent, filter by type if (persister.IsSubclassEntityName(entityEntry.EntityName)) { - Object index = GetIndexInParent(property, childEntity, persister, cp, parent); + object index = GetIndexInParent(property, childEntity, persister, cp, parent); if (index == null && mergeMap != null) { - Object unmergedInstance = mergeMap[parent]; - Object unmergedChild = mergeMap[childEntity]; + object unmergedInstance = mergeMap[parent]; + object unmergedChild = mergeMap[childEntity]; if (unmergedInstance != null && unmergedChild != null) { index = GetIndexInParent(property, unmergedChild, persister, cp, unmergedInstance); Modified: trunk/nhibernate/src/NHibernate/Mapping/ByCode/IListIndexMapper.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Mapping/ByCode/IListIndexMapper.cs 2011-05-31 12:12:20 UTC (rev 5896) +++ trunk/nhibernate/src/NHibernate/Mapping/ByCode/IListIndexMapper.cs 2011-05-31 15:06:16 UTC (rev 5897) @@ -1,3 +1,5 @@ +using System; + namespace NHibernate.Mapping.ByCode { public interface IListIndexMapper @@ -4,5 +6,6 @@ { void Column(string columnName); void Base(int baseIndex); + void Column(Action<IColumnMapper> columnMapper); } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/ListIndexMapper.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/ListIndexMapper.cs 2011-05-31 12:12:20 UTC (rev 5896) +++ trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/ListIndexMapper.cs 2011-05-31 15:06:16 UTC (rev 5897) @@ -1,10 +1,12 @@ using System; +using System.Linq; using NHibernate.Cfg.MappingSchema; namespace NHibernate.Mapping.ByCode.Impl { public class ListIndexMapper : IListIndexMapper { + private const string DefaultIndexColumnName = "ListIdx"; private readonly HbmListIndex mapping; private readonly System.Type ownerEntityType; @@ -18,9 +20,42 @@ public void Column(string columnName) { - mapping.column1 = columnName; + Column(x => x.Name(columnName)); } + public void Column(Action<IColumnMapper> columnMapper) + { + HbmColumn hbm = mapping.Columns.SingleOrDefault(); + hbm = hbm + ?? + new HbmColumn + { + name = mapping.column1 + }; + columnMapper(new ColumnMapper(hbm, DefaultIndexColumnName)); + if (ColumnTagIsRequired(hbm)) + { + mapping.column = hbm; + ResetColumnPlainValues(); + } + else + { + mapping.column1 = !DefaultIndexColumnName.Equals(hbm.name) ? hbm.name : null; + } + } + + private void ResetColumnPlainValues() + { + mapping.column1 = null; + } + + private bool ColumnTagIsRequired(HbmColumn hbm) + { + return hbm.length != null || hbm.precision != null || hbm.scale != null || hbm.notnull || hbm.unique + || hbm.uniquekey != null || hbm.sqltype != null || hbm.index != null || hbm.@default != null + || hbm.check != null; + } + public void Base(int baseIndex) { if (baseIndex <= 0) Modified: trunk/nhibernate/src/NHibernate/Properties/IndexPropertyAccessor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Properties/IndexPropertyAccessor.cs 2011-05-31 12:12:20 UTC (rev 5896) +++ trunk/nhibernate/src/NHibernate/Properties/IndexPropertyAccessor.cs 2011-05-31 15:06:16 UTC (rev 5897) @@ -25,12 +25,12 @@ public IGetter GetGetter(System.Type theClass, string propertyName) { - throw new NotImplementedException(); + return new IndexGetter(this); } public ISetter GetSetter(System.Type theClass, string propertyName) { - throw new NotImplementedException(); + return new IndexSetter(); } public bool CanAccessThroughReflectionOptimizer Modified: trunk/nhibernate/src/NHibernate/Type/ListType.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Type/ListType.cs 2011-05-31 12:12:20 UTC (rev 5896) +++ trunk/nhibernate/src/NHibernate/Type/ListType.cs 2011-05-31 15:06:16 UTC (rev 5897) @@ -79,8 +79,7 @@ int i = list.IndexOf(element); if (i < 0) return null; - else - return list[i]; + return i; } } } \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Domain.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Domain.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Domain.cs 2011-05-31 15:06:16 UTC (rev 5897) @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace NHibernate.Test.NHSpecificTest.NH941 +{ + public class MyClass + { + public virtual int Id { get; set; } + public virtual IList<Related> Relateds { get; set; } + } + + public class Related + { + public virtual int Id { get; set; } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs 2011-05-31 12:12:20 UTC (rev 5896) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs 2011-05-31 15:06:16 UTC (rev 5897) @@ -5,17 +5,6 @@ namespace NHibernate.Test.NHSpecificTest.NH941 { - public class MyClass - { - public virtual int Id { get; set; } - public virtual ICollection<Related> Relateds { get; set; } - } - - public class Related - { - public virtual int Id { get; set; } - } - public class Fixture : TestCaseMappingByCode { protected override HbmMapping GetMappings() Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/FixtureUsingList.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/FixtureUsingList.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/FixtureUsingList.cs 2011-05-31 15:06:16 UTC (rev 5897) @@ -0,0 +1,52 @@ +using System.Collections.Generic; +using NHibernate.Cfg.MappingSchema; +using NHibernate.Mapping.ByCode; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.NH941 +{ + public class FixtureUsingList : TestCaseMappingByCode + { + protected override HbmMapping GetMappings() + { + var mapper = new ModelMapper(); + mapper.Class<MyClass>(rc => + { + rc.Id(x => x.Id, map => map.Generator(Generators.HighLow)); + rc.List(x => x.Relateds, map => + { + map.Key(km => km.NotNullable(true)); + map.Cascade(Mapping.ByCode.Cascade.All); + map.Index(idxm=> idxm.Column(colmap=> colmap.NotNullable(true))); + }, rel => rel.OneToMany()); + }); + mapper.Class<Related>(rc => rc.Id(x => x.Id, map => map.Generator(Generators.HighLow))); + HbmMapping mappings = mapper.CompileMappingForAllExplicitAddedEntities(); + return mappings; + } + + [Test] + public void WhenSaveOneThenShouldSaveMany() + { + using (ISession session = OpenSession()) + { + using (ITransaction tx = session.BeginTransaction()) + { + var one = new MyClass(); + one.Relateds = new List<Related> {new Related(), new Related()}; + session.Persist(one); + tx.Commit(); + } + } + using (ISession session = OpenSession()) + { + using (ITransaction tx = session.BeginTransaction()) + { + session.CreateQuery("delete from Related").ExecuteUpdate(); + session.CreateQuery("delete from MyClass").ExecuteUpdate(); + tx.Commit(); + } + } + } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-05-31 12:12:20 UTC (rev 5896) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-05-31 15:06:16 UTC (rev 5897) @@ -867,7 +867,9 @@ <Compile Include="NHSpecificTest\NH2733\Model.cs" /> <Compile Include="NHSpecificTest\NH2736\Domain.cs" /> <Compile Include="NHSpecificTest\NH2736\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH941\Domain.cs" /> <Compile Include="NHSpecificTest\NH941\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH941\FixtureUsingList.cs" /> <Compile Include="NHSpecificTest\Properties\CompositePropertyRefTest.cs" /> <Compile Include="NHSpecificTest\Properties\DynamicEntityTest.cs" /> <Compile Include="NHSpecificTest\Properties\Model.cs" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-05-31 12:12:32
|
Revision: 5896 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5896&view=rev Author: fabiomaulo Date: 2011-05-31 12:12:20 +0000 (Tue, 31 May 2011) Log Message: ----------- Fix NH-941 NH-1050 Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/CollectionBinder.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs Modified: trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/CollectionBinder.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/CollectionBinder.cs 2011-05-31 03:41:20 UTC (rev 5895) +++ trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/CollectionBinder.cs 2011-05-31 12:12:20 UTC (rev 5896) @@ -760,6 +760,21 @@ } BindCache(collectionMapping.Cache, model); + + if (model.IsOneToMany && !model.IsInverse && !model.Key.IsNullable) + { + // for non-inverse one-to-many, with a not-null fk, add a backref! + string entityName = ((OneToMany)model.Element).ReferencedEntityName; + PersistentClass referenced = mappings.GetClass(entityName); + Backref prop = new Backref(); + prop.Name = '_' + model.OwnerEntityName + "." + collectionMapping.Name + "Backref"; + prop.IsUpdateable = false; + prop.IsSelectable = false; + prop.CollectionRole = model.Role; + prop.EntityName = model.Owner.EntityName; + prop.Value = model.Key; + referenced.AddProperty(prop); + } } private void BindManyToMany(HbmManyToMany manyToManyMapping, Mapping.Collection model) Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs 2011-05-31 03:41:20 UTC (rev 5895) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs 2011-05-31 12:12:20 UTC (rev 5896) @@ -16,7 +16,6 @@ public virtual int Id { get; set; } } - [Ignore("Not fixed yet")] public class Fixture : TestCaseMappingByCode { protected override HbmMapping GetMappings() @@ -27,7 +26,7 @@ rc.Id(x => x.Id, map => map.Generator(Generators.HighLow)); rc.Bag(x => x.Relateds, map => { - map.Key(km => km.Column(cm => cm.NotNullable(true))); + map.Key(km => km.NotNullable(true)); map.Cascade(Mapping.ByCode.Cascade.All); }, rel => rel.OneToMany()); }); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pa...@us...> - 2011-05-31 03:41:26
|
Revision: 5895 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5895&view=rev Author: patearl Date: 2011-05-31 03:41:20 +0000 (Tue, 31 May 2011) Log Message: ----------- Tests: Temporarily disabled a test for SQLite (NH-2752). Modified Paths: -------------- trunk/nhibernate/src/NHibernate.Test/Criteria/CriteriaQueryTest.cs Modified: trunk/nhibernate/src/NHibernate.Test/Criteria/CriteriaQueryTest.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Criteria/CriteriaQueryTest.cs 2011-05-30 22:38:01 UTC (rev 5894) +++ trunk/nhibernate/src/NHibernate.Test/Criteria/CriteriaQueryTest.cs 2011-05-31 03:41:20 UTC (rev 5895) @@ -112,6 +112,9 @@ [Test] public void AllowToSetLimitOnSubqueries() { + if (Dialect is SQLiteDialect) + Assert.Ignore("SQLite seems to have a bug related to named query parameters in subquery limit clauses."); + using (ISession session = OpenSession()) { DetachedCriteria dc = DetachedCriteria.For(typeof(Student)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-05-30 22:38:08
|
Revision: 5894 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5894&view=rev Author: fabiomaulo Date: 2011-05-30 22:38:01 +0000 (Mon, 30 May 2011) Log Message: ----------- Porting to start fix NH-941 Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Engine/Cascade.cs trunk/nhibernate/src/NHibernate/Engine/IPersistenceContext.cs trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Modified: trunk/nhibernate/src/NHibernate/Engine/Cascade.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/Cascade.cs 2011-05-30 22:28:04 UTC (rev 5893) +++ trunk/nhibernate/src/NHibernate/Engine/Cascade.cs 2011-05-30 22:38:01 UTC (rev 5894) @@ -123,7 +123,7 @@ if (style.DoCascade(action)) { - CascadeProperty(persister.GetPropertyValue(parent, i, entityMode), types[i], style, anything, false); + CascadeProperty(parent, persister.GetPropertyValue(parent, i, entityMode), types[i], style, anything, false); } else if (action.RequiresNoCascadeChecking) { @@ -136,7 +136,7 @@ } /// <summary> Cascade an action to the child or children</summary> - private void CascadeProperty(object child, IType type, CascadeStyle style, object anything, bool isCascadeDeleteEnabled) + private void CascadeProperty(object parent, object child, IType type, CascadeStyle style, object anything, bool isCascadeDeleteEnabled) { if (child != null) { @@ -145,12 +145,12 @@ IAssociationType associationType = (IAssociationType)type; if (CascadeAssociationNow(associationType)) { - CascadeAssociation(child, type, style, anything, isCascadeDeleteEnabled); + CascadeAssociation(parent, child, type, style, anything, isCascadeDeleteEnabled); } } else if (type.IsComponentType) { - CascadeComponent(child, (IAbstractComponentType)type, anything); + CascadeComponent(parent, child, (IAbstractComponentType)type, anything); } } } @@ -160,7 +160,7 @@ return associationType.ForeignKeyDirection.CascadeNow(point) && (eventSource.EntityMode != EntityMode.Xml || associationType.IsEmbeddedInXML); } - private void CascadeComponent(object child, IAbstractComponentType componentType, object anything) + private void CascadeComponent(object parent, object child, IAbstractComponentType componentType, object anything) { object[] children = componentType.GetPropertyValues(child, eventSource); IType[] types = componentType.Subtypes; @@ -169,25 +169,25 @@ CascadeStyle componentPropertyStyle = componentType.GetCascadeStyle(i); if (componentPropertyStyle.DoCascade(action)) { - CascadeProperty(children[i], types[i], componentPropertyStyle, anything, false); + CascadeProperty(parent, children[i], types[i], componentPropertyStyle, anything, false); } } } - private void CascadeAssociation(object child, IType type, CascadeStyle style, object anything, bool isCascadeDeleteEnabled) + private void CascadeAssociation(object parent, object child, IType type, CascadeStyle style, object anything, bool isCascadeDeleteEnabled) { if (type.IsEntityType || type.IsAnyType) { - CascadeToOne(child, type, style, anything, isCascadeDeleteEnabled); + CascadeToOne(parent, child, type, style, anything, isCascadeDeleteEnabled); } else if (type.IsCollectionType) { - CascadeCollection(child, style, anything, (CollectionType)type); + CascadeCollection(parent, child, style, anything, (CollectionType)type); } } /// <summary> Cascade an action to a collection</summary> - private void CascadeCollection(object child, CascadeStyle style, object anything, CollectionType type) + private void CascadeCollection(object parent, object child, CascadeStyle style, object anything, CollectionType type) { ICollectionPersister persister = eventSource.Factory.GetCollectionPersister(type.Role); IType elemType = persister.ElementType; @@ -198,24 +198,32 @@ //cascade to current collection elements if (elemType.IsEntityType || elemType.IsAnyType || elemType.IsComponentType) - CascadeCollectionElements(child, type, style, elemType, anything, persister.CascadeDeleteEnabled); + CascadeCollectionElements(parent, child, type, style, elemType, anything, persister.CascadeDeleteEnabled); point = oldCascadeTo; } /// <summary> Cascade an action to a to-one association or any type</summary> - private void CascadeToOne(object child, IType type, CascadeStyle style, object anything, bool isCascadeDeleteEnabled) + private void CascadeToOne(object parent, object child, IType type, CascadeStyle style, object anything, bool isCascadeDeleteEnabled) { string entityName = type.IsEntityType ? ((EntityType)type).GetAssociatedEntityName() : null; if (style.ReallyDoCascade(action)) { //not really necessary, but good for consistency... - action.Cascade(eventSource, child, entityName, anything, isCascadeDeleteEnabled); + eventSource.PersistenceContext.AddChildParent(child, parent); + try + { + action.Cascade(eventSource, child, entityName, anything, isCascadeDeleteEnabled); + } + finally + { + eventSource.PersistenceContext.RemoveChildParent(child); + } } } /// <summary> Cascade to the collection elements</summary> - private void CascadeCollectionElements(object child, CollectionType collectionType, CascadeStyle style, IType elemType, object anything, bool isCascadeDeleteEnabled) + private void CascadeCollectionElements(object parent, object child, CollectionType collectionType, CascadeStyle style, IType elemType, object anything, bool isCascadeDeleteEnabled) { // we can't cascade to non-embedded elements bool embeddedElements = eventSource.EntityMode != EntityMode.Xml @@ -229,7 +237,7 @@ log.Info("cascade " + action + " for collection: " + collectionType.Role); foreach (object o in action.GetCascadableChildrenIterator(eventSource, collectionType, child)) - CascadeProperty(o, elemType, style, anything, isCascadeDeleteEnabled); + CascadeProperty(parent, o, elemType, style, anything, isCascadeDeleteEnabled); log.Info("done cascade " + action + " for collection: " + collectionType.Role); } Modified: trunk/nhibernate/src/NHibernate/Engine/IPersistenceContext.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/IPersistenceContext.cs 2011-05-30 22:28:04 UTC (rev 5893) +++ trunk/nhibernate/src/NHibernate/Engine/IPersistenceContext.cs 2011-05-30 22:38:01 UTC (rev 5894) @@ -396,5 +396,18 @@ /// <summary>Is in a two-phase load? </summary> bool IsLoadFinished { get; } + + /// <summary> + /// Add child/parent relation to cache for cascading operations + /// </summary> + /// <param name="child">The child.</param> + /// <param name="parent">The parent.</param> + void AddChildParent(object child, object parent); + + /// <summary> + /// Remove child/parent relation from cache + /// </summary> + /// <param name="child">The child.</param> + void RemoveChildParent(object child); } } Modified: trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs 2011-05-30 22:28:04 UTC (rev 5893) +++ trunk/nhibernate/src/NHibernate/Engine/StatefulPersistenceContext.cs 2011-05-30 22:38:01 UTC (rev 5894) @@ -81,6 +81,11 @@ private Dictionary<CollectionKey, IPersistentCollection> unownedCollections; private bool hasNonReadOnlyEntities; + + // Parent entities cache by their child for cascading + // May be empty or not contains all relation + [NonSerialized] + private IDictionary parentsByChild; [NonSerialized] private int cascading; @@ -116,6 +121,7 @@ collectionEntries = IdentityMap.InstantiateSequenced(InitCollectionSize); collectionsByKey = new Dictionary<CollectionKey, IPersistentCollection>(InitCollectionSize); arrayHolders = IdentityMap.Instantiate(InitCollectionSize); + parentsByChild = IdentityMap.Instantiate(InitCollectionSize); nullifiableEntityKeys = new HashedSet<EntityKey>(); InitTransientState(); } @@ -279,6 +285,7 @@ { loadContexts.Cleanup(); } + parentsByChild.Clear(); } /// <summary>False if we know for certain that all the entities are read-only</summary> @@ -458,6 +465,7 @@ nullifiableEntityKeys.Remove(key); BatchFetchQueue.RemoveBatchLoadableEntityKey(key); BatchFetchQueue.RemoveSubselect(key); + parentsByChild.Clear(); return entity; } @@ -1084,21 +1092,165 @@ /// Search the persistence context for an owner for the child object, /// given a collection role /// </summary> - public object GetOwnerId(string entity, string property, object childObject, IDictionary mergeMap) + public object GetOwnerId(string entityName, string propertyName, object childEntity, IDictionary mergeMap) { - throw new NotImplementedException(); - // TODO persistent context (BackrefPropertyAccessor) + string collectionRole = entityName + '.' + propertyName; + IEntityPersister persister = session.Factory.GetEntityPersister(entityName); + ICollectionPersister collectionPersister = session.Factory.GetCollectionPersister(collectionRole); + + object parent = parentsByChild[childEntity]; + if (parent != null) + { + var entityEntry = (EntityEntry) entityEntries[parent]; + //there maybe more than one parent, filter by type + if (persister.IsSubclassEntityName(entityEntry.EntityName) && IsFoundInParent(propertyName, childEntity, persister, collectionPersister, parent)) + { + return GetEntry(parent).Id; + } + parentsByChild.Remove(childEntity); // remove wrong entry + } + + // iterate all the entities currently associated with the persistence context. + foreach (DictionaryEntry entry in entityEntries) + { + var entityEntry = (EntityEntry) entry.Value; + // does this entity entry pertain to the entity persister in which we are interested (owner)? + if (persister.IsSubclassEntityName(entityEntry.EntityName)) + { + object entityEntryInstance = entry.Key; + + //check if the managed object is the parent + bool found = IsFoundInParent(propertyName, childEntity, persister, collectionPersister, entityEntryInstance); + + if (!found && mergeMap != null) + { + //check if the detached object being merged is the parent + object unmergedInstance = mergeMap[entityEntryInstance]; + object unmergedChild = mergeMap[childEntity]; + if (unmergedInstance != null && unmergedChild != null) + { + found = IsFoundInParent(propertyName, unmergedChild, persister, collectionPersister, unmergedInstance); + } + } + + if (found) + { + return entityEntry.Id; + } + } + } + + // if we get here, it is possible that we have a proxy 'in the way' of the merge map resolution... + // NOTE: decided to put this here rather than in the above loop as I was nervous about the performance + // of the loop-in-loop especially considering this is far more likely the 'edge case' + if (mergeMap != null) + { + foreach (DictionaryEntry mergeMapEntry in mergeMap) + { + var proxy = mergeMapEntry.Key as INHibernateProxy; + if (proxy != null) + { + if (persister.IsSubclassEntityName(proxy.HibernateLazyInitializer.EntityName)) + { + bool found = IsFoundInParent(propertyName, childEntity, persister, collectionPersister, mergeMap[proxy]); + if (!found) + { + found = IsFoundInParent(propertyName, mergeMap[childEntity], persister, collectionPersister, mergeMap[proxy]); + } + if (found) + { + return proxy.HibernateLazyInitializer.Identifier; + } + } + } + } + } + + return null; } + private bool IsFoundInParent(string property, object childEntity, IEntityPersister persister, ICollectionPersister collectionPersister, object potentialParent) + { + object collection = persister.GetPropertyValue(potentialParent, property, session.EntityMode); + return collection != null && NHibernateUtil.IsInitialized(collection) && collectionPersister.CollectionType.Contains(collection, childEntity, session); + } + /// <summary> /// Search the persistence context for an index of the child object, given a collection role /// </summary> - public object GetIndexInOwner(string entity, string property, object childObject, IDictionary mergeMap) + public object GetIndexInOwner(string entity, string property, object childEntity, IDictionary mergeMap) { - throw new NotImplementedException(); - // TODO persistent context (IndexPropertyAccessor) + IEntityPersister persister = session.Factory.GetEntityPersister(entity); + ICollectionPersister cp = session.Factory.GetCollectionPersister(entity + '.' + property); + + // try cache lookup first + object parent = parentsByChild[childEntity]; + if (parent != null) + { + var entityEntry = (EntityEntry) entityEntries[parent]; + //there maybe more than one parent, filter by type + if (persister.IsSubclassEntityName(entityEntry.EntityName)) + { + Object index = GetIndexInParent(property, childEntity, persister, cp, parent); + + if (index == null && mergeMap != null) + { + Object unmergedInstance = mergeMap[parent]; + Object unmergedChild = mergeMap[childEntity]; + if (unmergedInstance != null && unmergedChild != null) + { + index = GetIndexInParent(property, unmergedChild, persister, cp, unmergedInstance); + } + } + if (index != null) + { + return index; + } + } + else + { + parentsByChild.Remove(childEntity); // remove wrong entry + } + } + + //Not found in cache, proceed + foreach (DictionaryEntry me in entityEntries) + { + var ee = (EntityEntry) me.Value; + if (persister.IsSubclassEntityName(ee.EntityName)) + { + object instance = me.Key; + object index = GetIndexInParent(property, childEntity, persister, cp, instance); + + if (index == null && mergeMap != null) + { + object unmergedInstance = mergeMap[instance]; + object unmergedChild = mergeMap[childEntity]; + if (unmergedInstance != null && unmergedChild != null) + { + index = GetIndexInParent(property, unmergedChild, persister, cp, unmergedInstance); + } + } + + if (index != null) + { + return index; + } + } + } + return null; } + private object GetIndexInParent(string property, object childEntity, IEntityPersister persister, ICollectionPersister collectionPersister, object potentialParent) + { + object collection = persister.GetPropertyValue(potentialParent, property, session.EntityMode); + if (collection != null && NHibernateUtil.IsInitialized(collection)) + { + return collectionPersister.CollectionType.IndexOf(collection, childEntity); + } + return null; + } + /// <summary> /// Record the fact that the association belonging to the keyed entity is null. /// </summary> @@ -1196,9 +1348,10 @@ object entity = tempObject; object tempObject2 = entityEntries[entity]; entityEntries.Remove(entity); - EntityEntry oldEntry = (EntityEntry) tempObject2; + var oldEntry = (EntityEntry) tempObject2; + parentsByChild.Clear(); - EntityKey newKey = new EntityKey(generatedId, oldEntry.Persister, Session.EntityMode); + var newKey = new EntityKey(generatedId, oldEntry.Persister, Session.EntityMode); AddEntity(newKey, entity); AddEntry(entity, oldEntry.Status, oldEntry.LoadedState, oldEntry.RowId, generatedId, oldEntry.Version, oldEntry.LockMode, oldEntry.ExistsInDatabase, oldEntry.Persister, oldEntry.IsBeingReplicated, @@ -1213,6 +1366,16 @@ } } + public void AddChildParent(object child, object parent) + { + parentsByChild[child] = parent; + } + + public void RemoveChildParent(object child) + { + parentsByChild.Remove(child); + } + #endregion public override string ToString() @@ -1240,6 +1403,7 @@ // collections to this session, as well as the EntityEntry and // CollectionEntry instances; these associations are transient // because serialization is used for different things. + parentsByChild = IdentityMap.Instantiate(InitCollectionSize); // TODO NH: "reconnect" EntityKey with session.factory and create a test for serialization of StatefulPersistenceContext foreach (DictionaryEntry collectionEntry in collectionEntries) Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs 2011-05-30 22:28:04 UTC (rev 5893) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs 2011-05-30 22:38:01 UTC (rev 5894) @@ -16,6 +16,7 @@ public virtual int Id { get; set; } } + [Ignore("Not fixed yet")] public class Fixture : TestCaseMappingByCode { protected override HbmMapping GetMappings() Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-05-30 22:28:04 UTC (rev 5893) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-05-30 22:38:01 UTC (rev 5894) @@ -867,6 +867,7 @@ <Compile Include="NHSpecificTest\NH2733\Model.cs" /> <Compile Include="NHSpecificTest\NH2736\Domain.cs" /> <Compile Include="NHSpecificTest\NH2736\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH941\Fixture.cs" /> <Compile Include="NHSpecificTest\Properties\CompositePropertyRefTest.cs" /> <Compile Include="NHSpecificTest\Properties\DynamicEntityTest.cs" /> <Compile Include="NHSpecificTest\Properties\Model.cs" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-05-30 22:28:10
|
Revision: 5893 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5893&view=rev Author: fabiomaulo Date: 2011-05-30 22:28:04 +0000 (Mon, 30 May 2011) Log Message: ----------- Support Unique and NotNullable for IKeyMapper Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Mapping/ByCode/IKeyMapper.cs trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/CollectionKeyCustomizer.cs trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/JoinKeyCustomizer.cs trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/JoinedSubclassKeyCustomizer.cs trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/KeyMapper.cs Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs Modified: trunk/nhibernate/src/NHibernate/Mapping/ByCode/IKeyMapper.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Mapping/ByCode/IKeyMapper.cs 2011-05-30 19:32:23 UTC (rev 5892) +++ trunk/nhibernate/src/NHibernate/Mapping/ByCode/IKeyMapper.cs 2011-05-30 22:28:04 UTC (rev 5893) @@ -15,6 +15,8 @@ void OnDelete(OnDeleteAction deleteAction); void PropertyRef(MemberInfo property); void Update(bool consideredInUpdateQuery); + void NotNullable(bool notnull); + void Unique(bool unique); /// <summary> /// Set the Foreing-Key name @@ -33,5 +35,7 @@ void PropertyRef<TProperty>(Expression<Func<TEntity, TProperty>> propertyGetter); void Update(bool consideredInUpdateQuery); void ForeignKey(string foreingKeyName); + void NotNullable(bool notnull); + void Unique(bool unique); } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/CollectionKeyCustomizer.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/CollectionKeyCustomizer.cs 2011-05-30 19:32:23 UTC (rev 5892) +++ trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/CollectionKeyCustomizer.cs 2011-05-30 22:28:04 UTC (rev 5893) @@ -55,6 +55,16 @@ CustomizersHolder.AddCustomizer(propertyPath, (ICollectionPropertiesMapper m) => m.Key(x => x.ForeignKey(foreingKeyName))); } + public void NotNullable(bool notnull) + { + CustomizersHolder.AddCustomizer(propertyPath, (ICollectionPropertiesMapper m) => m.Key(x => x.NotNullable(notnull))); + } + + public void Unique(bool unique) + { + // Do nothing (a collection with the key as unique... no thanks!) + } + #endregion } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/JoinKeyCustomizer.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/JoinKeyCustomizer.cs 2011-05-30 19:32:23 UTC (rev 5892) +++ trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/JoinKeyCustomizer.cs 2011-05-30 22:28:04 UTC (rev 5893) @@ -52,6 +52,16 @@ CustomizersHolder.AddCustomizer(typeof(TEntity), (IJoinAttributesMapper m) => m.Key(x => x.ForeignKey(foreingKeyName))); } + public void NotNullable(bool notnull) + { + CustomizersHolder.AddCustomizer(typeof(TEntity), (IJoinAttributesMapper m) => m.Key(x => x.NotNullable(notnull))); + } + + public void Unique(bool unique) + { + CustomizersHolder.AddCustomizer(typeof(TEntity), (IJoinAttributesMapper m) => m.Key(x => x.Unique(unique))); + } + #endregion } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/JoinedSubclassKeyCustomizer.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/JoinedSubclassKeyCustomizer.cs 2011-05-30 19:32:23 UTC (rev 5892) +++ trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/JoinedSubclassKeyCustomizer.cs 2011-05-30 22:28:04 UTC (rev 5893) @@ -52,6 +52,16 @@ CustomizersHolder.AddCustomizer(typeof (TEntity), (IJoinedSubclassAttributesMapper m) => m.Key(x => x.ForeignKey(foreingKeyName))); } + public void NotNullable(bool notnull) + { + CustomizersHolder.AddCustomizer(typeof(TEntity), (IJoinedSubclassAttributesMapper m) => m.Key(x => x.NotNullable(notnull))); + } + + public void Unique(bool unique) + { + CustomizersHolder.AddCustomizer(typeof(TEntity), (IJoinedSubclassAttributesMapper m) => m.Key(x => x.Unique(unique))); + } + #endregion } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/KeyMapper.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/KeyMapper.cs 2011-05-30 19:32:23 UTC (rev 5892) +++ trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/KeyMapper.cs 2011-05-30 22:28:04 UTC (rev 5893) @@ -50,8 +50,8 @@ else { mapping.column1 = !DefaultColumnName(ownerEntityType).Equals(hbm.name) ? hbm.name : null; - mapping.notnull = hbm.notnull; - mapping.unique = hbm.unique; + NotNullable(hbm.notnull); + Unique(hbm.unique); } } @@ -109,6 +109,16 @@ mapping.updateSpecified = true; } + public void NotNullable(bool notnull) + { + mapping.notnull = mapping.notnullSpecified = notnull; + } + + public void Unique(bool unique) + { + mapping.unique = mapping.uniqueSpecified = unique; + } + public void ForeignKey(string foreingKeyName) { if (foreingKeyName == null) Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH941/Fixture.cs 2011-05-30 22:28:04 UTC (rev 5893) @@ -0,0 +1,62 @@ +using System.Collections.Generic; +using NHibernate.Cfg.MappingSchema; +using NHibernate.Mapping.ByCode; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.NH941 +{ + public class MyClass + { + public virtual int Id { get; set; } + public virtual ICollection<Related> Relateds { get; set; } + } + + public class Related + { + public virtual int Id { get; set; } + } + + public class Fixture : TestCaseMappingByCode + { + protected override HbmMapping GetMappings() + { + var mapper = new ModelMapper(); + mapper.Class<MyClass>(rc => + { + rc.Id(x => x.Id, map => map.Generator(Generators.HighLow)); + rc.Bag(x => x.Relateds, map => + { + map.Key(km => km.Column(cm => cm.NotNullable(true))); + map.Cascade(Mapping.ByCode.Cascade.All); + }, rel => rel.OneToMany()); + }); + mapper.Class<Related>(rc => rc.Id(x => x.Id, map => map.Generator(Generators.HighLow))); + HbmMapping mappings = mapper.CompileMappingForAllExplicitAddedEntities(); + return mappings; + } + + [Test] + public void WhenSaveOneThenShouldSaveMany() + { + using (ISession session = OpenSession()) + { + using (ITransaction tx = session.BeginTransaction()) + { + var one = new MyClass(); + one.Relateds = new List<Related> {new Related(), new Related()}; + session.Persist(one); + tx.Commit(); + } + } + using (ISession session = OpenSession()) + { + using (ITransaction tx = session.BeginTransaction()) + { + session.CreateQuery("delete from Related").ExecuteUpdate(); + session.CreateQuery("delete from MyClass").ExecuteUpdate(); + tx.Commit(); + } + } + } + } +} \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-05-30 19:32:29
|
Revision: 5892 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5892&view=rev Author: fabiomaulo Date: 2011-05-30 19:32:23 +0000 (Mon, 30 May 2011) Log Message: ----------- Fix NH-2070 as possible Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Engine/CascadingAction.cs trunk/nhibernate/src/NHibernate/Engine/ForeignKeys.cs trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs Modified: trunk/nhibernate/src/NHibernate/Engine/CascadingAction.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/CascadingAction.cs 2011-05-30 19:14:52 UTC (rev 5891) +++ trunk/nhibernate/src/NHibernate/Engine/CascadingAction.cs 2011-05-30 19:32:23 UTC (rev 5892) @@ -377,7 +377,7 @@ string propertyName = persister.PropertyNames[propertyIndex]; throw new TransientObjectException( string.Format( - "object references an unsaved transient instance - save the transient instance before flushing: {0}.{1} -> {2}", + "object references an unsaved transient instance - save the transient instance before flushing or set cascade action for the property to something that would make it autosave: {0}.{1} -> {2}", parentEntiytName, propertyName, childEntityName)); } } Modified: trunk/nhibernate/src/NHibernate/Engine/ForeignKeys.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/ForeignKeys.cs 2011-05-30 19:14:52 UTC (rev 5891) +++ trunk/nhibernate/src/NHibernate/Engine/ForeignKeys.cs 2011-05-30 19:32:23 UTC (rev 5892) @@ -262,7 +262,8 @@ entityName = entityName ?? session.GuessEntityName(entity); string entityString = entity.ToString(); throw new TransientObjectException( - string.Format("object references an unsaved transient instance - save the transient instance before flushing. Type: {0}, Entity: {1}", entityName, entityString)); + string.Format("object references an unsaved transient instance - save the transient instance before flushing or set cascade action for the property to something that would make it autosave. Type: {0}, Entity: {1}", entityName, entityString)); + } id = session.GetEntityPersister(entityName, entity).GetIdentifier(entity, session.EntityMode); } Modified: trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs 2011-05-30 19:14:52 UTC (rev 5891) +++ trunk/nhibernate/src/NHibernate/Impl/SessionImpl.cs 2011-05-30 19:32:23 UTC (rev 5892) @@ -1318,7 +1318,7 @@ if (entry == null) { throw new TransientObjectException( - "object references an unsaved transient instance - save the transient instance before flushing: " + "object references an unsaved transient instance - save the transient instance before flushing or set cascade action for the property to something that would make it autosave: " + obj.GetType().FullName); } return entry.Persister.EntityName; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-05-30 19:14:58
|
Revision: 5891 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5891&view=rev Author: fabiomaulo Date: 2011-05-30 19:14:52 +0000 (Mon, 30 May 2011) Log Message: ----------- Test for NH-2213 (was fixed by fixing parameters stuff) Modified Paths: -------------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1742/Fixture.cs Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1742/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1742/Fixture.cs 2011-05-30 18:59:15 UTC (rev 5890) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH1742/Fixture.cs 2011-05-30 19:14:52 UTC (rev 5891) @@ -75,5 +75,23 @@ Assert.AreEqual(1, query.List<Event>().Count); } + + [Test] + public void NH2213() + { + IQuery query = session.CreateQuery("SELECT e FROM Event e " + + " inner join fetch e.descriptions d " + + " WHERE (e.SendedBy in( :dev)) " + + " AND (e.Date >= :from) " + + " AND (e.Date <= :to)" + + " ORDER BY d.Value"); + var devices = new List<Device>(); + devices.Add(device); + query.SetParameterList("dev", devices); + query.SetDateTime("from", date); + query.SetDateTime("to", date.AddMonths(1)); + + Assert.AreEqual(1, query.List<Event>().Count); + } } } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-05-30 18:59:21
|
Revision: 5890 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5890&view=rev Author: fabiomaulo Date: 2011-05-30 18:59:15 +0000 (Mon, 30 May 2011) Log Message: ----------- trivial relax Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Loader/Criteria/ComponentCollectionCriteriaInfoProvider.cs Modified: trunk/nhibernate/src/NHibernate/Loader/Criteria/ComponentCollectionCriteriaInfoProvider.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/Criteria/ComponentCollectionCriteriaInfoProvider.cs 2011-05-30 18:24:30 UTC (rev 5889) +++ trunk/nhibernate/src/NHibernate/Loader/Criteria/ComponentCollectionCriteriaInfoProvider.cs 2011-05-30 18:59:15 UTC (rev 5890) @@ -6,66 +6,64 @@ namespace NHibernate.Loader.Criteria { - public class ComponentCollectionCriteriaInfoProvider : ICriteriaInfoProvider - { - private readonly IQueryableCollection persister; - private readonly IDictionary<String, IType> subTypes = new Dictionary<string, IType>(); + public class ComponentCollectionCriteriaInfoProvider : ICriteriaInfoProvider + { + private readonly IQueryableCollection persister; + private readonly IDictionary<string, IType> subTypes = new Dictionary<string, IType>(); - public ComponentCollectionCriteriaInfoProvider(IQueryableCollection persister) - { - this.persister = persister; - if (!persister.ElementType.IsComponentType) - { - throw new ArgumentException("persister for role " + persister.Role + " is not a collection-of-component"); - } + public ComponentCollectionCriteriaInfoProvider(IQueryableCollection persister) + { + this.persister = persister; + if (!persister.ElementType.IsComponentType) + { + throw new ArgumentException("persister for role " + persister.Role + " is not a collection-of-component"); + } - var componentType = (ComponentType)persister.ElementType; - var names = componentType.PropertyNames; - var types = componentType.Subtypes; + var componentType = (IAbstractComponentType) persister.ElementType; + string[] names = componentType.PropertyNames; + IType[] types = componentType.Subtypes; - for (var i = 0; i < names.Length; i++) - { - subTypes.Add(names[i], types[i]); - } + for (int i = 0; i < names.Length; i++) + { + subTypes.Add(names[i], types[i]); + } + } - } + #region ICriteriaInfoProvider Members - public String Name - { - get - { - return persister.Role; - } - } + public String Name + { + get { return persister.Role; } + } - public string[] Spaces - { - get - { - return persister.CollectionSpaces; - } - } + public string[] Spaces + { + get { return persister.CollectionSpaces; } + } - public IPropertyMapping PropertyMapping - { - get - { - return persister; - } - } + public IPropertyMapping PropertyMapping + { + get { return persister; } + } - public IType GetType(String relativePath) - { - // TODO: can a component have a nested component? then we may need to do something more here... - if (relativePath.IndexOf('.') >= 0) - throw new ArgumentException("dotted paths not handled (yet?!) for collection-of-component"); + public IType GetType(String relativePath) + { + // TODO: can a component have a nested component? then we may need to do something more here... + if (relativePath.IndexOf('.') >= 0) + { + throw new ArgumentException("dotted paths not handled (yet?!) for collection-of-component"); + } - IType type; + IType type; - if (subTypes.TryGetValue(relativePath, out type) == false) - throw new ArgumentException("property " + relativePath + " not found in component of collection " + Name); + if (subTypes.TryGetValue(relativePath, out type) == false) + { + throw new ArgumentException("property " + relativePath + " not found in component of collection " + Name); + } - return type; - } - } + return type; + } + + #endregion + } } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-05-30 18:24:36
|
Revision: 5889 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5889&view=rev Author: fabiomaulo Date: 2011-05-30 18:24:30 +0000 (Mon, 30 May 2011) Log Message: ----------- Fix NH-2703 thanks to Roy Jacobs Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs trunk/nhibernate/src/NHibernate/Loader/OuterJoinableAssociation.cs trunk/nhibernate/src/NHibernate/NHibernate.csproj trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate/Loader/TopologicalSorter.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/Model.cs Modified: trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs 2011-05-30 17:31:39 UTC (rev 5888) +++ trunk/nhibernate/src/NHibernate/Loader/JoinWalker.cs 2011-05-30 18:24:30 UTC (rev 5889) @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Text.RegularExpressions; using Iesi.Collections.Generic; using NHibernate.Collection; using NHibernate.Engine; @@ -18,6 +19,7 @@ private readonly ISet<AssociationKey> visitedAssociationKeys = new HashedSet<AssociationKey>(); private readonly IDictionary<string, IFilter> enabledFilters; private readonly IDictionary<string, IFilter> enabledFiltersForManyToOne; + private readonly Regex aliasRegex = new Regex(@"([\w]+)\.", RegexOptions.IgnoreCase | RegexOptions.Compiled); private string[] suffixes; private string[] collectionSuffixes; @@ -110,6 +112,14 @@ get { return false; } } + public class DependentAlias + { + public string Alias { get; set; } + public string[] DependsOn { get; set; } + } + + readonly List<DependentAlias> _dependentAliases = new List<DependentAlias>(); + protected JoinWalker(ISessionFactoryImplementor factory, IDictionary<string, IFilter> enabledFilters) { this.factory = factory; @@ -149,7 +159,7 @@ OuterJoinableAssociation assoc = new OuterJoinableAssociation(type, alias, aliasedLhsColumns, subalias, joinType, GetWithClause(path), Factory, enabledFilters); assoc.ValidateJoin(path); - associations.Add(assoc); + AddAssociation(subalias, assoc); int nextDepth = currentDepth + 1; @@ -167,7 +177,65 @@ } } + private static int[] GetTopologicalSortOrder(List<DependentAlias> fields) + { + TopologicalSorter g = new TopologicalSorter(fields.Count); + Dictionary<string, int> _indexes = new Dictionary<string, int>(); + + // add vertices + for (int i = 0; i < fields.Count; i++) + { + _indexes[fields[i].Alias.ToLower()] = g.AddVertex(i); + } + + // add edges + for (int i = 0; i < fields.Count; i++) + { + if (fields[i].DependsOn != null) + { + for (int j = 0; j < fields[i].DependsOn.Length; j++) + { + var dependentField = fields[i].DependsOn[j].ToLower(); + if (_indexes.ContainsKey(dependentField)) + { + g.AddEdge(i, _indexes[dependentField]); + } + } + } + } + + return g.Sort(); + } + /// <summary> + /// Adds an association and extracts the aliases the association's 'with clause' is dependent on + /// </summary> + private void AddAssociation(string subalias, OuterJoinableAssociation association) + { + subalias = subalias.ToLower(); + + var dependencies = new List<string>(); + var on = association.On.ToString(); + if (!String.IsNullOrEmpty(on)) + { + foreach (Match match in aliasRegex.Matches(on)) + { + string alias = match.Groups[1].Value; + if (alias == subalias) continue; + dependencies.Add(alias.ToLower()); + } + } + + _dependentAliases.Add(new DependentAlias + { + Alias = subalias, + DependsOn = dependencies.ToArray() + }); + + associations.Add(association); + } + + /// <summary> /// For an entity class, return a list of associations to be fetched by outerjoin /// </summary> protected void WalkEntityTree(IOuterJoinLoadable persister, string alias) @@ -559,10 +627,18 @@ /// </summary> protected JoinFragment MergeOuterJoins(IList<OuterJoinableAssociation> associations) { + IList<OuterJoinableAssociation> sortedAssociations = new List<OuterJoinableAssociation>(); + + var indices = GetTopologicalSortOrder(_dependentAliases); + for (int index = indices.Length - 1; index >= 0; index--) + { + sortedAssociations.Add(associations[indices[index]]); + } + JoinFragment outerjoin = Dialect.CreateOuterJoinFragment(); OuterJoinableAssociation last = null; - foreach (OuterJoinableAssociation oj in associations) + foreach (OuterJoinableAssociation oj in sortedAssociations) { if (last != null && last.IsManyToManyWith(oj)) { Modified: trunk/nhibernate/src/NHibernate/Loader/OuterJoinableAssociation.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/OuterJoinableAssociation.cs 2011-05-30 17:31:39 UTC (rev 5888) +++ trunk/nhibernate/src/NHibernate/Loader/OuterJoinableAssociation.cs 2011-05-30 18:24:30 UTC (rev 5889) @@ -48,6 +48,11 @@ get { return rhsAlias; } } + public SqlString On + { + get { return on; } + } + private bool IsOneToOne { get Added: trunk/nhibernate/src/NHibernate/Loader/TopologicalSorter.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/TopologicalSorter.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Loader/TopologicalSorter.cs 2011-05-30 18:24:30 UTC (rev 5889) @@ -0,0 +1,122 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +// Algorithm from: http://tawani.blogspot.com/2009/02/topological-sorting-and-cyclic.html +namespace NHibernate.Loader +{ + class TopologicalSorter + { + #region - Private Members - + + private readonly int[] _vertices; // list of vertices + private readonly int[,] _matrix; // adjacency matrix + private int _numVerts; // current number of vertices + private readonly int[] _sortedArray; + + #endregion + + #region - CTors - + + public TopologicalSorter(int size) + { + _vertices = new int[size]; + _matrix = new int[size, size]; + _numVerts = 0; + for (int i = 0; i < size; i++) + for (int j = 0; j < size; j++) + _matrix[i, j] = 0; + _sortedArray = new int[size]; // sorted vert labels + } + + #endregion + + #region - Public Methods - + + public int AddVertex(int vertex) + { + _vertices[_numVerts++] = vertex; + return _numVerts - 1; + } + + public void AddEdge(int start, int end) + { + _matrix[start, end] = 1; + } + + public int[] Sort() // toplogical sort + { + while (_numVerts > 0) // while vertices remain, + { + // get a vertex with no successors, or -1 + int currentVertex = noSuccessors(); + if (currentVertex == -1) // must be a cycle + throw new Exception("Graph has cycles"); + + // insert vertex label in sorted array (start at end) + _sortedArray[_numVerts - 1] = _vertices[currentVertex]; + + deleteVertex(currentVertex); // delete vertex + } + + // vertices all gone; return sortedArray + return _sortedArray; + } + + #endregion + + #region - Private Helper Methods - + + // returns vert with no successors (or -1 if no such verts) + private int noSuccessors() + { + for (int row = 0; row < _numVerts; row++) + { + bool isEdge = false; // edge from row to column in adjMat + for (int col = 0; col < _numVerts; col++) + { + if (_matrix[row, col] > 0) // if edge to another, + { + isEdge = true; + break; // this vertex has a successor try another + } + } + if (!isEdge) // if no edges, has no successors + return row; + } + return -1; // no + } + + private void deleteVertex(int delVert) + { + // if not last vertex, delete from vertexList + if (delVert != _numVerts - 1) + { + for (int j = delVert; j < _numVerts - 1; j++) + _vertices[j] = _vertices[j + 1]; + + for (int row = delVert; row < _numVerts - 1; row++) + moveRowUp(row, _numVerts); + + for (int col = delVert; col < _numVerts - 1; col++) + moveColLeft(col, _numVerts - 1); + } + _numVerts--; // one less vertex + } + + private void moveRowUp(int row, int length) + { + for (int col = 0; col < length; col++) + _matrix[row, col] = _matrix[row + 1, col]; + } + + private void moveColLeft(int col, int length) + { + for (int row = 0; row < length; row++) + _matrix[row, col] = _matrix[row, col + 1]; + } + + #endregion + } +} Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj =================================================================== --- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-05-30 17:31:39 UTC (rev 5888) +++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-05-30 18:24:30 UTC (rev 5889) @@ -281,6 +281,7 @@ <Compile Include="Linq\Visitors\ResultOperatorProcessors\ProcessAggregateFromSeed.cs" /> <Compile Include="Linq\Visitors\SelectAndOrderByJoinDetector.cs" /> <Compile Include="Linq\Visitors\WhereJoinDetector.cs" /> + <Compile Include="Loader\TopologicalSorter.cs" /> <Compile Include="Loader\Loader.cs" /> <Compile Include="Loader\OuterJoinLoader.cs" /> <Compile Include="LockMode.cs" /> Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/Fixture.cs 2011-05-30 18:24:30 UTC (rev 5889) @@ -0,0 +1,76 @@ +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.NH2703 +{ + [TestFixture] + public class Fixture : BugTestCase + { + Parent RootElement = null; + + protected override void OnSetUp() + { + using (ISession session = Sfi.OpenSession()) + { + var parent = new Parent(); + parent.A.Add(new A() { PropA = "Child" }); + parent.B.Add(new B() { PropB = "Child" }); + parent.C.Add(new C() { PropC = "Child" }); + session.Persist(parent); + session.Flush(); + } + } + + protected override void OnTearDown() + { + using (ISession session = Sfi.OpenSession()) + { + session.CreateQuery("delete from A").ExecuteUpdate(); + session.CreateQuery("delete from B").ExecuteUpdate(); + session.CreateQuery("delete from C").ExecuteUpdate(); + session.CreateQuery("delete from Parent").ExecuteUpdate(); + session.Flush(); + } + base.OnTearDown(); + } + + [Test] + public void CanOuterJoinMultipleTablesWithSimpleWithClause() + { + using (ISession session = Sfi.OpenSession()) + { + IQueryOver<Parent, Parent> query = session.QueryOver(() => RootElement); + + A A_Alias = null; + B B_Alias = null; + C C_Alias = null; + query.Left.JoinQueryOver(parent => parent.C, () => C_Alias, c => c.PropC == A_Alias.PropA); + query.Left.JoinQueryOver(parent => parent.A, () => A_Alias); + query.Left.JoinQueryOver(parent => parent.B, () => B_Alias, b => b.PropB == C_Alias.PropC); + // Expected join order: a --> c --> b + + // This query should not throw + query.List(); + } + } + + [Test] + public void CanOuterJoinMultipleTablesWithComplexWithClause() + { + using (ISession session = Sfi.OpenSession()) + { + IQueryOver<Parent, Parent> query = session.QueryOver(() => RootElement); + + A A_Alias = null; + B B_Alias = null; + C C_Alias = null; + query.Left.JoinQueryOver(parent => parent.C, () => C_Alias, c => c.PropC == A_Alias.PropA && c.PropC == B_Alias.PropB); + query.Left.JoinQueryOver(parent => parent.A, () => A_Alias); + query.Left.JoinQueryOver(parent => parent.B, () => B_Alias, b => b.PropB == A_Alias.PropA); + // Expected join order: a --> b --> c + + // This query should not throw + query.List(); + } + } + } +} Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/Mappings.hbm.xml 2011-05-30 18:24:30 UTC (rev 5889) @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" + namespace="NHibernate.Test.NHSpecificTest.NH2703" + assembly="NHibernate.Test"> + + <class name="Parent" table="`Parent_Table`"> + <id name="Id"> + <generator class="native"/> + </id> + <list name="A" cascade="all"> + <key column="parent_id" /> + <index column="a_index" /> + <one-to-many class="A" /> + </list> + <list name="B" cascade="all"> + <key column="parent_id" /> + <index column="b_index" /> + <one-to-many class="B" /> + </list> + <list name="C" cascade="all"> + <key column="parent_id" /> + <index column="c_index" /> + <one-to-many class="C" /> + </list> + </class> + + <class name="A" table="`A_Table`"> + <id name="Id"> + <generator class="native"/> + </id> + <property name="PropA" type="String(15)"/> + </class> + + <class name="B" table="`B_Table`"> + <id name="Id"> + <generator class="native"/> + </id> + <property name="PropB" type="String(15)"/> + </class> + + <class name="C" table="`C_Table`"> + <id name="Id"> + <generator class="native"/> + </id> + <property name="PropC" type="String(15)"/> + </class> +</hibernate-mapping> Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/Model.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/Model.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2703/Model.cs 2011-05-30 18:24:30 UTC (rev 5889) @@ -0,0 +1,75 @@ +using System.Collections.Generic; + +namespace NHibernate.Test.NHSpecificTest.NH2703 +{ + public class Parent + { + private IList<A> a = new List<A>(); + private IList<B> b = new List<B>(); + private IList<C> c = new List<C>(); + private int id; + + public virtual IList<A> A + { + get { return a; } + set { a = value; } + } + + public virtual IList<B> B + { + get { return b; } + set { b = value; } + } + + public virtual IList<C> C + { + get { return c; } + set { c = value; } + } + + public virtual int Id + { + get { return id; } + set { id = value; } + } + } + + public class A + { + private int id; + + public virtual int Id + { + get { return id; } + set { id = value; } + } + + public virtual string PropA { get; set; } + } + + public class B + { + private int id; + + public virtual int Id + { + get { return id; } + set { id = value; } + } + + public virtual string PropB { get; set; } + } + + public class C + { + private int id; + + public virtual int Id + { + get { return id; } + set { id = value; } + } + + public virtual string PropC { get; set; } + } +} Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-05-30 17:31:39 UTC (rev 5888) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-05-30 18:24:30 UTC (rev 5889) @@ -854,6 +854,8 @@ <Compile Include="NHSpecificTest\NH2697\ArticleGroupItem.cs" /> <Compile Include="NHSpecificTest\NH2697\ArticleItem.cs" /> <Compile Include="NHSpecificTest\NH2697\SampleTest.cs" /> + <Compile Include="NHSpecificTest\NH2703\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH2703\Model.cs" /> <Compile Include="NHSpecificTest\NH2705\ItemBase.cs" /> <Compile Include="NHSpecificTest\NH2705\SubItemBase.cs" /> <Compile Include="NHSpecificTest\NH2705\SubItemDetails.cs" /> @@ -2707,6 +2709,7 @@ <EmbeddedResource Include="NHSpecificTest\NH1291AnonExample\Mappings.hbm.xml" /> </ItemGroup> <ItemGroup> + <EmbeddedResource Include="NHSpecificTest\NH2703\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2736\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2721\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2733\Mappings.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-05-30 17:31:45
|
Revision: 5888 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5888&view=rev Author: fabiomaulo Date: 2011-05-30 17:31:39 +0000 (Mon, 30 May 2011) Log Message: ----------- Fixed NH-2318 for HQL and LINQ Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Dialect/Function/AnsiTrimEmulationFunction.cs trunk/nhibernate/src/NHibernate/Param/PositionalParameterSpecification.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/Fixture.cs Modified: trunk/nhibernate/src/NHibernate/Dialect/Function/AnsiTrimEmulationFunction.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Dialect/Function/AnsiTrimEmulationFunction.cs 2011-05-30 16:50:30 UTC (rev 5887) +++ trunk/nhibernate/src/NHibernate/Dialect/Function/AnsiTrimEmulationFunction.cs 2011-05-30 17:31:39 UTC (rev 5888) @@ -111,7 +111,7 @@ // are present and "do the right thing" bool leading = true; // should leading trim-characters be trimmed? bool trailing = true; // should trailing trim-characters be trimmed? - string trimCharacter = null; // the trim-character + object trimCharacter = null; // the trim-character object trimSource = null; // the trim-source // potentialTrimCharacterArgIndex = 1 assumes that a @@ -147,7 +147,7 @@ } else { - trimCharacter = potentialTrimCharacter.ToString(); + trimCharacter = potentialTrimCharacter; if (StringHelper.EqualsCaseInsensitive("from", args[potentialTrimCharacterArgIndex + 1].ToString())) { trimSource = args[potentialTrimCharacterArgIndex + 2]; @@ -158,9 +158,7 @@ } } - IList argsToUse = new List<object>(); - argsToUse.Add(trimSource); - argsToUse.Add(trimCharacter); + IList argsToUse = new List<object> {trimSource, trimCharacter}; if (trimCharacter.Equals("' '")) { Modified: trunk/nhibernate/src/NHibernate/Param/PositionalParameterSpecification.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Param/PositionalParameterSpecification.cs 2011-05-30 16:50:30 UTC (rev 5887) +++ trunk/nhibernate/src/NHibernate/Param/PositionalParameterSpecification.cs 2011-05-30 17:31:39 UTC (rev 5888) @@ -56,8 +56,11 @@ object value = queryParameters.PositionalParameterValues[hqlPosition]; string backTrackId = GetIdsForBackTrack(session.Factory).First(); // just the first because IType suppose the oders in certain sequence - int position = sqlQueryParametersList.GetEffectiveParameterLocations(backTrackId).Single(); // an HQL positional parameter can't appear more than once - type.NullSafeSet(command, value, position, session); + // an HQL positional parameter can appear more than once because a custom HQL-Function can duplicate it + foreach (int position in sqlQueryParametersList.GetEffectiveParameterLocations(backTrackId)) + { + type.NullSafeSet(command, value, position, session); + } } public override void SetEffectiveType(QueryParameters queryParameters) Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/Fixture.cs 2011-05-30 16:50:30 UTC (rev 5887) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/Fixture.cs 2011-05-30 17:31:39 UTC (rev 5888) @@ -70,7 +70,6 @@ } [Test] - [Ignore] public void LinqTrimFunctionsWithParameters() { AddObjects(); @@ -94,7 +93,6 @@ } [Test] - [Ignore] public void HqlTrimFunctionsWithParameters() { AddObjects(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-05-30 16:50:36
|
Revision: 5887 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5887&view=rev Author: fabiomaulo Date: 2011-05-30 16:50:30 +0000 (Mon, 30 May 2011) Log Message: ----------- Fix NH-2328, NH-2741 (thanks to Andrei Alecu, patch applied with modifications) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/BinaryLogicOperatorNode.cs trunk/nhibernate/src/NHibernate/Type/MetaType.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2328/Fixture.cs Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/BinaryLogicOperatorNode.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/BinaryLogicOperatorNode.cs 2011-05-30 16:33:17 UTC (rev 5886) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/BinaryLogicOperatorNode.cs 2011-05-30 16:50:30 UTC (rev 5887) @@ -6,6 +6,7 @@ using NHibernate.Param; using NHibernate.SqlCommand; using NHibernate.Type; +using NHibernate.Util; namespace NHibernate.Hql.Ast.ANTLR.Tree { @@ -50,7 +51,7 @@ { throw new SemanticException( "right-hand operand of a binary operator was null" ); } - + ProcessMetaTypeDiscriminatorIfNecessary(lhs, rhs); IType lhsType = ExtractDataType( lhs ); IType rhsType = ExtractDataType( rhs ); @@ -265,5 +266,40 @@ return type; } + + private void ProcessMetaTypeDiscriminatorIfNecessary(IASTNode lhs, IASTNode rhs) + { + // this method inserts the discriminator value for the rhs node so that .class queries on <any> mappings work with the class name + var lhsNode = lhs as SqlNode; + var rhsNode = rhs as SqlNode; + if (lhsNode == null || rhsNode == null) + { + return; + } + if (rhsNode.Text == null) + { + var lhsNodeMetaType = lhsNode.DataType as MetaType; + if (lhsNodeMetaType != null) + { + string className = SessionFactoryHelper.GetImportedClassName(rhsNode.OriginalText); + + object discriminatorValue = lhsNodeMetaType.GetMetaValue(TypeNameParser.Parse(className).Type); + rhsNode.Text = discriminatorValue.ToString(); + return; + } + } + if (lhsNode.Text == null) + { + var rhsNodeMetaType = rhsNode.DataType as MetaType; + if (rhsNodeMetaType != null) + { + string className = SessionFactoryHelper.GetImportedClassName(lhsNode.OriginalText); + + object discriminatorValue = rhsNodeMetaType.GetMetaValue(TypeNameParser.Parse(className).Type); + lhsNode.Text = discriminatorValue.ToString(); + return; + } + } + } } } Modified: trunk/nhibernate/src/NHibernate/Type/MetaType.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Type/MetaType.cs 2011-05-30 16:33:17 UTC (rev 5886) +++ trunk/nhibernate/src/NHibernate/Type/MetaType.cs 2011-05-30 16:50:30 UTC (rev 5887) @@ -117,5 +117,9 @@ return (string)value; //value is the entity name } + internal object GetMetaValue(string className) + { + return keys[className]; + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2328/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2328/Fixture.cs 2011-05-30 16:33:17 UTC (rev 5886) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2328/Fixture.cs 2011-05-30 16:50:30 UTC (rev 5887) @@ -56,7 +56,6 @@ } [Test] - [Ignore("VisitTypeBinaryExpression generates HQL tree with string constant, but DB has a number")] public void AnyIs_Linq() { using (ISession s = OpenSession()) @@ -72,18 +71,31 @@ } [Test] - [Description("Is this right? - the HQL translation should turn the class-string to an int, not the user?")] - public void AnyIs_HqlRequiresNumberIn() + public void AnyIs_HqlWorksWithClassNameInTheRight() { using (ISession s = OpenSession()) { var boxes = - s.CreateQuery("from ToyBox t where t.Shape.class = 2") + s.CreateQuery("from ToyBox t where t.Shape.class = Square") .List<ToyBox>(); Assert.That(boxes.Count, Is.EqualTo(1)); Assert.That(boxes[0].Name, Is.EqualTo("Box2")); } } + + [Test] + public void AnyIs_HqlWorksWithClassNameInTheLeft() + { + using (ISession s = OpenSession()) + { + var boxes = + s.CreateQuery("from ToyBox t where Square = t.Shape.class") + .List<ToyBox>(); + + Assert.That(boxes.Count, Is.EqualTo(1)); + Assert.That(boxes[0].Name, Is.EqualTo("Box2")); + } + } } } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pa...@us...> - 2011-05-30 16:33:23
|
Revision: 5886 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5886&view=rev Author: patearl Date: 2011-05-30 16:33:17 +0000 (Mon, 30 May 2011) Log Message: ----------- NH-2318: Added missing file. Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/A.cs Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/A.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/A.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/A.cs 2011-05-30 16:33:17 UTC (rev 5886) @@ -0,0 +1,23 @@ +using System; +using System.Collections; + +namespace NHibernate.Test.NHSpecificTest.NH2318 +{ + public class A + { + private int? _id; + private string _name; + + public int? Id + { + get { return _id; } + set { _id = value; } + } + + public string Name + { + get { return _name; } + set { _name = value; } + } + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pa...@us...> - 2011-05-30 16:22:32
|
Revision: 5885 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5885&view=rev Author: patearl Date: 2011-05-30 16:22:26 +0000 (Mon, 30 May 2011) Log Message: ----------- NH-2318: Added failing tests. Modified Paths: -------------- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/LinqMapping.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/Mappings.hbm.xml Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/Fixture.cs 2011-05-30 16:22:26 UTC (rev 5885) @@ -0,0 +1,151 @@ +using System; +using System.Collections.Generic; +using NHibernate.Criterion; +using NUnit.Framework; +using NHibernate.Linq; +using System.Linq; +using NHibernate.Linq.Functions; + +namespace NHibernate.Test.NHSpecificTest.NH2318 +{ + [TestFixture] + public class Fixture : BugTestCase + { + protected override void Configure(Cfg.Configuration configuration) + { + base.Configure(configuration); + configuration.SetProperty("linqtohql.generatorsregistry", "NHibernate.Test.NHSpecificTest.NH2318.ExtendedLinqtoHqlGeneratorsRegistry, NHibernate.Test"); + } + + protected override void OnTearDown() + { + using( ISession s = sessions.OpenSession() ) + { + s.Delete( "from A" ); + s.Flush(); + } + } + + private void AddObjects() + { + ISession s = OpenSession(); + try + { + s.Save(new A { Name = "first" }); + s.Save(new A { Name = "second" }); + s.Save(new A { Name = "aba" }); + s.Flush(); + } + finally + { + s.Close(); + } + } + + [Test] + [Ignore] + public void CriteriaTrimFunctionsWithParameters() + { + AddObjects(); + + ISession s = OpenSession(); + try + { + ICriteria criteria = s.CreateCriteria(typeof (A)).Add( + Restrictions.Eq( + Projections.SqlFunction( + "trim", + NHibernateUtil.String, + Projections.Constant("f"), + Projections.Property("Name")), + "irst")); + IList<A> items = criteria.List<A>(); + Assert.AreEqual(1, items.Count); + Assert.AreEqual("first", items[0].Name); + } + finally + { + s.Close(); + } + } + + [Test] + [Ignore] + public void LinqTrimFunctionsWithParameters() + { + AddObjects(); + + ISession s = OpenSession(); + try + { + IList<A> items = s.Query<A>().Where(a => a.Name.TrimLeading("f").TrimTrailing("t") == "irs").ToList(); + Assert.AreEqual(1, items.Count); + Assert.AreEqual("first", items[0].Name); + + string trimString = "a"; + items = s.Query<A>().Where(a => a.Name.TrimLeading(trimString).TrimTrailing(trimString) == "b").ToList(); + Assert.AreEqual(1, items.Count); + Assert.AreEqual("aba", items[0].Name); + } + finally + { + s.Close(); + } + } + + [Test] + [Ignore] + public void HqlTrimFunctionsWithParameters() + { + AddObjects(); + + ISession s = OpenSession(); + try + { + IList<A> items = s.CreateQuery("from A a where a.Name = :p0 or a.Name <> :p0 order by a.Name").SetParameter("p0", "first").List<A>(); + Assert.AreEqual(3, items.Count); + Assert.AreEqual("aba", items[0].Name); + Assert.AreEqual("first", items[1].Name); + Assert.AreEqual("second", items[2].Name); + + items = s.CreateQuery("from A a where a.Name = ? or a.Name <> ? order by a.Name").SetParameter(0, "first").SetParameter(1, "first").List<A>(); + Assert.AreEqual(3, items.Count); + Assert.AreEqual("aba", items[0].Name); + Assert.AreEqual("first", items[1].Name); + Assert.AreEqual("second", items[2].Name); + + items = s.CreateQuery("from A a where TRIM(LEADING :p0 FROM a.Name) = 'irst'").SetParameter("p0", "f").List<A>(); + Assert.AreEqual(1, items.Count); + Assert.AreEqual("first", items[0].Name); + + items = s.CreateQuery("from A a where TRIM(TRAILING :p0 FROM TRIM(LEADING :p1 FROM a.Name)) = 'irs'").SetParameter("p0", "t").SetParameter("p1", "f").List<A>(); + Assert.AreEqual(1, items.Count); + Assert.AreEqual("first", items[0].Name); + + items = s.CreateQuery("from A a where TRIM(TRAILING :p0 FROM TRIM(LEADING :p0 FROM a.Name)) = 'b'").SetParameter("p0", "a").List<A>(); + Assert.AreEqual(1, items.Count); + Assert.AreEqual("aba", items[0].Name); + + items = s.CreateQuery("from A a where TRIM(TRAILING :p0 FROM a.Name) = 'firs'").SetParameter("p0", "t").List<A>(); + Assert.AreEqual(1, items.Count); + Assert.AreEqual("first", items[0].Name); + + items = s.CreateQuery("from A a where TRIM(LEADING ? FROM a.Name) = 'irst'").SetParameter(0, "f").List<A>(); + Assert.AreEqual(1, items.Count); + Assert.AreEqual("first", items[0].Name); + + items = s.CreateQuery("from A a where TRIM(TRAILING ? FROM a.Name) = 'firs'").SetParameter(0, "t").List<A>(); + Assert.AreEqual(1, items.Count); + Assert.AreEqual("first", items[0].Name); + + items = s.CreateQuery("from A a where TRIM(TRAILING ? FROM TRIM(LEADING ? FROM a.Name)) = 'irs'").SetParameter(0, "t").SetParameter(1, "f").List<A>(); + Assert.AreEqual(1, items.Count); + Assert.AreEqual("first", items[0].Name); + } + finally + { + s.Close(); + } + } + } +} Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/LinqMapping.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/LinqMapping.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/LinqMapping.cs 2011-05-30 16:22:26 UTC (rev 5885) @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using NHibernate.Hql.Ast; +using NHibernate.Linq; +using NHibernate.Linq.Functions; +using NHibernate.Linq.Visitors; + +namespace NHibernate.Test.NHSpecificTest.NH2318 +{ + public static class TrimExtensions + { + public static string TrimLeading(this string source, string trim) + { + // Bogus implementation so we know for sure it's the database doing the work. + throw new NotImplementedException(); + } + + public static string TrimTrailing(this string source, string trim) + { + // Bogus implementation so we know for sure it's the database doing the work. + throw new NotImplementedException(); + } + } + public class TrimGenerator : BaseHqlGeneratorForMethod + { + public TrimGenerator() + { + SupportedMethods = new[] { + ReflectionHelper.GetMethodDefinition(() => TrimExtensions.TrimLeading(null, null)), + ReflectionHelper.GetMethodDefinition(() => TrimExtensions.TrimTrailing(null, null)), + }; + } + + public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor) + { + string leadingOrTrailing = "TRAILING"; + if (method.Name == "TrimLeading") + leadingOrTrailing = "LEADING"; + + return treeBuilder.MethodCall("Trim", + treeBuilder.Ident(leadingOrTrailing), + visitor.Visit(arguments[1]).AsExpression(), + treeBuilder.Ident("FROM"), + visitor.Visit(arguments[0]).AsExpression()); + } + } + + public class ExtendedLinqtoHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry + { + public ExtendedLinqtoHqlGeneratorsRegistry() + { + this.Merge(new TrimGenerator()); + } + } +} Added: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/Mappings.hbm.xml (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2318/Mappings.hbm.xml 2011-05-30 16:22:26 UTC (rev 5885) @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" ?> +<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernate.Test" namespace="NHibernate.Test.NHSpecificTest.NH2318"> + <class name="A" table="a" lazy="false"> + <id name="Id" column="id" unsaved-value="null"> + <generator class="native" /> + </id> + <property name="Name" column="aname" /> + </class> +</hibernate-mapping> Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-05-30 16:11:57 UTC (rev 5884) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-05-30 16:22:26 UTC (rev 5885) @@ -731,6 +731,9 @@ <Compile Include="NHSpecificTest\NH2313\Fixture.cs" /> <Compile Include="NHSpecificTest\NH2317\Domain.cs" /> <Compile Include="NHSpecificTest\NH2317\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH2318\A.cs" /> + <Compile Include="NHSpecificTest\NH2318\Fixture.cs" /> + <Compile Include="NHSpecificTest\NH2318\LinqMapping.cs" /> <Compile Include="NHSpecificTest\NH2322\Fixture.cs" /> <Compile Include="NHSpecificTest\NH2322\Model.cs" /> <Compile Include="NHSpecificTest\NH2322\PostUpdateEventListener.cs" /> @@ -2753,6 +2756,7 @@ <EmbeddedResource Include="NHSpecificTest\NH2362\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2244\Mappings.hbm.xml" /> <EmbeddedResource Include="NHSpecificTest\NH2394\Mappings.hbm.xml" /> + <EmbeddedResource Include="NHSpecificTest\NH2318\Mappings.hbm.xml" /> <EmbeddedResource Include="DynamicEntity\Interceptor\Customer.hbm.xml" /> <EmbeddedResource Include="Any\Person.hbm.xml" /> <EmbeddedResource Include="Any\Properties.hbm.xml" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-05-30 16:12:03
|
Revision: 5884 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5884&view=rev Author: fabiomaulo Date: 2011-05-30 16:11:57 +0000 (Mon, 30 May 2011) Log Message: ----------- Fix NH-2738 Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Type/TypeFactory.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/MappingByCode/IntegrationTests/NH2738/ trunk/nhibernate/src/NHibernate.Test/MappingByCode/IntegrationTests/NH2738/Fixture.cs Modified: trunk/nhibernate/src/NHibernate/Type/TypeFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Type/TypeFactory.cs 2011-05-30 15:31:30 UTC (rev 5883) +++ trunk/nhibernate/src/NHibernate/Type/TypeFactory.cs 2011-05-30 16:11:57 UTC (rev 5884) @@ -517,11 +517,25 @@ } else if (typeClass.IsEnum) { - type = (IType) Activator.CreateInstance(typeof (EnumType<>).MakeGenericType(typeClass)); + try + { + type = (IType)Activator.CreateInstance(typeof(EnumType<>).MakeGenericType(typeClass)); + } + catch (Exception e) + { + throw new MappingException("Can't instantiate enum "+ typeClass.FullName +"; The enum can't be empty", e); + } } else if (IsNullableEnum(typeClass)) { - type = (IType)Activator.CreateInstance(typeof(EnumType<>).MakeGenericType(typeClass.GetGenericArguments()[0])); + try + { + type = (IType)Activator.CreateInstance(typeof(EnumType<>).MakeGenericType(typeClass.GetGenericArguments()[0])); + } + catch (Exception e) + { + throw new MappingException("Can't instantiate enum " + typeClass.FullName + "; The enum can't be empty", e); + } } else if (typeClass.IsSerializable) { Added: trunk/nhibernate/src/NHibernate.Test/MappingByCode/IntegrationTests/NH2738/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/MappingByCode/IntegrationTests/NH2738/Fixture.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/MappingByCode/IntegrationTests/NH2738/Fixture.cs 2011-05-30 16:11:57 UTC (rev 5884) @@ -0,0 +1,35 @@ +using NHibernate.Mapping.ByCode; +using NUnit.Framework; +using SharpTestsEx; + +namespace NHibernate.Test.MappingByCode.IntegrationTests.NH2738 +{ + public enum MyEmptyEnum + { + + } + + public class MyClass + { + public virtual int Id { get; set; } + public MyEmptyEnum MyEmptyEnum { get; set; } + } + public class Fixture + { + [Test] + public void WhenMapEmptyEnumThenThrowsExplicitException() + { + var mapper = new ModelMapper(); + mapper.Class<MyClass>(rc => + { + rc.Id(x => x.Id); + rc.Property(x => x.MyEmptyEnum); + }); + var mappings = mapper.CompileMappingForAllExplicitAddedEntities(); + var conf = TestConfigurationHelper.GetDefaultConfiguration(); + conf.AddMapping(mappings); + + conf.Executing(c => c.BuildSessionFactory()).Throws<MappingException>().And.ValueOf.Message.Should().Contain("MyEmptyEnum"); + } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-05-30 15:31:30 UTC (rev 5883) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-05-30 16:11:57 UTC (rev 5884) @@ -557,6 +557,7 @@ <Compile Include="MappingByCode\IntegrationTests\NH2728\IAnimal.cs" /> <Compile Include="MappingByCode\IntegrationTests\NH2728\SampleTest.cs" /> <Compile Include="MappingByCode\IntegrationTests\NH2728\Toy.cs" /> + <Compile Include="MappingByCode\IntegrationTests\NH2738\Fixture.cs" /> <Compile Include="MappingByCode\MappersTests\AnyMapperTest.cs" /> <Compile Include="MappingByCode\MappersTests\IdMapperTest.cs" /> <Compile Include="MappingByCode\MappersTests\ManyToOneMapperTest.cs" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-05-30 15:31:36
|
Revision: 5883 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5883&view=rev Author: fabiomaulo Date: 2011-05-30 15:31:30 +0000 (Mon, 30 May 2011) Log Message: ----------- Minor (public default ctor) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Type/BinaryBlobType.cs Modified: trunk/nhibernate/src/NHibernate/Type/BinaryBlobType.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Type/BinaryBlobType.cs 2011-05-30 14:04:09 UTC (rev 5882) +++ trunk/nhibernate/src/NHibernate/Type/BinaryBlobType.cs 2011-05-30 15:31:30 UTC (rev 5883) @@ -14,7 +14,7 @@ [Serializable] public class BinaryBlobType : BinaryType { - internal BinaryBlobType(): base(new BinaryBlobSqlType()) {} + public BinaryBlobType(): base(new BinaryBlobSqlType()) {} internal BinaryBlobType(BinarySqlType sqlType) : base(sqlType) {} /// <summary></summary> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-05-30 14:04:15
|
Revision: 5882 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5882&view=rev Author: fabiomaulo Date: 2011-05-30 14:04:09 +0000 (Mon, 30 May 2011) Log Message: ----------- Current version of the trunk Modified Paths: -------------- trunk/nhibernate/build-common/common.xml Modified: trunk/nhibernate/build-common/common.xml =================================================================== --- trunk/nhibernate/build-common/common.xml 2011-05-30 13:58:24 UTC (rev 5881) +++ trunk/nhibernate/build-common/common.xml 2011-05-30 14:04:09 UTC (rev 5882) @@ -84,7 +84,7 @@ effectively SP0). --> - <property name="project.version" value="3.2.0.CR1" overwrite="false" /> + <property name="project.version" value="3.2.0.Beta2" overwrite="false" /> <!-- Compute short project version (major.minor) using a regex --> <regex input="${project.version}" pattern="^(?'shortversion'\d+\.\d+)" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fab...@us...> - 2011-05-30 13:58:33
|
Revision: 5881 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5881&view=rev Author: fabiomaulo Date: 2011-05-30 13:58:24 +0000 (Mon, 30 May 2011) Log Message: ----------- - Fix NH-2736 - refactoring of sql-parameters managements for HQL-LINQ Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Engine/JoinSequence.cs trunk/nhibernate/src/NHibernate/Engine/QueryParameters.cs trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/BasicExecutor.cs trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/MultiTableDeleteExecutor.cs trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/MultiTableUpdateExecutor.cs trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/HqlSqlWalker.cs trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/SqlGenerator.cs trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/BinaryLogicOperatorNode.cs trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/FromElement.cs trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/SqlFragment.cs trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Util/JoinProcessor.cs trunk/nhibernate/src/NHibernate/NHibernate.csproj trunk/nhibernate/src/NHibernate/Param/AbstractExplicitParameterSpecification.cs trunk/nhibernate/src/NHibernate/Param/AggregatedIndexCollectionSelectorParameterSpecifications.cs trunk/nhibernate/src/NHibernate/Param/CollectionFilterKeyParameterSpecification.cs trunk/nhibernate/src/NHibernate/Param/DynamicFilterParameterSpecification.cs trunk/nhibernate/src/NHibernate/Param/IExplicitParameterSpecification.cs trunk/nhibernate/src/NHibernate/Param/IParameterSpecification.cs trunk/nhibernate/src/NHibernate/Param/NamedParameterSpecification.cs trunk/nhibernate/src/NHibernate/Param/PositionalParameterSpecification.cs trunk/nhibernate/src/NHibernate/Param/VersionTypeSeedParameterSpecification.cs trunk/nhibernate/src/NHibernate/SqlCommand/Parameter.cs trunk/nhibernate/src/NHibernate/SqlCommand/SqlString.cs trunk/nhibernate/src/NHibernate.Test/Linq/FunctionTests.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj trunk/nhibernate/src/NHibernate.Test/SqlCommandTest/SqlStringFixture.cs Added Paths: ----------- trunk/nhibernate/src/NHibernate/Param/ParametersBackTrackExtensions.cs trunk/nhibernate/src/NHibernate/Param/QuerySkipParameterSpecification.cs trunk/nhibernate/src/NHibernate/Param/QueryTakeParameterSpecification.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2736/ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2736/Domain.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2736/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2736/Mappings.hbm.xml Modified: trunk/nhibernate/src/NHibernate/Engine/JoinSequence.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/JoinSequence.cs 2011-05-29 18:36:56 UTC (rev 5880) +++ trunk/nhibernate/src/NHibernate/Engine/JoinSequence.cs 2011-05-30 13:58:24 UTC (rev 5881) @@ -139,7 +139,7 @@ public JoinFragment ToJoinFragment( IDictionary<string, IFilter> enabledFilters, bool includeExtraJoins, - string withClauseFragment, + SqlString withClauseFragment, string withClauseJoinAlias) { QueryJoinFragment joinFragment = new QueryJoinFragment(factory.Dialect, useThetaStyle); @@ -164,7 +164,7 @@ { Join join = joins[i]; string on = join.AssociationType.GetOnCondition(join.Alias, factory, enabledFilters); - string condition; + SqlString condition = new SqlString(); if (last != null && IsManyToManyRoot(last) && ((IQueryableCollection)last).ElementType == join.AssociationType) @@ -174,36 +174,38 @@ // defined specifically on the many-to-many string manyToManyFilter = ((IQueryableCollection)last) .GetManyToManyFilterFragment(join.Alias, enabledFilters); - condition = "".Equals(manyToManyFilter) + condition = new SqlString("".Equals(manyToManyFilter) ? on : "".Equals(on) ? manyToManyFilter - : on + " and " + manyToManyFilter; + : on + " and " + manyToManyFilter); } else { // NH Different behavior : NH1179 and NH1293 // Apply filters in Many-To-One association var enabledForManyToOne = FilterHelper.GetEnabledForManyToOne(enabledFilters); - condition = string.IsNullOrEmpty(on) && enabledForManyToOne.Count > 0 + condition = new SqlString(string.IsNullOrEmpty(on) && enabledForManyToOne.Count > 0 ? join.Joinable.FilterFragment(join.Alias, enabledForManyToOne) - : on; + : on); } if (withClauseFragment != null) { if (join.Alias.Equals(withClauseJoinAlias)) { - condition += " and " + withClauseFragment; + condition = condition.Append(" and ").Append(withClauseFragment); } } + + // NH: the variable "condition" have to be a SqlString because it may contains Parameter instances with BackTrack joinFragment.AddJoin( join.Joinable.TableName, join.Alias, join.LHSColumns, JoinHelper.GetRHSColumnNames(join.AssociationType, factory), join.JoinType, - new SqlString(condition) + condition ); if (includeExtraJoins) { Modified: trunk/nhibernate/src/NHibernate/Engine/QueryParameters.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Engine/QueryParameters.cs 2011-05-29 18:36:56 UTC (rev 5880) +++ trunk/nhibernate/src/NHibernate/Engine/QueryParameters.cs 2011-05-30 13:58:24 UTC (rev 5881) @@ -324,7 +324,7 @@ { if (part is Parameter) { - result.AddParameter(); + result.Add(((Parameter)part).Clone()); // (?) can be a position parameter or a named parameter (already substituted by (?), // but only the positional parameters are available at this point. Adding them in the @@ -487,7 +487,7 @@ int span = typedval.Type.GetColumnSpan(factory); string name = namedParameter.Key; - int[] locs = GetEffectiveNamedParameterLocations(sqlParameters, name) ?? getNamedParameterLocations(name); + int[] locs = getNamedParameterLocations(name); for (int i = 0; i < locs.Length; i++) { int location = locs[i]; @@ -567,23 +567,6 @@ return ConvertITypesToSqlTypes(paramTypeList, factory, totalSpan); } - private int[] GetEffectiveNamedParameterLocations(IList<Parameter> sqlParameters, object backTrackId) - { - var locations = new List<int>(5); - for (int i = 0; i < sqlParameters.Count; i++) - { - if (backTrackId.Equals(sqlParameters[i].BackTrack)) - { - locations.Add(i); - } - } - if(locations.Count == 0) - { - return null; - } - return locations.ToArray(); - } - public int BindParameters(IDbCommand command, int start, ISessionImplementor session) { int location = start; @@ -651,6 +634,12 @@ return span; } + internal SqlString ProcessedSql + { + get { return processedSQL; } + set { processedSQL = value; } + } + public SqlString FilteredSQL { get { return processedSQL; } @@ -659,16 +648,19 @@ public IList<IType> FilteredParameterTypes { get { return filteredParameterTypes; } + internal set { filteredParameterTypes = value; } } public IList<object> FilteredParameterValues { get { return filteredParameterValues; } + internal set { filteredParameterValues = value; } } public IList<int> FilteredParameterLocations { get { return filteredParameterLocations; } + internal set { filteredParameterLocations = value; } } public bool NaturalKeyLookup { get; set; } Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/BasicExecutor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/BasicExecutor.cs 2011-05-29 18:36:56 UTC (rev 5880) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/BasicExecutor.cs 2011-05-30 13:58:24 UTC (rev 5881) @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Data; using System.Data.Common; +using System.Linq; using Antlr.Runtime; using Antlr.Runtime.Tree; @@ -9,9 +10,9 @@ using NHibernate.Exceptions; using NHibernate.Hql.Ast.ANTLR.Tree; using NHibernate.Param; -using NHibernate.Persister.Entity; using NHibernate.SqlCommand; using NHibernate.SqlTypes; +using IQueryable = NHibernate.Persister.Entity.IQueryable; namespace NHibernate.Hql.Ast.ANTLR.Exec { @@ -59,24 +60,16 @@ try { CheckParametersExpectedType(parameters); // NH Different behavior (NH-1898) - var parameterTypes = new List<SqlType>(Parameters.Count); + + var sqlQueryParametersList = sql.GetParameters().ToList(); + SqlType[] parameterTypes = Parameters.GetQueryParameterTypes(sqlQueryParametersList, session.Factory); + + st = session.Batcher.PrepareCommand(CommandType.Text, sql, parameterTypes); foreach (var parameterSpecification in Parameters) { - if (parameterSpecification.ExpectedType == null) - { - throw new QuerySyntaxException("Can't determine SqlType of parameter " + parameterSpecification.RenderDisplayInfo()+"\n Possible cause: wrong case-sensitive property-name."); - } - parameterTypes.AddRange(parameterSpecification.ExpectedType.SqlTypes(Factory)); + parameterSpecification.Bind(st, sqlQueryParametersList, parameters, session); } - st = session.Batcher.PrepareCommand(CommandType.Text, sql, parameterTypes.ToArray()); - IEnumerator<IParameterSpecification> paramSpecifications = Parameters.GetEnumerator(); - // NH Different behavior: The inital value is 0 (initialized to 1 in JAVA) - int pos = 0; - while (paramSpecifications.MoveNext()) - { - var paramSpec = paramSpecifications.Current; - pos += paramSpec.Bind(st, parameters, session, pos); - } + if (selection != null) { if (selection.Timeout != RowSelection.NoValue) Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/MultiTableDeleteExecutor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/MultiTableDeleteExecutor.cs 2011-05-29 18:36:56 UTC (rev 5880) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/MultiTableDeleteExecutor.cs 2011-05-30 13:58:24 UTC (rev 5881) @@ -1,16 +1,15 @@ using System; -using System.Collections.Generic; using System.Data; using System.Data.Common; - +using System.Linq; using NHibernate.Engine; using NHibernate.Exceptions; using NHibernate.Hql.Ast.ANTLR.Tree; using NHibernate.Param; -using NHibernate.Persister.Entity; using NHibernate.SqlCommand; using NHibernate.SqlTypes; using NHibernate.Util; +using IQueryable = NHibernate.Persister.Entity.IQueryable; namespace NHibernate.Hql.Ast.ANTLR.Exec { @@ -83,19 +82,15 @@ try { var paramsSpec = Walker.Parameters; - var parameterTypes = new List<SqlType>(paramsSpec.Count); + var sqlQueryParametersList = idInsertSelect.GetParameters().ToList(); + SqlType[] parameterTypes = paramsSpec.GetQueryParameterTypes(sqlQueryParametersList, session.Factory); + + ps = session.Batcher.PrepareCommand(CommandType.Text, idInsertSelect, parameterTypes); foreach (var parameterSpecification in paramsSpec) { - parameterTypes.AddRange(parameterSpecification.ExpectedType.SqlTypes(Factory)); + parameterSpecification.Bind(ps, sqlQueryParametersList, parameters, session); } - ps = session.Batcher.PrepareCommand(CommandType.Text, idInsertSelect, parameterTypes.ToArray()); - // NH Different behavior: The inital value is 0 (initialized to 1 in JAVA) - int pos = 0; - foreach (var specification in paramsSpec) - { - pos += specification.Bind(ps, parameters, session, pos); - } resultCount = session.Batcher.ExecuteNonQuery(ps); } finally Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/MultiTableUpdateExecutor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/MultiTableUpdateExecutor.cs 2011-05-29 18:36:56 UTC (rev 5880) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Exec/MultiTableUpdateExecutor.cs 2011-05-30 13:58:24 UTC (rev 5881) @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Data; using System.Data.Common; - +using System.Linq; using NHibernate.Engine; using NHibernate.Exceptions; using NHibernate.Hql.Ast.ANTLR.Tree; @@ -11,6 +11,7 @@ using NHibernate.SqlCommand; using NHibernate.SqlTypes; using NHibernate.Util; +using IQueryable = NHibernate.Persister.Entity.IQueryable; namespace NHibernate.Hql.Ast.ANTLR.Exec { @@ -109,9 +110,15 @@ List<IParameterSpecification> whereParams = (new List<IParameterSpecification>(allParams)).GetRange( parameterStart, allParams.Count - parameterStart); - ps = session.Batcher.PrepareCommand(CommandType.Text, idInsertSelect, GetParametersTypes(whereParams)); + var sqlQueryParametersList = idInsertSelect.GetParameters().ToList(); + SqlType[] parameterTypes = whereParams.GetQueryParameterTypes(sqlQueryParametersList, session.Factory); - BindParameters(whereParams, ps, parameters, session); + ps = session.Batcher.PrepareCommand(CommandType.Text, idInsertSelect, parameterTypes); + foreach (var parameterSpecification in whereParams) + { + parameterSpecification.Bind(ps, sqlQueryParametersList, parameters, session); + } + resultCount = session.Batcher.ExecuteNonQuery(ps); } finally @@ -139,8 +146,16 @@ { try { - ps = session.Batcher.PrepareCommand(CommandType.Text, updates[i], GetParametersTypes(hqlParameters[i])); - BindParameters(hqlParameters[i], ps, parameters, session); + var sqlQueryParametersList = updates[i].GetParameters().ToList(); + var paramsSpec = hqlParameters[i]; + SqlType[] parameterTypes = paramsSpec.GetQueryParameterTypes(sqlQueryParametersList, session.Factory); + + ps = session.Batcher.PrepareCommand(CommandType.Text, updates[i], parameterTypes); + foreach (var parameterSpecification in paramsSpec) + { + parameterSpecification.Bind(ps, sqlQueryParametersList, parameters, session); + } + session.Batcher.ExecuteNonQuery(ps); } finally @@ -165,34 +180,6 @@ } } - private SqlType[] GetParametersTypes(IEnumerable<IParameterSpecification> specifications) - { - if (specifications == null) - { - return new SqlType[0]; - } - var result = new List<SqlType>(); - foreach (var specification in specifications) - { - result.AddRange(specification.ExpectedType.SqlTypes(Factory)); - } - return result.ToArray(); - } - - private static void BindParameters(IEnumerable<IParameterSpecification> specifications, IDbCommand command, - QueryParameters parameters, ISessionImplementor session) - { - if (specifications == null) - { - return; - } - int position = 0; // ADO params are 0-based - foreach (var specification in specifications) - { - position += specification.Bind(command, parameters, session, position); - } - } - protected override IQueryable[] AffectedQueryables { get { return new[] {persister}; } Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/HqlSqlWalker.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/HqlSqlWalker.cs 2011-05-29 18:36:56 UTC (rev 5880) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/HqlSqlWalker.cs 2011-05-30 13:58:24 UTC (rev 5881) @@ -907,6 +907,7 @@ { if (_namedParameters.Count > 0) { + // NH TODO: remove this limitation throw new SemanticException("cannot define positional parameter after any named parameters have been defined"); } ParameterNode parameter = (ParameterNode)adaptor.Create(PARAM, "?"); @@ -1081,7 +1082,8 @@ sql.whereExpr(); - fromElement.SetWithClauseFragment(visitor.GetJoinAlias(), "(" + sql.GetSQL() + ")"); + var withClauseFragment = new SqlString("(", sql.GetSQL(), ")"); + fromElement.SetWithClauseFragment(visitor.GetJoinAlias(), withClauseFragment); } catch (SemanticException) { Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs 2011-05-29 18:36:56 UTC (rev 5880) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Loader/QueryLoader.cs 2011-05-30 13:58:24 UTC (rev 5881) @@ -1,21 +1,24 @@ using System; +using System.Linq; using System.Collections; using System.Collections.Generic; using System.Data; using System.Diagnostics; - using NHibernate.Engine; using NHibernate.Event; using NHibernate.Hql.Ast.ANTLR.Tree; +using NHibernate.Hql.Classic; using NHibernate.Impl; using NHibernate.Loader; using NHibernate.Param; using NHibernate.Persister.Collection; using NHibernate.Persister.Entity; using NHibernate.SqlCommand; +using NHibernate.SqlTypes; using NHibernate.Transform; using NHibernate.Type; using NHibernate.Util; +using IQueryable = NHibernate.Persister.Entity.IQueryable; namespace NHibernate.Hql.Ast.ANTLR.Loader { @@ -23,7 +26,6 @@ public class QueryLoader : BasicLoader { private readonly QueryTranslatorImpl _queryTranslator; - private SelectClause _selectClause; private bool _hasScalars; private string[][] _scalarColumnNames; @@ -49,7 +51,6 @@ : base(factory) { _queryTranslator = queryTranslator; - _selectClause = selectClause; Initialize(selectClause); PostInstantiate(); @@ -434,5 +435,241 @@ } return result; } + + /// <summary> + /// Obtain an <c>IDbCommand</c> with all parameters pre-bound. Bind positional parameters, + /// named parameters, and limit parameters. + /// </summary> + /// <remarks> + /// Creates an IDbCommand object and populates it with the values necessary to execute it against the + /// database to Load an Entity. + /// </remarks> + /// <param name="queryParameters">The <see cref="QueryParameters"/> to use for the IDbCommand.</param> + /// <param name="scroll">TODO: find out where this is used...</param> + /// <param name="session">The SessionImpl this Command is being prepared in.</param> + /// <returns>A CommandWrapper wrapping an IDbCommand that is ready to be executed.</returns> + protected internal override IDbCommand PrepareQueryCommand(QueryParameters queryParameters, bool scroll, ISessionImplementor session) + { + // NH: In this QueryLoader we can know better all parameters used so we can simplify the IDbCommand construction + // NH: would be very useful if we can do the same with Criteria. This method works just for HQL and LINQ. + + // A distinct-copy of parameter specifications collected during query construction + var parameterSpecs = new HashSet<IParameterSpecification>(_queryTranslator.CollectedParameterSpecifications); + SqlString sqlString = SqlString.Copy(); + + // dynamic-filter parameters: during the HQL->SQL parsing, filters can be added as SQL_TOKEN/string and the SqlGenerator will not find it + sqlString = ExpandDynamicFilterParameters(sqlString, parameterSpecs, session); + AdjustQueryParametersForSubSelectFetching(sqlString, parameterSpecs, session, queryParameters); // NOTE: see TODO below + + sqlString = AddLimitsParametersIfNeeded(sqlString, parameterSpecs, queryParameters, session); + // TODO: for sub-select fetching we have to try to assign the QueryParameter.ProcessedSQL here (with limits) but only after use IParameterSpecification for any kind of queries + + // The PreprocessSQL method can modify the SqlString but should never add parameters (or we have to override it) + sqlString = PreprocessSQL(sqlString, queryParameters, session.Factory.Dialect); + + // After the last modification to the SqlString we can collect all parameters types. + ResetEffectiveExpectedType(parameterSpecs, queryParameters); // <= TODO: remove this method when we can infer the type during the parse + var sqlQueryParametersList = sqlString.GetParameters().ToList(); + SqlType[] parameterTypes = parameterSpecs.GetQueryParameterTypes(sqlQueryParametersList, session.Factory); + + parameterSpecs.SetQueryParameterLocations(sqlQueryParametersList, session.Factory); + + IDbCommand command = session.Batcher.PrepareQueryCommand(CommandType.Text, sqlString, parameterTypes); + + try + { + RowSelection selection = queryParameters.RowSelection; + if (selection != null && selection.Timeout != RowSelection.NoValue) + { + command.CommandTimeout = selection.Timeout; + } + + BindParametersValues(command, sqlQueryParametersList, parameterSpecs, queryParameters, session); + + session.Batcher.ExpandQueryParameters(command, sqlString); + } + catch (HibernateException) + { + session.Batcher.CloseCommand(command, null); + throw; + } + catch (Exception sqle) + { + session.Batcher.CloseCommand(command, null); + ADOExceptionReporter.LogExceptions(sqle); + throw; + } + return command; + } + + private void AdjustQueryParametersForSubSelectFetching(SqlString sqlString, IEnumerable<IParameterSpecification> parameterSpecs, ISessionImplementor session, QueryParameters queryParameters) + { + // TODO: Remove this when all parameters are managed using IParameterSpecification (QueryParameters does not need to have decomposed values for filters) + + var dynamicFilterParameterSpecifications = parameterSpecs.OfType<DynamicFilterParameterSpecification>().ToList(); + var filteredParameterValues = new List<object>(); + var filteredParameterTypes = new List<IType>(); + var filteredParameterLocations = new List<int>(); + + if (dynamicFilterParameterSpecifications.Count != 0) + { + var sqlQueryParametersList = sqlString.GetParameters().ToList(); + foreach (DynamicFilterParameterSpecification specification in dynamicFilterParameterSpecifications) + { + string backTrackId = specification.GetIdsForBackTrack(session.Factory).First(); + object value = session.GetFilterParameterValue(specification.FilterParameterFullName); + var elementType = specification.ExpectedType; + foreach (int position in sqlQueryParametersList.GetEffectiveParameterLocations(backTrackId)) + { + filteredParameterValues.Add(value); + filteredParameterTypes.Add(elementType); + filteredParameterLocations.Add(position); + } + } + } + + queryParameters.ProcessedSql = sqlString; + queryParameters.FilteredParameterLocations = filteredParameterLocations; + queryParameters.FilteredParameterTypes = filteredParameterTypes; + queryParameters.FilteredParameterValues = filteredParameterValues; + } + + private SqlString ExpandDynamicFilterParameters(SqlString sqlString, ICollection<IParameterSpecification> parameterSpecs, ISessionImplementor session) + { + var enabledFilters = session.EnabledFilters; + if (enabledFilters.Count == 0 || sqlString.ToString().IndexOf(ParserHelper.HqlVariablePrefix) < 0) + { + return sqlString; + } + + Dialect.Dialect dialect = session.Factory.Dialect; + string symbols = ParserHelper.HqlSeparators + dialect.OpenQuote + dialect.CloseQuote; + + var originSql = sqlString.Compact(); + var result = new SqlStringBuilder(); + foreach (var sqlPart in originSql.Parts) + { + var parameter = sqlPart as Parameter; + if (parameter != null) + { + result.Add(parameter); + continue; + } + + var sqlFragment = sqlPart.ToString(); + var tokens = new StringTokenizer(sqlFragment, symbols, true); + + foreach (string token in tokens) + { + if (token.StartsWith(ParserHelper.HqlVariablePrefix)) + { + string filterParameterName = token.Substring(1); + string[] parts = StringHelper.ParseFilterParameterName(filterParameterName); + string filterName = parts[0]; + string parameterName = parts[1]; + var filter = (FilterImpl)enabledFilters[filterName]; + + object value = filter.GetParameter(parameterName); + IType type = filter.FilterDefinition.GetParameterType(parameterName); + int parameterColumnSpan = type.GetColumnSpan(session.Factory); + var collectionValue = value as ICollection; + int? collectionSpan = null; + + // Add query chunk + string typeBindFragment = string.Join(", ", Enumerable.Repeat("?", parameterColumnSpan).ToArray()); + string bindFragment; + if (collectionValue != null && !type.ReturnedClass.IsArray) + { + collectionSpan = collectionValue.Count; + bindFragment = string.Join(", ", Enumerable.Repeat(typeBindFragment, collectionValue.Count).ToArray()); + } + else + { + bindFragment = typeBindFragment; + } + + // dynamic-filter parameter tracking + var filterParameterFragment = SqlString.Parse(bindFragment); + var dynamicFilterParameterSpecification = new DynamicFilterParameterSpecification(filterName, parameterName, type, collectionSpan); + var parameters = filterParameterFragment.GetParameters().ToArray(); + var sqlParameterPos = 0; + var paramTrackers = dynamicFilterParameterSpecification.GetIdsForBackTrack(session.Factory); + foreach (var paramTracker in paramTrackers) + { + parameters[sqlParameterPos++].BackTrack = paramTracker; + } + + parameterSpecs.Add(dynamicFilterParameterSpecification); + result.Add(filterParameterFragment); + } + else + { + result.Add(token); + } + } + } + return result.ToSqlString().Compact(); + } + + private SqlString AddLimitsParametersIfNeeded(SqlString sqlString, ICollection<IParameterSpecification> parameterSpecs, QueryParameters queryParameters, ISessionImplementor session) + { + var sessionFactory = session.Factory; + Dialect.Dialect dialect = sessionFactory.Dialect; + + RowSelection selection = queryParameters.RowSelection; + bool useLimit = UseLimit(selection, dialect); + if (useLimit) + { + bool hasFirstRow = GetFirstRow(selection) > 0; + bool useOffset = hasFirstRow && dialect.SupportsLimitOffset; + int max = GetMaxOrLimit(dialect, selection); + int? skip = useOffset ? (int?) dialect.GetOffsetValue(GetFirstRow(selection)) : null; + int? take = max != int.MaxValue ? (int?) max : null; + + Parameter skipSqlParameter = null; + Parameter takeSqlParameter = null; + if (skip.HasValue) + { + var skipParameter = new QuerySkipParameterSpecification(); + skipSqlParameter = Parameter.Placeholder; + skipSqlParameter.BackTrack = skipParameter.GetIdsForBackTrack(sessionFactory).First(); + parameterSpecs.Add(skipParameter); + } + if (take.HasValue) + { + var takeParameter = new QueryTakeParameterSpecification(); + takeSqlParameter = Parameter.Placeholder; + takeSqlParameter.BackTrack = takeParameter.GetIdsForBackTrack(sessionFactory).First(); + parameterSpecs.Add(takeParameter); + } + // The dialect can move the given parameters where he need, what it can't do is generates new parameters loosing the BackTrack. + return dialect.GetLimitString(sqlString, skip, take, skipSqlParameter, takeSqlParameter); + } + return sqlString; + } + + private void ResetEffectiveExpectedType(IEnumerable<IParameterSpecification> parameterSpecs, QueryParameters queryParameters) + { + foreach (var parameterSpecification in parameterSpecs.OfType<IExplicitParameterSpecification>()) + { + parameterSpecification.SetEffectiveType(queryParameters); + } + } + + /// <summary> + /// Bind all parameters values. + /// </summary> + /// <param name="command">The command where bind each value.</param> + /// <param name="sqlQueryParametersList">The list of Sql query parameter in the exact sequence they are present in the query.</param> + /// <param name="parameterSpecs">All parameter-specifications collected during query construction.</param> + /// <param name="queryParameters">The encapsulation of the parameter values to be bound.</param> + /// <param name="session">The session from where execute the query.</param> + private void BindParametersValues(IDbCommand command, IList<Parameter> sqlQueryParametersList, IEnumerable<IParameterSpecification> parameterSpecs, QueryParameters queryParameters, ISessionImplementor session) + { + foreach (var parameterSpecification in parameterSpecs) + { + parameterSpecification.Bind(command, sqlQueryParametersList, queryParameters, session); + } + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/SqlGenerator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/SqlGenerator.cs 2011-05-29 18:36:56 UTC (rev 5880) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/SqlGenerator.cs 2011-05-30 13:58:24 UTC (rev 5881) @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Linq; using Antlr.Runtime; using Antlr.Runtime.Tree; using NHibernate.Dialect.Function; @@ -92,11 +93,6 @@ writer.Clause(s); } - private void ParameterOut() - { - writer.Parameter(); - } - /// <summary> /// Add a aspace if the previous token was not a space or a parenthesis. /// </summary> @@ -129,11 +125,12 @@ private void Out(IASTNode n) { - var parameterNode= n as ParameterNode; + var parameterNode = n as ParameterNode; if (parameterNode != null) { var parameter = Parameter.Placeholder; - parameter.BackTrack = parameterNode.HqlParameterSpecification.IdForBackTrack; + // supposed to be simplevalue + parameter.BackTrack = parameterNode.HqlParameterSpecification.GetIdsForBackTrack(sessionFactory).Single(); writer.PushParameter(parameter); } else if (n is SqlNode) @@ -151,13 +148,11 @@ } else if (n is IParameterContainer) { - if (((IParameterContainer) n).HasEmbeddedParameters) + var parameterContainer = (IParameterContainer) n; + if (parameterContainer.HasEmbeddedParameters) { - IParameterSpecification[] specifications = ((IParameterContainer) n).GetEmbeddedParameters(); - if (specifications != null) - { - collectedParameters.AddRange(specifications); - } + IParameterSpecification[] specifications = parameterContainer.GetEmbeddedParameters(); + collectedParameters.AddRange(specifications); } } } @@ -340,8 +335,6 @@ } var dialect = sessionFactory.Dialect; - - // FIXME - We need to adjust the parameters from the user according to dialect settings like UseMaxForLimit, OffsetStartsAtOne. This will need to happen every time we query. // Skip-Take in HQL should be supported just for Dialect supporting variable limits at least when users use parameters for skip-take. if (!dialect.SupportsVariableLimit && (skipIsParameter || takeIsParameter)) @@ -349,26 +342,28 @@ throw new NotSupportedException("The dialect " + dialect.GetType().FullName + " does not supports variable limits"); } - // If a limit is a parameter, it should be of type IExplicitValueParameterSpecification. Parameter skipParameter = null; Parameter takeParameter = null; if(queryWriter.SkipParameter != null) { + queryWriter.SkipParameter.ExpectedType = NHibernateUtil.Int32; skipParameter = Parameter.Placeholder; - skipParameter.BackTrack = queryWriter.SkipParameter.IdForBackTrack; + skipParameter.BackTrack = queryWriter.SkipParameter.GetIdsForBackTrack(sessionFactory).First(); } if (queryWriter.TakeParameter != null) { + queryWriter.TakeParameter.ExpectedType = NHibernateUtil.Int32; takeParameter = Parameter.Placeholder; - takeParameter.BackTrack = queryWriter.TakeParameter.IdForBackTrack; + takeParameter.BackTrack = queryWriter.TakeParameter.GetIdsForBackTrack(sessionFactory).First(); } - // We allow the user to specify either constants or parameters for their limits. - return dialect.GetLimitString(sqlString, - queryWriter.Skip.HasValue ? (int?)dialect.GetOffsetValue(queryWriter.Skip.Value) : null, - queryWriter.Take.HasValue ? (int?)dialect.GetLimitValue(queryWriter.Skip ?? 0, queryWriter.Take.Value) : null, - skipParameter, - takeParameter); + // We allow the user to specify either constants or parameters for their limits. + // The dialect can move the given parameters where he need, what it can't do is generates new parameters loosing the BackTrack. + return dialect.GetLimitString(sqlString, + queryWriter.Skip.HasValue ? (int?) dialect.GetOffsetValue(queryWriter.Skip.Value) : null, + queryWriter.Take.HasValue ? (int?) dialect.GetLimitValue(queryWriter.Skip ?? 0, queryWriter.Take.Value) : null, + skipParameter, + takeParameter); } private void Skip(IASTNode node) Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/BinaryLogicOperatorNode.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/BinaryLogicOperatorNode.cs 2011-05-29 18:36:56 UTC (rev 5880) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/BinaryLogicOperatorNode.cs 2011-05-30 13:58:24 UTC (rev 5881) @@ -1,9 +1,11 @@ using System; +using System.Collections.Generic; +using System.Linq; using Antlr.Runtime; using NHibernate.Engine; using NHibernate.Param; +using NHibernate.SqlCommand; using NHibernate.Type; -using NHibernate.Util; namespace NHibernate.Hql.Ast.ANTLR.Tree { @@ -13,9 +15,12 @@ /// Ported by: Steve Strong /// </summary> [CLSCompliant(false)] - public class BinaryLogicOperatorNode : HqlSqlWalkerNode, IBinaryOperatorNode + public class BinaryLogicOperatorNode : HqlSqlWalkerNode, IBinaryOperatorNode, IParameterContainer { - public BinaryLogicOperatorNode(IToken token) : base(token) + private List<IParameterSpecification> embeddedParameters; + + public BinaryLogicOperatorNode(IToken token) + : base(token) { } @@ -58,13 +63,15 @@ rhsType = lhsType; } - if ( typeof(IExpectedTypeAwareNode).IsAssignableFrom( lhs.GetType() ) ) + var lshExpectedTypeAwareNode = lhs as IExpectedTypeAwareNode; + if (lshExpectedTypeAwareNode != null) { - ( ( IExpectedTypeAwareNode ) lhs ).ExpectedType = rhsType; + lshExpectedTypeAwareNode.ExpectedType = rhsType; } - if ( typeof(IExpectedTypeAwareNode).IsAssignableFrom( rhs.GetType() ) ) + var rshExpectedTypeAwareNode = rhs as IExpectedTypeAwareNode; + if (rshExpectedTypeAwareNode != null) { - ( ( IExpectedTypeAwareNode ) rhs ).ExpectedType = lhsType; + rshExpectedTypeAwareNode.ExpectedType = lhsType; } MutateRowValueConstructorSyntaxesIfNecessary( lhsType, rhsType ); @@ -122,131 +129,138 @@ */ private void MutateRowValueConstructorSyntax(int valueElements) { + // Reduce the new tree in just one SqlFragment, to manage parameters + // mutation depends on the types of nodes invloved... - int comparisonType = Type; - string comparisonText = Text; - Type = HqlSqlWalker.AND; - Text = "AND"; + string comparisonText = "==".Equals(Text) ? "=" : Text; + Type = HqlSqlWalker.SQL_TOKEN; + string[] lhsElementTexts = ExtractMutationTexts(LeftHandOperand, valueElements); + string[] rhsElementTexts = ExtractMutationTexts(RightHandOperand, valueElements); - String[] lhsElementTexts = ExtractMutationTexts( LeftHandOperand, valueElements ); - String[] rhsElementTexts = ExtractMutationTexts( RightHandOperand, valueElements ); + var lho = LeftHandOperand as ParameterNode; + IParameterSpecification lhsEmbeddedCompositeParameterSpecification = (lho == null) ? null : lho.HqlParameterSpecification; - IParameterSpecification lhsEmbeddedCompositeParameterSpecification = - LeftHandOperand == null || ( !(LeftHandOperand is ParameterNode)) - ? null - : ( ( ParameterNode ) LeftHandOperand ).HqlParameterSpecification; + var rho = RightHandOperand as ParameterNode; + IParameterSpecification rhsEmbeddedCompositeParameterSpecification = (rho == null) ? null : rho.HqlParameterSpecification; - IParameterSpecification rhsEmbeddedCompositeParameterSpecification = - RightHandOperand == null || ( !(RightHandOperand is ParameterNode)) - ? null - : ( ( ParameterNode ) RightHandOperand ).HqlParameterSpecification; + var multicolumnComparisonClause = Translate(valueElements, comparisonText, lhsElementTexts, rhsElementTexts); - IASTNode container = this; + if (lhsEmbeddedCompositeParameterSpecification != null) + { + AddEmbeddedParameter(lhsEmbeddedCompositeParameterSpecification); + } + if (rhsEmbeddedCompositeParameterSpecification != null) + { + AddEmbeddedParameter(rhsEmbeddedCompositeParameterSpecification); + } + ClearChildren(); + Text = multicolumnComparisonClause; + } - for ( int i = valueElements - 1; i > 0; i-- ) + public override SqlString RenderText(ISessionFactoryImplementor sessionFactory) + { + if(!HasEmbeddedParameters) { - if ( i == 1 ) - { - container.ClearChildren(); + // this expression was not changed by MutateRowValueConstructorSyntax + return base.RenderText(sessionFactory); + } + var result = SqlString.Parse(Text); + // query-parameter = the parameter specified in the NHibernate query + // sql-parameter = real parameter/s inside the final SQL + // here is where we suppose the SqlString has all sql-parameters in sequence for a given query-parameter. + // This happen when the query-parameter spans multiple columns (components,custom-types and so on). + var parameters = result.GetParameters().ToArray(); + var sqlParameterPos = 0; + var paramTrackers = embeddedParameters.SelectMany(specification => specification.GetIdsForBackTrack(sessionFactory)); + foreach (var paramTracker in paramTrackers) + { + parameters[sqlParameterPos++].BackTrack = paramTracker; + } + return result; + } - container.AddChildren( - ASTFactory.CreateNode( - comparisonType, comparisonText, - ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, lhsElementTexts[0]), - ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, rhsElementTexts[0]) - ), - ASTFactory.CreateNode( - comparisonType, comparisonText, - ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, lhsElementTexts[1]), - ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, rhsElementTexts[1]) - )); + public void AddEmbeddedParameter(IParameterSpecification specification) + { + if (embeddedParameters == null) + { + embeddedParameters = new List<IParameterSpecification>(); + } + embeddedParameters.Add(specification); + } - // "pass along" our initial embedded parameter node(s) to the first generated - // sql fragment so that it can be handled later for parameter binding... - SqlFragment fragment = ( SqlFragment ) container.GetChild(0).GetChild(0); - if ( lhsEmbeddedCompositeParameterSpecification != null ) { - fragment.AddEmbeddedParameter( lhsEmbeddedCompositeParameterSpecification ); - } - if ( rhsEmbeddedCompositeParameterSpecification != null ) { - fragment.AddEmbeddedParameter( rhsEmbeddedCompositeParameterSpecification ); - } - } - else - { - container.ClearChildren(); - container.AddChildren( - ASTFactory.CreateNode(HqlSqlWalker.AND, "AND"), - ASTFactory.CreateNode( - comparisonType, comparisonText, - ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, lhsElementTexts[i]), - ASTFactory.CreateNode(HqlSqlWalker.SQL_TOKEN, rhsElementTexts[i]) - )); + public bool HasEmbeddedParameters + { + get { return embeddedParameters != null && embeddedParameters.Count != 0; } + } - container = container.GetChild(0); - } + public IParameterSpecification[] GetEmbeddedParameters() + { + return embeddedParameters.ToArray(); + } + + private string Translate(int valueElements, string comparisonText, string[] lhsElementTexts, string[] rhsElementTexts) + { + var multicolumnComparisonClauses = new List<string>(); + for (int i = 0; i < valueElements; i++) + { + multicolumnComparisonClauses.Add(string.Format("{0} {1} {2}", lhsElementTexts[i], comparisonText, rhsElementTexts[i])); } + return "(" + string.Join(" and ", multicolumnComparisonClauses.ToArray()) + ")"; } private static string[] ExtractMutationTexts(IASTNode operand, int count) { if ( operand is ParameterNode ) { - string[] rtn = new string[count]; - for ( int i = 0; i < count; i++ ) - { - rtn[i] = "?"; - } - return rtn; + return Enumerable.Repeat("?", count).ToArray(); } - else if ( operand.Type == HqlSqlWalker.VECTOR_EXPR ) + if (operand is SqlNode) { - string[] rtn = new string[operand.ChildCount]; - - for (int x = 0; x < operand.ChildCount; x++) - { - rtn[ x++ ] = operand.GetChild(x).Text; - - } - return rtn; - } - else if ( operand is SqlNode ) - { string nodeText = operand.Text; - if ( nodeText.StartsWith( "(" ) ) + if (nodeText.StartsWith("(")) { - nodeText = nodeText.Substring( 1 ); + nodeText = nodeText.Substring(1); } - if ( nodeText.EndsWith( ")" ) ) + if (nodeText.EndsWith(")")) { - nodeText = nodeText.Substring( 0, nodeText.Length - 1 ); + nodeText = nodeText.Substring(0, nodeText.Length - 1); } string[] splits = nodeText.Split(new[] { ", " }, StringSplitOptions.None); - if ( count != splits.Length ) + if (count != splits.Length) { - throw new HibernateException( "SqlNode's text did not reference expected number of columns" ); + throw new HibernateException("SqlNode's text did not reference expected number of columns"); } return splits; } - else + if (operand.Type == HqlSqlWalker.VECTOR_EXPR) { - throw new HibernateException( "dont know how to extract row value elements from node : " + operand ); + var rtn = new string[operand.ChildCount]; + + for (int x = 0; x < operand.ChildCount; x++) + { + rtn[ x ] = operand.GetChild(x).Text; + } + return rtn; } + throw new HibernateException( "dont know how to extract row value elements from node : " + operand ); } protected static IType ExtractDataType(IASTNode operand) { IType type = null; - if ( operand is SqlNode ) + var sqlNode = operand as SqlNode; + if (sqlNode != null) { - type = ( ( SqlNode ) operand ).DataType; + type = sqlNode.DataType; } - if ( type == null && operand is IExpectedTypeAwareNode ) + var expectedTypeAwareNode = operand as IExpectedTypeAwareNode; + if (type == null && expectedTypeAwareNode != null) { - type = ( ( IExpectedTypeAwareNode ) operand ).ExpectedType; + type = expectedTypeAwareNode.ExpectedType; } return type; Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/FromElement.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/FromElement.cs 2011-05-29 18:36:56 UTC (rev 5880) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/FromElement.cs 2011-05-30 13:58:24 UTC (rev 5881) @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Collections.Generic; using System.Text; using Antlr.Runtime; @@ -10,6 +11,7 @@ using NHibernate.SqlCommand; using NHibernate.Type; using NHibernate.Util; +using IQueryable = NHibernate.Persister.Entity.IQueryable; namespace NHibernate.Hql.Ast.ANTLR.Tree { @@ -36,7 +38,7 @@ private bool _collectionJoin; private string _role; private bool _initialized; - private string _withClauseFragment; + private SqlString _withClauseFragment; private string _withClauseJoinAlias; private bool _filter; private IToken _token; @@ -73,7 +75,7 @@ _isAllPropertyFetch = fetch; } - public void SetWithClauseFragment(String withClauseJoinAlias, string withClauseFragment) + public void SetWithClauseFragment(String withClauseJoinAlias, SqlString withClauseFragment) { _withClauseJoinAlias = withClauseJoinAlias; _withClauseFragment = withClauseFragment; @@ -296,7 +298,7 @@ } } - public string WithClauseFragment + public SqlString WithClauseFragment { get { return _withClauseFragment; } } @@ -330,7 +332,22 @@ public override SqlString RenderText(Engine.ISessionFactoryImplementor sessionFactory) { - return SqlString.Parse(Text); + var result = SqlString.Parse(Text); + // query-parameter = the parameter specified in the NHibernate query + // sql-parameter = real parameter/s inside the final SQL + // here is where we suppose the SqlString has all sql-parameters in sequence for a given query-parameter. + // This happen when the query-parameter spans multiple columns (components,custom-types and so on). + if (HasEmbeddedParameters) + { + var parameters = result.GetParameters().ToArray(); + var sqlParameterPos = 0; + var paramTrackers = _embeddedParameters.SelectMany(specification => specification.GetIdsForBackTrack(sessionFactory)); + foreach (var paramTracker in paramTrackers) + { + parameters[sqlParameterPos++].BackTrack = paramTracker; + } + } + return result; } public string RenderCollectionSelectFragment(int size, int k) Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/SqlFragment.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/SqlFragment.cs 2011-05-29 18:36:56 UTC (rev 5880) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Tree/SqlFragment.cs 2011-05-30 13:58:24 UTC (rev 5881) @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using Antlr.Runtime; using NHibernate.Param; using NHibernate.SqlCommand; @@ -39,7 +40,22 @@ public override SqlString RenderText(Engine.ISessionFactoryImplementor sessionFactory) { - return SqlString.Parse(Text); + var result = SqlString.Parse(Text); + // query-parameter = the parameter specified in the NHibernate query + // sql-parameter = real parameter/s inside the final SQL + // here is where we suppose the SqlString has all sql-parameters in sequence for a given query-parameter. + // This happen when the query-parameter spans multiple columns (components,custom-types and so on). + if (HasEmbeddedParameters) + { + var parameters = result.GetParameters().ToArray(); + var sqlParameterPos = 0; + var paramTrackers = _embeddedParameters.SelectMany(specification => specification.GetIdsForBackTrack(sessionFactory)); + foreach (var paramTracker in paramTrackers) + { + parameters[sqlParameterPos++].BackTrack = paramTracker; + } + } + return result; } // ParameterContainer impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Util/JoinProcessor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Util/JoinProcessor.cs 2011-05-29 18:36:56 UTC (rev 5880) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/ANTLR/Util/JoinProcessor.cs 2011-05-30 13:58:24 UTC (rev 5881) @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Linq; using System.Text; using NHibernate.Engine; @@ -129,11 +130,7 @@ log.Debug( "Using FROM fragment [" + fromFragment + "]" ); } - ProcessDynamicFilterParameters( - fromFragment, - fromElement, - _walker - ); + ProcessDynamicFilterParameters(fromFragment,fromElement,_walker); } _syntheticAndFactory.AddWhereFragment( @@ -167,43 +164,7 @@ return; } - Dialect.Dialect dialect = walker.SessionFactoryHelper.Factory.Dialect; - - string symbols = new StringBuilder().Append( ParserHelper.HqlSeparators ) - .Append( dialect.OpenQuote) - .Append( dialect.CloseQuote) - .ToString(); - - StringTokenizer tokens = new StringTokenizer( sqlFragment.ToString(), symbols, true ); - StringBuilder result = new StringBuilder(); - - foreach (string token in tokens) - { - if ( token.StartsWith( ParserHelper.HqlVariablePrefix ) ) - { - string filterParameterName = token.Substring( 1 ); - string[] parts = StringHelper.ParseFilterParameterName( filterParameterName ); - FilterImpl filter = ( FilterImpl ) walker.EnabledFilters[parts[0]]; - Object value = filter.GetParameter( parts[1] ); - IType type = filter.FilterDefinition.GetParameterType( parts[1] ); - String typeBindFragment = StringHelper.Join( - ",", - ArrayHelper.FillArray( "?", type.GetColumnSpan( walker.SessionFactoryHelper.Factory ) ) - ); - string bindFragment = ( value != null && value is ICollection) - ? StringHelper.Join( ",", ArrayHelper.FillArray( typeBindFragment, ( ( ICollection ) value ).Count ) ) - : typeBindFragment; - //result.Append( bindFragment ); - result.Append(token); - container.AddEmbeddedParameter( new DynamicFilterParameterSpecification( parts[0], parts[1], type ) ); - } - else - { - result.Append( token ); - } - } - - container.Text = result.ToString(); + container.Text = sqlFragment.ToString(); // dynamic-filters are processed altogether by Loader } private static bool HasDynamicFilterParam(SqlString sqlFragment) Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj =================================================================== --- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-05-29 18:36:56 UTC (rev 5880) +++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-05-30 13:58:24 UTC (rev 5881) @@ -495,6 +495,9 @@ <Compile Include="NonUniqueResultException.cs" /> <Compile Include="ObjectDeletedException.cs" /> <Compile Include="ObjectNotFoundException.cs" /> + <Compile Include="Param\ParametersBackTrackExtensions.cs" /> + <Compile Include="Param\QuerySkipParameterSpecification.cs" /> + <Compile Include="Param\QueryTakeParameterSpecification.cs" /> <Compile Include="PersistentObjectException.cs" /> <Compile Include="Persister\PersisterFactory.cs" /> <Compile Include="Properties\CamelCaseMUnderscoreStrategy.cs" /> Modified: trunk/nhibernate/src/NHibernate/Param/AbstractExplicitParameterSpecification.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Param/AbstractExplicitParameterSpecification.cs 2011-05-29 18:36:56 UTC (rev 5880) +++ trunk/nhibernate/src/NHibernate/Param/AbstractExplicitParameterSpecification.cs 2011-05-30 13:58:24 UTC (rev 5881) @@ -1,43 +1,64 @@ -using System.Data; +using System; +using System.Collections.Generic; +using System.Data; using NHibernate.Engine; +using NHibernate.SqlCommand; using NHibernate.Type; namespace NHibernate.Param { - public abstract class AbstractExplicitParameterSpecification : IExplicitParameterSpecification + public abstract class AbstractExplicitParameterSpecification : IExplicitParameterSpecification { - private readonly int _sourceLine; - private readonly int _sourceColumn; - private IType _expectedType; + private readonly int sourceColumn; + private readonly int sourceLine; /// <summary> /// Constructs an AbstractExplicitParameterSpecification. /// </summary> /// <param name="sourceLine">sourceLine</param> /// <param name="sourceColumn">sourceColumn</param> - protected AbstractExplicitParameterSpecification(int sourceLine, int sourceColumn) { - _sourceLine = sourceLine; - _sourceColumn = sourceColumn; + protected AbstractExplicitParameterSpecification(int sourceLine, int sourceColumn) + { + this.sourceLine = sourceLine; + this.sourceColumn = sourceColumn; } - public int SourceLine + #region IExplicitParameterSpecification Members + + public int SourceLine { - get { return _sourceLine; } + get { return sourceLine; } } public int SourceColumn { - get { return _sourceColumn; } + get { return sourceColumn; } } - public IType ExpectedType + public IType ExpectedType { get; set; } + + public abstract string RenderDisplayInfo(); + public abstract IEnumerable<string> GetIdsForBackTrack(IMapping sessionFactory); + public abstract void Bind(IDbCommand command, IList<Parameter> sqlQueryParametersList, QueryParameters queryParameters, ISessionImplementor session); + public abstract void SetEffectiveType(QueryParameters queryParameters); + + #endregion + + protected int GetParemeterSpan(IMapping sessionFactory) { - get { return _expectedType; } - set { _expectedType = value; } + if (sessionFactory == null) + { + throw new ArgumentNullException("sessionFactory"); + } + if (ExpectedType != null) + { + // TODO: we have to find a way to set all expected types during the query parsing + var paremeterSpan = ExpectedType.GetColumnSpan(sessionFactory); + // NOTE: the OneToOneType does not return the real ColumnSpan + return paremeterSpan == 0 ? 1 : paremeterSpan; + } + // TODO: (see above) when the ExpectedType is null we will set the BackTrackId just for the first position (not a big problem because IType does not support something different... so far) + return 1; } - - public abstract string RenderDisplayInfo(); - public abstract object IdForBackTrack { get; } - public abstract int Bind(IDbCommand statement, QueryParameters qp, ISessionImplementor session, int position); } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Param/AggregatedIndexCollectionSelectorParameterSpecifications.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Param/AggregatedIndexCollectionSelectorParameterSpecifications.cs 2011-05-29 18:36:56 UTC (rev 5880) +++ trunk/nhibernate/src/NHibernate/Param/AggregatedIndexCollectionSelectorParameterSpecifications.cs 2011-05-30 13:58:24 UTC (rev 5881) @@ -3,6 +3,7 @@ using System.Data; using System.Text; using NHibernate.Engine; +using NHibernate.SqlCommand; using NHibernate.Type; namespace NHibernate.Param @@ -10,20 +11,25 @@ public class AggregatedIndexCollectionSelectorParameterSpecifications : IParameterSpecification { private readonly IList<IParameterSpecification> _paramSpecs; - private readonly Guid idForBackTrack = Guid.NewGuid(); public AggregatedIndexCollectionSelectorParameterSpecifications(IList<IParameterSpecification> paramSpecs) { _paramSpecs = paramSpecs; } - public int Bind(IDbCommand statement, QueryParameters qp, ISessionImplementor session, int position) + //public int Bind(IDbCommand statement, QueryParameters qp, ISessionImplementor session, int position) + //{ + // int bindCount = 0; + + // foreach (IParameterSpecification spec in _paramSpecs) + // { + // bindCount += spec.Bind(statement, qp, session, position + bindCount); + // } + // return bindCount; + //} + + + public void Bind(IDbCommand command, IList<Parameter> sqlQueryParametersList, QueryParameters queryParameters, ISessionImplementor session) { - int bindCount = 0; - - foreach (IParameterSpecification spec in _paramSpecs) - { - bindCount += spec.Bind(statement, qp, session, position + bindCount); - } - return bindCount; + throw new NotImplementedException(); } public IType ExpectedType @@ -38,9 +44,9 @@ return "index-selector [" + CollectDisplayInfo() + "]" ; } - public object IdForBackTrack + public IEnumerable<string> GetIdsForBackTrack(IMapping sessionFactory) { - get { return idForBackTrack; } + throw new NotImplementedException(); } private string CollectDisplayInfo() Modified: trunk/nhibernate/src/NHibernate/Param/CollectionFilterKeyParameterSpecification.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Param/CollectionFilterKeyParameterSpecification.cs 2011-05-29 18:36:56 UTC (rev 5880) +++ trunk/nhibernate/src/NHibernate/Param/CollectionFilterKeyParameterSpecification.cs 2011-05-30 13:58:24 UTC (rev 5881) @@ -1,17 +1,21 @@ using System; +using System.Collections.Generic; using System.Data; +using System.Linq; using NHibernate.Engine; +using NHibernate.SqlCommand; using NHibernate.Type; namespace NHibernate.Param { - class CollectionFilterKeyParameterSpecification : IParameterSpecification + public class CollectionFilterKeyParameterSpecification : IParameterSpecification { - private readonly string _collectionRole; - private readonly IType _keyType; - private readonly int _queryParameterPosition; - private readonly string idForBackTrack; + private const string CollectionFilterParameterIdTemplate = "<collfilter{0}{1}_{2}>"; + private readonly string collectionRole; + private readonly IType keyType; + private readonly int queryParameterPosition; + /// <summary> /// Creates a specialized collection-filter collection-key parameter spec. /// </summary> @@ -20,37 +24,66 @@ /// <param name="queryParameterPosition">The position within QueryParameters where we can find the appropriate param value to bind.</param> public CollectionFilterKeyParameterSpecification(string collectionRole, IType keyType, int queryParameterPosition) { - _collectionRole = collectionRole; - _keyType = keyType; - _queryParameterPosition = queryParameterPosition; - idForBackTrack = "nhcollkey_" + _collectionRole + "nh"; + this.collectionRole = collectionRole; + this.keyType = keyType; + this.queryParameterPosition = queryParameterPosition; } - public int Bind( - IDbCommand statement, - QueryParameters qp, - ISessionImplementor session, - int position) - { - object value = qp.PositionalParameterValues[_queryParameterPosition]; - _keyType.NullSafeSet(statement, value, position, session); - return _keyType.GetColumnSpan(session.Factory); - } + #region IParameterSpecification Members public IType ExpectedType { - get { return _keyType; } + get { return keyType; } set { throw new InvalidOperationException(); } } public string RenderDisplayInfo() { - return "collection-filter-key=" + _collectionRole; + return "collection-filter-key=" + collectionRole; } - public object IdForBackTrack + public IEnumerable<string> GetIdsForBackTrack(IMapping sessionFactory) { - get { return idForBackTrack; } + int paremeterSpan = keyType.GetColumnSpan(sessionFactory); + for (int i = 0; i < paremeterSpan; i++) + { + yield return string.Format(CollectionFilterParameterIdTemplate, collectionRole, queryParameterPosition, i); + } } + + public void Bind(IDbCommand command, IList<Parameter> sqlQueryParametersList, QueryParameters queryParameters, ISessionImplementor session) + { + IType type = keyType; + object value = queryParameters.PositionalParameterValues[queryParameterPosition]; + + string backTrackId = GetIdsForBackTrack(session.Factory).First(); // just the first because IType suppose the oders in certain sequence + int position = sqlQueryParametersList.GetEffectiveParameterLocations(backTrackId).Single(); // an HQL positional parameter can't appear more than once + type.NullSafeSet(command, value, position, session); + } + + #endregion + + public override bool Equals(object obj) + { + return base.Equals(obj as CollectionFilterKeyParameterSpecification); + } + + public bool Equals(CollectionFilterKeyParameterSpecification other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + if (ReferenceEquals(this, other)) + { + return true; + } + return other.queryParameterPosition == queryParameterPosition; + } + + public override int GetHashCode() + { + return queryParameterPosition ^ 877; + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Param/DynamicFilterParameterSp... [truncated message content] |
From: <pa...@us...> - 2011-05-29 18:37:03
|
Revision: 5880 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5880&view=rev Author: patearl Date: 2011-05-29 18:36:56 +0000 (Sun, 29 May 2011) Log Message: ----------- Documentation and consistency improvements in limit support. Includes a fix for a bug recently introduced in the MsSql2005Dialect. Modified Paths: -------------- trunk/nhibernate/releasenotes.txt trunk/nhibernate/src/NHibernate/Criterion/SubqueryExpression.cs trunk/nhibernate/src/NHibernate/Dialect/Dialect.cs trunk/nhibernate/src/NHibernate/Dialect/MsSql2005Dialect.cs trunk/nhibernate/src/NHibernate/Loader/Loader.cs Modified: trunk/nhibernate/releasenotes.txt =================================================================== --- trunk/nhibernate/releasenotes.txt 2011-05-29 18:06:21 UTC (rev 5879) +++ trunk/nhibernate/releasenotes.txt 2011-05-29 18:36:56 UTC (rev 5880) @@ -4,6 +4,8 @@ ##### Possible Breaking Changes ##### * All Dialect.GetLimitString() methods replaced with a single GetLimitString method with a new signature. + For dialects the developers don't perform routine tests on, efforts were made to ensure the new limit string + method conforms to the database documentation. Please report any limit-related bugs discovered at runtime. * [NH-2550] - Allow public access to FieldInterceptor Session (IFieldInterceptor changed) * [NH-2593] - For Microsoft SQL Server the default batch-size (adonet.batch_size) is set to 20 where not explicit defined in the session-factory configuration * - ICollectionPersister added property to fix [NH-2489] Modified: trunk/nhibernate/src/NHibernate/Criterion/SubqueryExpression.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Criterion/SubqueryExpression.cs 2011-05-29 18:06:21 UTC (rev 5879) +++ trunk/nhibernate/src/NHibernate/Criterion/SubqueryExpression.cs 2011-05-29 18:36:56 UTC (rev 5880) @@ -66,11 +66,13 @@ if (criteriaImpl.FirstResult != 0 || criteriaImpl.MaxResults != RowSelection.NoValue) { - int firstResults = factory.Dialect.GetOffsetValue(Loader.Loader.GetFirstRow(parameters.RowSelection)); - int maxResults = Loader.Loader.GetMaxOrLimit(factory.Dialect, parameters.RowSelection); - int? offsetParameterIndex = criteriaQuery.CreatePagingParameter(firstResults); - int? limitParameterIndex = criteriaQuery.CreatePagingParameter(maxResults); - sql = factory.Dialect.GetLimitString(sql, firstResults, maxResults, offsetParameterIndex, limitParameterIndex); + int? offset = Loader.Loader.GetOffsetUsingDialect(parameters.RowSelection, factory.Dialect); + int? limit = Loader.Loader.GetLimitUsingDialect(parameters.RowSelection, factory.Dialect); + int? offsetParameterIndex = offset.HasValue ? criteriaQuery.CreatePagingParameter(offset.Value) : null; + int? limitParameterIndex = limit.HasValue ? criteriaQuery.CreatePagingParameter(limit.Value) : null; + Parameter offsetParameter = offsetParameterIndex.HasValue ? Parameter.WithIndex(offsetParameterIndex.Value) : null; + Parameter limitParameter = limitParameterIndex.HasValue ? Parameter.WithIndex(limitParameterIndex.Value) : null; + sql = factory.Dialect.GetLimitString(sql, offset, limit, offsetParameter, limitParameter); } if (op != null) Modified: trunk/nhibernate/src/NHibernate/Dialect/Dialect.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Dialect/Dialect.cs 2011-05-29 18:06:21 UTC (rev 5879) +++ trunk/nhibernate/src/NHibernate/Dialect/Dialect.cs 2011-05-29 18:36:56 UTC (rev 5880) @@ -1702,28 +1702,34 @@ } /// <summary> + /// Generates a string to limit the result set to a number of maximum results with a specified offset into the results. /// Expects any database-specific offset and limit adjustments to have already been performed (ex. UseMaxForLimit, OffsetStartsAtOne). + /// Performs error checking based on the various dialect limit support options. If both parameters and fixed valeus are + /// specified, this will use the parameter option if possible. Otherwise, it will fall back to a fixed string. /// </summary> - internal SqlString GetLimitString(SqlString queryString, int? offset, int? limit, int? offsetParameterIndex, int? limitParameterIndex) + /// <param name="queryString"></param> + /// <param name="offset"></param> + /// <param name="limit"></param> + /// <param name="offsetParameter"></param> + /// <param name="limitParameter"></param> + /// <returns></returns> + public SqlString GetLimitString(SqlString queryString, int? offset, int? limit, Parameter offsetParameter, Parameter limitParameter) { - SqlString offsetParameter = - SupportsVariableLimit && offsetParameterIndex.HasValue ? new SqlString(Parameter.WithIndex(offsetParameterIndex.Value)) : - offset.HasValue ? new SqlString(offset.ToString()) : - null; + if (offset == null && limit == null && offsetParameter == null && limitParameter == null) + return queryString; - SqlString limitParameter = - SupportsVariableLimit && limitParameterIndex.HasValue ? new SqlString(Parameter.WithIndex(limitParameterIndex.Value)) : - limit.HasValue ? new SqlString(limit.ToString()) : - null; + if (!SupportsLimit) + throw new NotSupportedException("Dialect does not support limits."); - return GetLimitString(queryString, offsetParameter, limitParameter); - } + if (!SupportsVariableLimit && offsetParameter != null && offset == null) + throw new NotSupportedException("Dialect does not support variable limits."); - /// <summary> - /// Expects any database-specific offset and limit adjustments to have already been performed (ex. UseMaxForLimit, OffsetStartsAtOne). - /// </summary> - internal SqlString GetLimitString(SqlString queryString, int? offset, int? limit, Parameter offsetParameter, Parameter limitParameter) - { + if (!SupportsVariableLimit && limitParameter != null && limit == null) + throw new NotSupportedException("Dialect does not support variable limits."); + + if (!SupportsLimitOffset && (offset != null || offsetParameter != null)) + throw new NotSupportedException("Dialect does not support limits with offsets."); + SqlString o = SupportsVariableLimit && offsetParameter != null ? new SqlString(offsetParameter) : offset.HasValue ? new SqlString(offset.ToString()) : @@ -1737,7 +1743,15 @@ return GetLimitString(queryString, o, l); } - internal int GetLimitValue(int offset, int limit) + /// <summary> + /// Some databases require that a limit statement contain the maximum row number + /// instead of the number of rows to retrieve. This method adjusts source + /// limit and offset values to account for this. + /// </summary> + /// <param name="offset"></param> + /// <param name="limit"></param> + /// <returns></returns> + public int GetLimitValue(int offset, int limit) { if (limit == int.MaxValue) return int.MaxValue; @@ -1748,7 +1762,13 @@ return limit; } - internal int GetOffsetValue(int offset) + /// <summary> + /// Some databases use limit row offsets that start at one instead of zero. + /// This method adjusts a desired offset using the OffsetStartsAtOne flag. + /// </summary> + /// <param name="offset"></param> + /// <returns></returns> + public int GetOffsetValue(int offset) { if (OffsetStartsAtOne) return offset + 1; Modified: trunk/nhibernate/src/NHibernate/Dialect/MsSql2005Dialect.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Dialect/MsSql2005Dialect.cs 2011-05-29 18:06:21 UTC (rev 5879) +++ trunk/nhibernate/src/NHibernate/Dialect/MsSql2005Dialect.cs 2011-05-29 18:36:56 UTC (rev 5880) @@ -76,6 +76,9 @@ if (limit != null) result.Add("TOP (").Add(limit).Add(") "); + else + // ORDER BY can only be used in subqueries if TOP is also specified. + result.Add("TOP (" + int.MaxValue + ") "); result .Add(StringHelper.Join(", ", columnsOrAliases)) Modified: trunk/nhibernate/src/NHibernate/Loader/Loader.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Loader/Loader.cs 2011-05-29 18:06:21 UTC (rev 5879) +++ trunk/nhibernate/src/NHibernate/Loader/Loader.cs 2011-05-29 18:36:56 UTC (rev 5880) @@ -1098,6 +1098,29 @@ return dialect.SupportsLimit && (HasMaxRows(selection) || HasOffset(selection)); } + /// <summary> + /// Performs dialect-specific manipulations on the offset value before returning it. + /// This method is applicable for use in limit statements only. + /// </summary> + internal static int? GetOffsetUsingDialect(RowSelection selection, Dialect.Dialect dialect) + { + int firstRow = GetFirstRow(selection); + if (firstRow == 0) + return null; + return dialect.GetOffsetValue(firstRow); + } + + /// <summary> + /// Performs dialect-specific manipulations on the limit value before returning it. + /// This method is applicable for use in limit statements only. + /// </summary> + internal static int? GetLimitUsingDialect(RowSelection selection, Dialect.Dialect dialect) + { + if (selection == null || selection.MaxRows == RowSelection.NoValue) + return null; + return dialect.GetLimitValue(GetFirstRow(selection), selection.MaxRows); + } + /// <summary> /// Obtain an <c>IDbCommand</c> with all parameters pre-bound. Bind positional parameters, /// named parameters, and limit parameters. @@ -1127,14 +1150,17 @@ if (useLimit) { - int max = GetMaxOrLimit(dialect, selection); + int? offset = GetOffsetUsingDialect(selection, dialect); + int? limit = GetLimitUsingDialect(selection, dialect); + Parameter offsetParameter = queryParameters.OffsetParameterIndex.HasValue ? Parameter.WithIndex(queryParameters.OffsetParameterIndex.Value) : null; + Parameter limitParameter = queryParameters.LimitParameterIndex.HasValue ? Parameter.WithIndex(queryParameters.LimitParameterIndex.Value) : null; sqlString = dialect.GetLimitString( sqlString.Trim(), - useOffset ? (int?)dialect.GetOffsetValue(GetFirstRow(selection)) : null, - max != int.MaxValue ? (int?)max : null, - queryParameters.OffsetParameterIndex, - queryParameters.LimitParameterIndex); + useOffset ? offset : null, + limit, + useOffset ? offsetParameter : null, + limitParameter); } sqlString = PreprocessSQL(sqlString, queryParameters, dialect); @@ -1742,15 +1768,18 @@ if (useLimit) { - int max = GetMaxOrLimit(dialect, selection); - sqlString = - dialect.GetLimitString( - sqlString.Trim(), - useOffset ? (int?)dialect.GetOffsetValue(GetFirstRow(selection)) : null, - max != int.MaxValue ? (int?)max : null, - parameters.OffsetParameterIndex, - parameters.LimitParameterIndex); - } + int? offset = GetOffsetUsingDialect(selection, dialect); + int? limit = GetLimitUsingDialect(selection, dialect); + Parameter offsetParameter = parameters.OffsetParameterIndex.HasValue ? Parameter.WithIndex(parameters.OffsetParameterIndex.Value) : null; + Parameter limitParameter = parameters.LimitParameterIndex.HasValue ? Parameter.WithIndex(parameters.LimitParameterIndex.Value) : null; + sqlString = + dialect.GetLimitString( + sqlString.Trim(), + useOffset ? offset : null, + limit, + useOffset ? offsetParameter : null, + limitParameter); + } sqlString = PreprocessSQL(sqlString, parameters, dialect); return new SqlCommandInfo(sqlString, sqlTypes); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |