|
From: <ric...@us...> - 2011-07-23 19:32:05
|
Revision: 5991
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5991&view=rev
Author: ricbrown
Date: 2011-07-23 19:31:58 +0000 (Sat, 23 Jul 2011)
Log Message:
-----------
NH-2792: Using a named parameter multiple times in a native SQL query results in invalid parameter binding (exception in some drivers - Oracle)
Fixes the following tests on Oracle:
NHibernate.Test.Component.Basic.ComponentTest.TestNamedQuery
NHibernate.Test.FilterTest.DynamicFilterTest.CriteriaQueryFilters
NHibernate.Test.FilterTest.DynamicFilterTest.HqlFilters
NHibernate.Test.FilterTest.DynamicFilterTest.ManyToManyFilterOnCriteria
NHibernate.Test.FilterTest.DynamicFilterTest.ManyToManyFilterOnQuery
NHibernate.Test.FilterTest.DynamicFilterTest.ManyToManyOnCollectionLoadAfterHQL
NHibernate.Test.Hql.HQLFunctions.Cast
NHibernate.Test.Legacy.FooBarTest.NamedParams
NHibernate.Test.NHSpecificTest.ManyToOneFilters20Behaviour.Fixture.ExplicitFiltersOnCollectionsShouldBeActiveWithEagerLoad
NHibernate.Test.NHSpecificTest.NH1098.FilterParameterOrderFixture.CriteriaParameterOrder
NHibernate.Test.NHSpecificTest.NH1098.FilterParameterOrderFixture.QueryWithNamedParameters
NHibernate.Test.NHSpecificTest.NH1098.FilterParameterOrderFixture.QueryWithPositionalParameter
NHibernate.Test.NHSpecificTest.NH1293.Fixture.Criteria_Does_Not_Equal_To_HQL
NHibernate.Test.NHSpecificTest.NH1490.Fixture.Incorrect_SQL_Translated_Params_Bug
NHibernate.Test.NHSpecificTest.NH1864.Fixture.Bug
NHibernate.Test.NHSpecificTest.NH1864.Fixture.FilterOnOffOn
NHibernate.Test.NHSpecificTest.NH1864.Fixture.FilterQueryTwice
NHibernate.Test.NHSpecificTest.NH1868.Fixture.Bug
NHibernate.Test.NHSpecificTest.NH1868.Fixture.FilterOnOffOn
NHibernate.Test.NHSpecificTest.NH1868.Fixture.FilterQuery3
NHibernate.Test.NHSpecificTest.NH1868.Fixture.FilterQueryTwice
NHibernate.Test.NHSpecificTest.NH1908.Fixture.QueryPropertyInBothFilterAndQuery
NHibernate.Test.NHSpecificTest.NH1908.Fixture.QueryPropertyInBothFilterAndQueryUsingWith
NHibernate.Test.NHSpecificTest.NH1908ThreadSafety.Fixture.UsingFiltersIsThreadSafe
NHibernate.Test.NHSpecificTest.NH1920.Fixture.Can_Query_With_Collection_Size_Condition
NHibernate.Test.NHSpecificTest.NH1927.Fixture.CriteriaWithEagerFetch
NHibernate.Test.NHSpecificTest.NH1927.Fixture.HqlWithEagerFetch
NHibernate.Test.NHSpecificTest.NH1990.Fixture.FetchingBySubqueryFilterParameters
NHibernate.Test.NHSpecificTest.NH1990.Fixture.FetchingBySubqueryFilterParametersAndPositionalParameters
NHibernate.Test.NHSpecificTest.NH1990.Fixture.FetchingBySubqueryFilterParametersAndPositionalParametersAndNamedParameters
NHibernate.Test.NHSpecificTest.NH2318.Fixture.HqlTrimFunctionsWithParameters
NHibernate.Test.QueryTest.DetachedQueryFixture.ExecutableNamedQuery
NHibernate.Test.SqlTest.Query.SelfReferencingCollectionLoadTest.LoadCollection
NHibernate.Test.SubclassFilterTest.DiscrimSubclassFilterTest.FiltersWithSubclass
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/AdoNet/AbstractBatcher.cs
trunk/nhibernate/src/NHibernate/Driver/DriverBase.cs
trunk/nhibernate/src/NHibernate/Driver/IDriver.cs
trunk/nhibernate/src/NHibernate/Driver/SqlStringFormatter.cs
trunk/nhibernate/src/NHibernate/Engine/IBatcher.cs
trunk/nhibernate/src/NHibernate/Loader/Loader.cs
Modified: trunk/nhibernate/src/NHibernate/AdoNet/AbstractBatcher.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/AdoNet/AbstractBatcher.cs 2011-07-23 15:29:50 UTC (rev 5990)
+++ trunk/nhibernate/src/NHibernate/AdoNet/AbstractBatcher.cs 2011-07-23 19:31:58 UTC (rev 5991)
@@ -222,6 +222,11 @@
}
}
+ public void RemoveUnusedCommandParameters(IDbCommand cmd, SqlString sqlString)
+ {
+ Driver.RemoveUnusedCommandParameters(cmd, sqlString);
+ }
+
public void ExpandQueryParameters(IDbCommand cmd, SqlString sqlString)
{
Driver.ExpandQueryParameters(cmd, sqlString);
Modified: trunk/nhibernate/src/NHibernate/Driver/DriverBase.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Driver/DriverBase.cs 2011-07-23 15:29:50 UTC (rev 5990)
+++ trunk/nhibernate/src/NHibernate/Driver/DriverBase.cs 2011-07-23 19:31:58 UTC (rev 5991)
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Data;
+using System.Linq;
using NHibernate.Engine;
using NHibernate.SqlCommand;
using NHibernate.SqlTypes;
@@ -213,6 +214,22 @@
return dbParam;
}
+ public void RemoveUnusedCommandParameters(IDbCommand cmd, SqlString sqlString)
+ {
+ var formatter = GetSqlStringFormatter();
+ formatter.Format(sqlString);
+
+ cmd.Parameters
+ .Cast<IDbDataParameter>()
+ .Select(p => p.ParameterName)
+ .Except(formatter.AssignedParameterNames)
+ .ToList()
+ .ForEach(ununsedParameterName =>
+ {
+ cmd.Parameters.RemoveAt(ununsedParameterName);
+ });
+ }
+
public virtual void ExpandQueryParameters(IDbCommand cmd, SqlString sqlString)
{
if (UseNamedPrefixInSql)
Modified: trunk/nhibernate/src/NHibernate/Driver/IDriver.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Driver/IDriver.cs 2011-07-23 15:29:50 UTC (rev 5990)
+++ trunk/nhibernate/src/NHibernate/Driver/IDriver.cs 2011-07-23 19:31:58 UTC (rev 5991)
@@ -87,6 +87,14 @@
IDbDataParameter GenerateParameter(IDbCommand command, string name, SqlType sqlType);
/// <summary>
+ /// Remove 'extra' parameters from the IDbCommand
+ /// </summary>
+ /// <remarks>
+ /// We sometimes create more parameters than necessary (see NH-2792 & also comments in SqlStringFormatter.ISqlStringVisitor.Parameter)
+ /// </remarks>
+ void RemoveUnusedCommandParameters(IDbCommand cmd, SqlString sqlString);
+
+ /// <summary>
/// Expand the parameters of the cmd to have a single parameter for each parameter in the
/// sql string
/// </summary>
Modified: trunk/nhibernate/src/NHibernate/Driver/SqlStringFormatter.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Driver/SqlStringFormatter.cs 2011-07-23 15:29:50 UTC (rev 5990)
+++ trunk/nhibernate/src/NHibernate/Driver/SqlStringFormatter.cs 2011-07-23 19:31:58 UTC (rev 5991)
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Text;
using NHibernate.SqlCommand;
using NHibernate.Engine.Query;
@@ -12,12 +13,9 @@
private int parameterIndex = 0;
private readonly ISqlParameterFormatter formatter;
private readonly string multipleQueriesSeparator;
-
- private readonly Dictionary<int, int> queryIndexToNumberOfPreceedingParameters = new Dictionary<int, int>();
- private readonly Dictionary<int, int> parameterIndexToQueryIndex = new Dictionary<int, int>();
-
- private bool hasReturnParameter = false;
+ private bool hasReturnParameter;
private bool foundReturnParameter = false;
+ private IList<string> assignedParameterNames = new List<string>();
public SqlStringFormatter(ISqlParameterFormatter formatter, string multipleQueriesSeparator)
{
@@ -27,8 +25,7 @@
public void Format(SqlString text)
{
- DetermineNumberOfPreceedingParametersForEachQuery(text);
- foundReturnParameter = false;
+ hasReturnParameter = DetermineIfSqlStringHasReturnParameter(text);
text.Visit(this);
}
@@ -52,6 +49,7 @@
if (hasReturnParameter && !foundReturnParameter)
{
result.Append(parameter);
+ assignedParameterNames.Add(String.Empty);
foundReturnParameter = true;
return;
}
@@ -63,50 +61,25 @@
// A candidateplace is making DriverBase.SetCommandParameters a little bit more intelligent... perhaps SqlString aware (see also DriverBase.SetCommandText, DriverBase.GenerateCommand)
string name = formatter.GetParameterName(parameter.ParameterPosition ?? parameterIndex);
+ assignedParameterNames.Add(name);
parameterIndex++;
result.Append(name);
}
- private void DetermineNumberOfPreceedingParametersForEachQuery(SqlString text)
+ private bool DetermineIfSqlStringHasReturnParameter(SqlString text)
{
- // NH: this code smell very bad. It look like specific for ORACLE and probably unused even for ORACLE
- int currentParameterIndex = 0;
- int currentQueryParameterCount = 0;
- int currentQueryIndex = 0;
- hasReturnParameter = false;
- foundReturnParameter = false;
-
CallableParser.Detail callableDetail = CallableParser.Parse(text.ToString());
+ return (callableDetail.IsCallable && callableDetail.HasReturn);
+ }
- if (callableDetail.IsCallable && callableDetail.HasReturn)
- hasReturnParameter = true;
+ public bool HasReturnParameter
+ {
+ get { return foundReturnParameter; }
+ }
- foreach (object part in text.Parts)
- {
- if (part.ToString().Equals(multipleQueriesSeparator))
- {
- queryIndexToNumberOfPreceedingParameters[currentQueryIndex] = currentParameterIndex - currentQueryParameterCount;
- currentQueryParameterCount = 0;
- currentQueryIndex++;
- continue;
- }
-
- Parameter parameter = part as Parameter;
-
- if (parameter != null)
- {
- if (hasReturnParameter && !foundReturnParameter)
- {
- foundReturnParameter = true;
- }
- else
- {
- parameterIndexToQueryIndex[currentParameterIndex] = currentQueryIndex;
- }
- currentQueryParameterCount++;
- currentParameterIndex++;
- }
- }
+ public string[] AssignedParameterNames
+ {
+ get { return assignedParameterNames.ToArray(); }
}
}
}
Modified: trunk/nhibernate/src/NHibernate/Engine/IBatcher.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Engine/IBatcher.cs 2011-07-23 15:29:50 UTC (rev 5990)
+++ trunk/nhibernate/src/NHibernate/Engine/IBatcher.cs 2011-07-23 19:31:58 UTC (rev 5991)
@@ -132,6 +132,14 @@
int ExecuteNonQuery(IDbCommand cmd);
/// <summary>
+ /// Remove 'extra' parameters from the IDbCommand
+ /// </summary>
+ /// <remarks>
+ /// We sometimes create more parameters than necessary (see NH-2792 & also comments in SqlStringFormatter.ISqlStringVisitor.Parameter)
+ /// </remarks>
+ void RemoveUnusedCommandParameters(IDbCommand cmd, SqlString sqlString);
+
+ /// <summary>
/// Expand the parameters of the cmd to have a single parameter for each parameter in the
/// sql string
/// </summary>
Modified: trunk/nhibernate/src/NHibernate/Loader/Loader.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Loader/Loader.cs 2011-07-23 15:29:50 UTC (rev 5990)
+++ trunk/nhibernate/src/NHibernate/Loader/Loader.cs 2011-07-23 19:31:58 UTC (rev 5991)
@@ -1148,6 +1148,7 @@
sqlCommand.Bind(command, session);
+ session.Batcher.RemoveUnusedCommandParameters(command, sqlString);
session.Batcher.ExpandQueryParameters(command, sqlString);
}
catch (HibernateException)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|