|
From: <fab...@us...> - 2011-03-29 14:23:51
|
Revision: 5568
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5568&view=rev
Author: fabiomaulo
Date: 2011-03-29 14:23:44 +0000 (Tue, 29 Mar 2011)
Log Message:
-----------
Fix NH-2605
Modified Paths:
--------------
trunk/nhibernate/releasenotes.txt
trunk/nhibernate/src/NHibernate/Driver/DriverBase.cs
trunk/nhibernate/src/NHibernate/Driver/IDriver.cs
trunk/nhibernate/src/NHibernate/Driver/MySqlDataDriver.cs
trunk/nhibernate/src/NHibernate/Driver/NpgsqlDriver.cs
trunk/nhibernate/src/NHibernate/Driver/SQLite20Driver.cs
trunk/nhibernate/src/NHibernate/Driver/SqlClientDriver.cs
trunk/nhibernate/src/NHibernate/Driver/SqlServerCeDriver.cs
trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs
trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs
trunk/nhibernate/src/NHibernate/NHibernate.csproj
Added Paths:
-----------
trunk/nhibernate/src/NHibernate/Driver/BasicResultSetsCommand.cs
trunk/nhibernate/src/NHibernate/Driver/IResultSetsCommand.cs
Modified: trunk/nhibernate/releasenotes.txt
===================================================================
--- trunk/nhibernate/releasenotes.txt 2011-03-28 19:43:25 UTC (rev 5567)
+++ trunk/nhibernate/releasenotes.txt 2011-03-29 14:23:44 UTC (rev 5568)
@@ -6,6 +6,7 @@
* [NH-2550] - Allow public access to FieldInterceptor Session (IFieldInterceptor changed)
* [NH-2593] - Form 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]
+ * [NH-2605] Refactorize MultiQuery/MultiCriteria implementation to delegate responsibility to IDrive (IDrive changed).
Build 3.1.0.GA (rev5425)
=============================
Added: trunk/nhibernate/src/NHibernate/Driver/BasicResultSetsCommand.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Driver/BasicResultSetsCommand.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Driver/BasicResultSetsCommand.cs 2011-03-29 14:23:44 UTC (rev 5568)
@@ -0,0 +1,307 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using NHibernate.Engine;
+using NHibernate.SqlCommand;
+using NHibernate.SqlTypes;
+
+namespace NHibernate.Driver
+{
+ public class BasicResultSetsCommand: IResultSetsCommand
+ {
+ private static readonly IInternalLogger log = LoggerProvider.LoggerFor(typeof(BasicResultSetsCommand));
+
+ private readonly ISessionImplementor session;
+ private readonly Dialect.Dialect dialect;
+ private readonly IBatcher batcher;
+ private int resultSetsCount = 0;
+ private readonly List<SqlType> types = new List<SqlType>();
+ private SqlString sqlString = new SqlString();
+
+ public BasicResultSetsCommand(ISessionImplementor session)
+ {
+ this.session = session;
+ dialect = session.Factory.Dialect;
+ batcher = session.Batcher;
+ }
+
+ public virtual void Append(SqlCommandInfo commandInfo)
+ {
+ resultSetsCount++;
+ sqlString = sqlString.Append(commandInfo.Text).Append(";").Append(Environment.NewLine);
+ types.AddRange(commandInfo.ParameterTypes);
+ }
+
+ public int ParametersCount
+ {
+ get { return types.Count; }
+ }
+
+ public bool HasQueries
+ {
+ get { return resultSetsCount > 0; }
+ }
+
+ public SqlString Sql
+ {
+ get { return sqlString; }
+ }
+
+ public virtual IDataReader GetReader(QueryParameters[] queryParameters, int? commandTimeout)
+ {
+ SqlType[] sqlTypes = types.ToArray();
+ var command= batcher.PrepareQueryCommand(CommandType.Text, sqlString, sqlTypes);
+ if(commandTimeout.HasValue)
+ {
+ command.CommandTimeout = commandTimeout.Value;
+ }
+ log.Info(command.CommandText);
+
+ BindParameters(command, queryParameters);
+ return new BatcherDataReaderWrapper(batcher, command);
+ }
+
+ protected virtual void BindParameters(IDbCommand command, QueryParameters[] queryParameters)
+ {
+ int colIndex = 0;
+
+ for (int queryIndex = 0; queryIndex < resultSetsCount; queryIndex++)
+ {
+ int limitParameterSpan = BindLimitParametersFirstIfNeccesary(command, queryParameters[queryIndex], colIndex);
+ colIndex = BindQueryParameters(command, queryParameters[queryIndex], colIndex + limitParameterSpan);
+ colIndex += BindLimitParametersLastIfNeccesary(command, queryParameters[queryIndex], colIndex);
+ }
+ }
+
+ protected virtual int BindLimitParametersLastIfNeccesary(IDbCommand command, QueryParameters parameter, int colIndex)
+ {
+ RowSelection selection = parameter.RowSelection;
+ if (Loader.Loader.UseLimit(selection, dialect) && !dialect.BindLimitParametersFirst)
+ {
+ return Loader.Loader.BindLimitParameters(command, colIndex, selection, session);
+ }
+ return 0;
+ }
+
+ protected virtual int BindQueryParameters(IDbCommand command, QueryParameters parameter, int colIndex)
+ {
+ colIndex += parameter.BindParameters(command, colIndex, session);
+ return colIndex;
+ }
+
+ protected virtual int BindLimitParametersFirstIfNeccesary(IDbCommand command, QueryParameters parameter, int colIndex)
+ {
+ int limitParameterSpan = 0;
+ RowSelection selection = parameter.RowSelection;
+ if (Loader.Loader.UseLimit(selection, dialect) && dialect.BindLimitParametersFirst)
+ {
+ limitParameterSpan += Loader.Loader.BindLimitParameters(command, colIndex, selection, session);
+ }
+ return limitParameterSpan;
+ }
+ }
+
+ /// <summary>
+ /// Datareader wrapper with the same life cycle of its command (through the batcher)
+ /// </summary>
+ public class BatcherDataReaderWrapper: IDataReader
+ {
+ private readonly IBatcher batcher;
+ private readonly IDbCommand command;
+ private readonly IDataReader reader;
+
+ public BatcherDataReaderWrapper(IBatcher batcher, IDbCommand command)
+ {
+ if (batcher == null)
+ {
+ throw new ArgumentNullException("batcher");
+ }
+ if (command == null)
+ {
+ throw new ArgumentNullException("command");
+ }
+ this.batcher = batcher;
+ this.command = command;
+ reader = batcher.ExecuteReader(command);
+ }
+
+ public void Dispose()
+ {
+ batcher.CloseCommand(command, reader);
+ }
+
+ #region IDataRecord Members
+
+ public string GetName(int i)
+ {
+ return reader.GetName(i);
+ }
+
+ public string GetDataTypeName(int i)
+ {
+ return reader.GetDataTypeName(i);
+ }
+
+ public System.Type GetFieldType(int i)
+ {
+ return reader.GetFieldType(i);
+ }
+
+ public object GetValue(int i)
+ {
+ return reader.GetDecimal(i);
+ }
+
+ public int GetValues(object[] values)
+ {
+ return reader.GetValues(values);
+ }
+
+ public int GetOrdinal(string name)
+ {
+ return reader.GetOrdinal(name);
+ }
+
+ public bool GetBoolean(int i)
+ {
+ return reader.GetBoolean(i);
+ }
+
+ public byte GetByte(int i)
+ {
+ return reader.GetByte(i);
+ }
+
+ public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
+ {
+ return reader.GetBytes(i, fieldOffset, buffer, bufferoffset, length);
+ }
+
+ public char GetChar(int i)
+ {
+ return reader.GetChar(i);
+ }
+
+ public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
+ {
+ return reader.GetChars(i, fieldoffset, buffer, bufferoffset, length);
+ }
+
+ public Guid GetGuid(int i)
+ {
+ return reader.GetGuid(i);
+ }
+
+ public short GetInt16(int i)
+ {
+ return reader.GetInt16(i);
+ }
+
+ public int GetInt32(int i)
+ {
+ return reader.GetInt32(i);
+ }
+
+ public long GetInt64(int i)
+ {
+ return reader.GetInt64(i);
+ }
+
+ public float GetFloat(int i)
+ {
+ return reader.GetFloat(i);
+ }
+
+ public double GetDouble(int i)
+ {
+ return reader.GetDouble(i);
+ }
+
+ public string GetString(int i)
+ {
+ return reader.GetString(i);
+ }
+
+ public decimal GetDecimal(int i)
+ {
+ return reader.GetDecimal(i);
+ }
+
+ public DateTime GetDateTime(int i)
+ {
+ return reader.GetDateTime(i);
+ }
+
+ public IDataReader GetData(int i)
+ {
+ return reader.GetData(i);
+ }
+
+ public bool IsDBNull(int i)
+ {
+ return reader.IsDBNull(i);
+ }
+
+ public int FieldCount
+ {
+ get { return reader.FieldCount; }
+ }
+
+ public object this[int i]
+ {
+ get { return reader[i]; }
+ }
+
+ public object this[string name]
+ {
+ get { return reader[name]; }
+ }
+
+ #endregion
+
+ public override bool Equals(object obj)
+ {
+ return reader.Equals(obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return reader.GetHashCode();
+ }
+
+ public void Close()
+ {
+ batcher.CloseCommand(command, reader);
+ }
+
+ public DataTable GetSchemaTable()
+ {
+ return reader.GetSchemaTable();
+ }
+
+ public bool NextResult()
+ {
+ return reader.NextResult();
+ }
+
+ public bool Read()
+ {
+ return reader.Read();
+ }
+
+ public int Depth
+ {
+ get { return reader.Depth; }
+ }
+
+ public bool IsClosed
+ {
+ get { return reader.IsClosed; }
+ }
+
+ public int RecordsAffected
+ {
+ get { return reader.RecordsAffected; }
+ }
+ }
+}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate/Driver/DriverBase.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Driver/DriverBase.cs 2011-03-28 19:43:25 UTC (rev 5567)
+++ trunk/nhibernate/src/NHibernate/Driver/DriverBase.cs 2011-03-29 14:23:44 UTC (rev 5568)
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Data;
-
+using NHibernate.Engine;
using NHibernate.SqlCommand;
using NHibernate.SqlTypes;
using NHibernate.Util;
@@ -166,11 +166,16 @@
private void SetCommandText(IDbCommand cmd, SqlString sqlString)
{
- SqlStringFormatter formatter = new SqlStringFormatter(this, MultipleQueriesSeparator);
+ SqlStringFormatter formatter = GetSqlStringFormatter();
formatter.Format(sqlString);
cmd.CommandText = formatter.GetFormattedText();
}
+ protected virtual SqlStringFormatter GetSqlStringFormatter()
+ {
+ return new SqlStringFormatter(this, ";");
+ }
+
private void SetCommandParameters(IDbCommand cmd, SqlType[] sqlTypes)
{
for (int i = 0; i < sqlTypes.Length; i++)
@@ -229,6 +234,16 @@
cmd.Parameters.Add(parameter);
}
+ public virtual IResultSetsCommand GetResultSetsCommand(ISessionImplementor session)
+ {
+ throw new NotSupportedException(string.Format("The driver {0} does not support multiple queries.", GetType().FullName));
+ }
+
+ public virtual bool SupportsMultipleQueries
+ {
+ get { return false; }
+ }
+
protected virtual IDbDataParameter CloneParameter(IDbCommand cmd, IDbDataParameter originalParameter)
{
var clone = cmd.CreateParameter();
@@ -263,15 +278,5 @@
param.Direction = ParameterDirection.Output;
return param;
}
-
- public virtual bool SupportsMultipleQueries
- {
- get { return false; }
- }
-
- public virtual string MultipleQueriesSeparator
- {
- get { return ";"; }
- }
}
}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate/Driver/IDriver.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Driver/IDriver.cs 2011-03-28 19:43:25 UTC (rev 5567)
+++ trunk/nhibernate/src/NHibernate/Driver/IDriver.cs 2011-03-29 14:23:44 UTC (rev 5568)
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Data;
+using NHibernate.Engine;
using NHibernate.SqlCommand;
using NHibernate.SqlTypes;
@@ -60,17 +61,6 @@
bool SupportsMultipleOpenReaders { get; }
/// <summary>
- /// Can we issue several select queries in a single query, and get
- /// several result sets back?
- /// </summary>
- bool SupportsMultipleQueries { get; }
-
- /// <summary>
- /// How we separate the queries when we use multiply queries.
- /// </summary>
- string MultipleQueriesSeparator { get; }
-
- /// <summary>
/// Generates an IDbCommand from the SqlString according to the requirements of the DataProvider.
/// </summary>
/// <param name="type">The <see cref="CommandType"/> of the command to generate.</param>
@@ -106,5 +96,8 @@
/// 'select ... from MyTable t where t.Col1 = ? and t.Col2 = ?'
/// </remarks>
void ExpandQueryParameters(IDbCommand cmd, SqlString sqlString);
+
+ IResultSetsCommand GetResultSetsCommand(ISessionImplementor session);
+ bool SupportsMultipleQueries { get; }
}
}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Driver/IResultSetsCommand.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Driver/IResultSetsCommand.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Driver/IResultSetsCommand.cs 2011-03-29 14:23:44 UTC (rev 5568)
@@ -0,0 +1,15 @@
+using System.Data;
+using NHibernate.Engine;
+using NHibernate.SqlCommand;
+
+namespace NHibernate.Driver
+{
+ public interface IResultSetsCommand
+ {
+ void Append(SqlCommandInfo commandInfo);
+ int ParametersCount { get; }
+ bool HasQueries { get; }
+ SqlString Sql { get; }
+ IDataReader GetReader(QueryParameters[] queryParameters, int? commandTimeout);
+ }
+}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate/Driver/MySqlDataDriver.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Driver/MySqlDataDriver.cs 2011-03-28 19:43:25 UTC (rev 5567)
+++ trunk/nhibernate/src/NHibernate/Driver/MySqlDataDriver.cs 2011-03-29 14:23:44 UTC (rev 5568)
@@ -79,6 +79,11 @@
get { return false; }
}
+ public override IResultSetsCommand GetResultSetsCommand(Engine.ISessionImplementor session)
+ {
+ return new BasicResultSetsCommand(session);
+ }
+
public override bool SupportsMultipleQueries
{
get { return true; }
Modified: trunk/nhibernate/src/NHibernate/Driver/NpgsqlDriver.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Driver/NpgsqlDriver.cs 2011-03-28 19:43:25 UTC (rev 5567)
+++ trunk/nhibernate/src/NHibernate/Driver/NpgsqlDriver.cs 2011-03-29 14:23:44 UTC (rev 5568)
@@ -63,6 +63,11 @@
get { return true; }
}
+ public override IResultSetsCommand GetResultSetsCommand(Engine.ISessionImplementor session)
+ {
+ return new BasicResultSetsCommand(session);
+ }
+
public override bool SupportsMultipleQueries
{
get { return true; }
Modified: trunk/nhibernate/src/NHibernate/Driver/SQLite20Driver.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Driver/SQLite20Driver.cs 2011-03-28 19:43:25 UTC (rev 5567)
+++ trunk/nhibernate/src/NHibernate/Driver/SQLite20Driver.cs 2011-03-29 14:23:44 UTC (rev 5568)
@@ -76,7 +76,12 @@
{
get { return false; }
}
-
+
+ public override IResultSetsCommand GetResultSetsCommand(Engine.ISessionImplementor session)
+ {
+ return new BasicResultSetsCommand(session);
+ }
+
public override bool SupportsMultipleQueries
{
get { return true; }
Modified: trunk/nhibernate/src/NHibernate/Driver/SqlClientDriver.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Driver/SqlClientDriver.cs 2011-03-28 19:43:25 UTC (rev 5567)
+++ trunk/nhibernate/src/NHibernate/Driver/SqlClientDriver.cs 2011-03-29 14:23:44 UTC (rev 5568)
@@ -2,6 +2,7 @@
using System.Data.SqlClient;
using NHibernate.AdoNet;
using NHibernate.Dialect;
+using NHibernate.Engine;
using NHibernate.SqlCommand;
using NHibernate.SqlTypes;
@@ -91,11 +92,6 @@
get { return false; }
}
- public override bool SupportsMultipleQueries
- {
- get { return true; }
- }
-
public override IDbCommand GenerateCommand(CommandType type, SqlString sqlString, SqlType[] parameterTypes)
{
IDbCommand command = base.GenerateCommand(type, sqlString, parameterTypes);
@@ -189,5 +185,15 @@
}
#endregion
+
+ public override IResultSetsCommand GetResultSetsCommand(ISessionImplementor session)
+ {
+ return new BasicResultSetsCommand(session);
+ }
+
+ public override bool SupportsMultipleQueries
+ {
+ get { return true; }
+ }
}
}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate/Driver/SqlServerCeDriver.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Driver/SqlServerCeDriver.cs 2011-03-28 19:43:25 UTC (rev 5567)
+++ trunk/nhibernate/src/NHibernate/Driver/SqlServerCeDriver.cs 2011-03-29 14:23:44 UTC (rev 5568)
@@ -98,6 +98,11 @@
return command;
}
+ public override IResultSetsCommand GetResultSetsCommand(Engine.ISessionImplementor session)
+ {
+ return new BasicResultSetsCommand(session);
+ }
+
public override bool SupportsMultipleQueries
{
get { return true; }
Modified: trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs 2011-03-28 19:43:25 UTC (rev 5567)
+++ trunk/nhibernate/src/NHibernate/Impl/MultiCriteriaImpl.cs 2011-03-29 14:23:44 UTC (rev 5568)
@@ -1,7 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using System.Data;
using System.Diagnostics;
using Iesi.Collections;
using Iesi.Collections.Generic;
@@ -11,7 +10,6 @@
using NHibernate.Engine;
using NHibernate.Loader.Criteria;
using NHibernate.SqlCommand;
-using NHibernate.SqlTypes;
using NHibernate.Transform;
using NHibernate.Type;
@@ -27,8 +25,6 @@
private readonly ISessionFactoryImplementor factory;
private readonly List<CriteriaQueryTranslator> translators = new List<CriteriaQueryTranslator>();
private readonly List<QueryParameters> parameters = new List<QueryParameters>();
- private readonly List<SqlType> types = new List<SqlType>();
- private SqlString sqlString = new SqlString();
private readonly List<CriteriaLoader> loaders = new List<CriteriaLoader>();
private readonly Dialect.Dialect dialect;
private IList criteriaResults;
@@ -38,6 +34,7 @@
private string cacheRegion;
private IResultTransformer resultTransformer;
private readonly Dictionary<CriteriaLoader, int> loaderToResultIndex = new Dictionary<CriteriaLoader, int>();
+ private readonly IResultSetsCommand resultSetsCommand;
/// <summary>
/// Initializes a new instance of the <see cref="MultiCriteriaImpl"/> class.
@@ -47,20 +44,18 @@
internal MultiCriteriaImpl(SessionImpl session, ISessionFactoryImplementor factory)
{
IDriver driver = session.Factory.ConnectionProvider.Driver;
- if (!driver.SupportsMultipleQueries)
- {
- throw new NotSupportedException(
- string.Format("The driver {0} does not support multiple queries.", driver.GetType().FullName));
- }
dialect = session.Factory.Dialect;
+ resultSetsCommand = driver.GetResultSetsCommand(session);
this.session = session;
this.factory = factory;
}
-
public SqlString SqlString
{
- get { return sqlString; }
+ get
+ {
+ return resultSetsCommand.Sql;
+ }
}
public IList List()
@@ -179,11 +174,8 @@
translators.Add(translator);
QueryParameters queryParameters = translator.GetQueryParameters();
parameters.Add(queryParameters);
- SqlCommandInfo commandInfo = loader.GetQueryStringAndTypes(session, queryParameters, types.Count);
- sqlString = sqlString.Append(commandInfo.Text)
- .Append(session.Factory.ConnectionProvider.Driver.MultipleQueriesSeparator)
- .Append(Environment.NewLine);
- types.AddRange(commandInfo.ParameterTypes);
+ SqlCommandInfo commandInfo = loader.GetQueryStringAndTypes(session, queryParameters, resultSetsCommand.ParametersCount);
+ resultSetsCommand.Append(commandInfo);
}
}
@@ -197,15 +189,11 @@
}
int rowCount = 0;
- using (
- IDbCommand command =
- session.Batcher.PrepareCommand(CommandType.Text, sqlString, types.ToArray()))
+ using (var reader = resultSetsCommand.GetReader(parameters.ToArray(), null))
{
- BindParameters(command);
ArrayList[] hydratedObjects = new ArrayList[loaders.Count];
List<EntityKey[]>[] subselectResultKeys = new List<EntityKey[]>[loaders.Count];
bool[] createSubselects = new bool[loaders.Count];
- IDataReader reader = session.Batcher.ExecuteReader(command);
try
{
for (int i = 0; i < loaders.Count; i++)
@@ -254,13 +242,10 @@
}
catch (Exception e)
{
- log.Error("Error executing multi criteria : [" + command.CommandText + "]");
- throw new HibernateException("Error executing multi criteria : [" + command.CommandText + "]", e);
+ var message = string.Format("Failed to execute multi criteria: [{0}]", resultSetsCommand.Sql);
+ log.Error(message, e);
+ throw new HibernateException(message, e);
}
- finally
- {
- session.Batcher.CloseCommand(command, reader);
- }
for (int i = 0; i < loaders.Count; i++)
{
CriteriaLoader loader = loaders[i];
@@ -310,48 +295,6 @@
}
}
- private void BindParameters(IDbCommand command)
- {
- int colIndex = 0;
-
- for (int queryIndex = 0; queryIndex < loaders.Count; queryIndex++)
- {
- int limitParameterSpan = BindLimitParametersFirstIfNeccesary(command, queryIndex, colIndex);
- colIndex = BindQueryParameters(command, queryIndex, colIndex + limitParameterSpan);
- colIndex += BindLimitParametersLastIfNeccesary(command, queryIndex, colIndex);
- }
- }
-
- private int BindLimitParametersLastIfNeccesary(IDbCommand command, int queryIndex, int colIndex)
- {
- QueryParameters parameter = parameters[queryIndex];
- RowSelection selection = parameter.RowSelection;
- if (Loader.Loader.UseLimit(selection, dialect) && !dialect.BindLimitParametersFirst)
- {
- return Loader.Loader.BindLimitParameters(command, colIndex, selection, session);
- }
- return 0;
- }
-
- private int BindQueryParameters(IDbCommand command, int queryIndex, int colIndex)
- {
- QueryParameters parameter = parameters[queryIndex];
- colIndex += parameter.BindParameters(command, colIndex, session);
- return colIndex;
- }
-
- private int BindLimitParametersFirstIfNeccesary(IDbCommand command, int queryIndex, int colIndex)
- {
- int limitParametersSpan = 0;
- QueryParameters parameter = parameters[queryIndex];
- RowSelection selection = parameter.RowSelection;
- if (Loader.Loader.UseLimit(selection, dialect) && dialect.BindLimitParametersFirst)
- {
- limitParametersSpan += Loader.Loader.BindLimitParameters(command, colIndex, selection, session);
- }
- return limitParametersSpan;
- }
-
public IMultiCriteria Add(System.Type resultGenericListType, ICriteria criteria)
{
criteriaQueries.Add(criteria);
Modified: trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs 2011-03-28 19:43:25 UTC (rev 5567)
+++ trunk/nhibernate/src/NHibernate/Impl/MultiQueryImpl.cs 2011-03-29 14:23:44 UTC (rev 5568)
@@ -1,8 +1,8 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using System.Data;
using System.Diagnostics;
+using System.Linq;
using Iesi.Collections;
using Iesi.Collections.Generic;
using NHibernate.Cache;
@@ -13,7 +13,6 @@
using NHibernate.Loader.Custom;
using NHibernate.Loader.Custom.Sql;
using NHibernate.SqlCommand;
-using NHibernate.SqlTypes;
using NHibernate.Transform;
using NHibernate.Type;
@@ -34,23 +33,18 @@
private bool isCacheable;
private readonly ISessionImplementor session;
private IResultTransformer resultTransformer;
- private readonly List<SqlType> types = new List<SqlType>();
- private SqlString sqlString;
private readonly Dialect.Dialect dialect;
private bool forceCacheRefresh;
private QueryParameters combinedParameters;
private FlushMode flushMode = FlushMode.Unspecified;
private FlushMode sessionFlushMode = FlushMode.Unspecified;
+ private readonly IResultSetsCommand resultSetsCommand;
public MultiQueryImpl(ISessionImplementor session)
{
IDriver driver = session.Factory.ConnectionProvider.Driver;
- if (!driver.SupportsMultipleQueries)
- {
- throw new NotSupportedException(
- string.Format("The driver {0} does not support multiple queries.", driver.GetType().FullName));
- }
dialect = session.Factory.Dialect;
+ resultSetsCommand = driver.GetResultSetsCommand(session);
this.session = session;
}
@@ -508,126 +502,121 @@
}
int rowCount = 0;
- IDbCommand command = PrepareQueriesCommand();
-
- BindParameters(command);
-
ArrayList results = new ArrayList();
- log.Info(command.CommandText);
- if (commandTimeout != RowSelection.NoValue)
- command.CommandTimeout = commandTimeout;
ArrayList[] hydratedObjects = new ArrayList[Translators.Count];
List<EntityKey[]>[] subselectResultKeys = new List<EntityKey[]>[Translators.Count];
bool[] createSubselects = new bool[Translators.Count];
- IDataReader reader = session.Batcher.ExecuteReader(command);
- try
+
+ using (var reader = resultSetsCommand.GetReader(Parameters.ToArray(), commandTimeout != RowSelection.NoValue ? commandTimeout : (int?)null))
{
- if (log.IsDebugEnabled)
+ try
{
- log.DebugFormat("Executing {0} queries", translators.Count);
- }
- for (int i = 0; i < translators.Count; i++)
- {
- ITranslator translator = Translators[i];
- QueryParameters parameter = Parameters[i];
- IList tempResults;
- if (resultCollectionGenericType[i] == typeof(object))
+ if (log.IsDebugEnabled)
{
- tempResults = new ArrayList();
+ log.DebugFormat("Executing {0} queries", translators.Count);
}
- else
+ for (int i = 0; i < translators.Count; i++)
{
- tempResults = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(resultCollectionGenericType[i]));
- }
- int entitySpan = translator.Loader.EntityPersisters.Length;
- hydratedObjects[i] = entitySpan > 0 ? new ArrayList() : null;
- RowSelection selection = parameter.RowSelection;
- int maxRows = Loader.Loader.HasMaxRows(selection) ? selection.MaxRows : int.MaxValue;
- if (!dialect.SupportsLimitOffset || !Loader.Loader.UseLimit(selection, dialect))
- {
- Loader.Loader.Advance(reader, selection);
- }
+ ITranslator translator = Translators[i];
+ QueryParameters parameter = Parameters[i];
+ IList tempResults;
+ if (resultCollectionGenericType[i] == typeof (object))
+ {
+ tempResults = new ArrayList();
+ }
+ else
+ {
+ tempResults = (IList) Activator.CreateInstance(typeof (List<>).MakeGenericType(resultCollectionGenericType[i]));
+ }
+ int entitySpan = translator.Loader.EntityPersisters.Length;
+ hydratedObjects[i] = entitySpan > 0 ? new ArrayList() : null;
+ RowSelection selection = parameter.RowSelection;
+ int maxRows = Loader.Loader.HasMaxRows(selection) ? selection.MaxRows : int.MaxValue;
+ if (!dialect.SupportsLimitOffset || !Loader.Loader.UseLimit(selection, dialect))
+ {
+ Loader.Loader.Advance(reader, selection);
+ }
- LockMode[] lockModeArray = translator.Loader.GetLockModes(parameter.LockModes);
- EntityKey optionalObjectKey = Loader.Loader.GetOptionalObjectKey(parameter, session);
+ LockMode[] lockModeArray = translator.Loader.GetLockModes(parameter.LockModes);
+ EntityKey optionalObjectKey = Loader.Loader.GetOptionalObjectKey(parameter, session);
- createSubselects[i] = translator.Loader.IsSubselectLoadingEnabled;
- subselectResultKeys[i] = createSubselects[i] ? new List<EntityKey[]>() : null;
+ createSubselects[i] = translator.Loader.IsSubselectLoadingEnabled;
+ subselectResultKeys[i] = createSubselects[i] ? new List<EntityKey[]>() : null;
- translator.Loader.HandleEmptyCollections(parameter.CollectionKeys, reader, session);
- EntityKey[] keys = new EntityKey[entitySpan]; // we can reuse it each time
+ translator.Loader.HandleEmptyCollections(parameter.CollectionKeys, reader, session);
+ EntityKey[] keys = new EntityKey[entitySpan]; // we can reuse it each time
- if (log.IsDebugEnabled)
- {
- log.Debug("processing result set");
- }
-
- int count;
- for (count = 0; count < maxRows && reader.Read(); count++)
- {
if (log.IsDebugEnabled)
{
- log.Debug("result set row: " + count);
+ log.Debug("processing result set");
}
- rowCount++;
+ int count;
+ for (count = 0; count < maxRows && reader.Read(); count++)
+ {
+ if (log.IsDebugEnabled)
+ {
+ log.Debug("result set row: " + count);
+ }
- object result =
- translator.Loader.GetRowFromResultSet(reader,
- session,
- parameter,
- lockModeArray,
- optionalObjectKey,
- hydratedObjects[i],
- keys,
- true);
+ rowCount++;
- tempResults.Add(result);
+ object result =
+ translator.Loader.GetRowFromResultSet(reader,
+ session,
+ parameter,
+ lockModeArray,
+ optionalObjectKey,
+ hydratedObjects[i],
+ keys,
+ true);
- if (createSubselects[i])
+ tempResults.Add(result);
+
+ if (createSubselects[i])
+ {
+ subselectResultKeys[i].Add(keys);
+ keys = new EntityKey[entitySpan]; //can't reuse in this case
+ }
+ }
+
+ if (log.IsDebugEnabled)
{
- subselectResultKeys[i].Add(keys);
- keys = new EntityKey[entitySpan]; //can't reuse in this case
+ log.Debug(string.Format("done processing result set ({0} rows)", count));
}
- }
- if (log.IsDebugEnabled)
- {
- log.Debug(string.Format("done processing result set ({0} rows)", count));
- }
+ results.Add(tempResults);
- results.Add(tempResults);
+ if (log.IsDebugEnabled)
+ {
+ log.DebugFormat("Query {0} returned {1} results", i, tempResults.Count);
+ }
- if (log.IsDebugEnabled)
- {
- log.DebugFormat("Query {0} returned {1} results", i, tempResults.Count);
+ reader.NextResult();
}
-
- reader.NextResult();
}
- }
- catch (Exception ex)
- {
- log.Error("Failed to execute multi query: [" + command.CommandText + "]", ex);
- throw new HibernateException("Failed to execute multi query: [" + command.CommandText + "]", ex);
- }
- finally
- {
- session.Batcher.CloseCommand(command, reader);
- }
- for (int i = 0; i < translators.Count; i++)
- {
- ITranslator translator = translators[i];
- QueryParameters parameter = parameters[i];
+ catch (Exception ex)
+ {
+ var message = string.Format("Failed to execute multi query: [{0}]", resultSetsCommand.Sql);
+ log.Error(message, ex);
+ throw new HibernateException(message, ex);
+ }
- translator.Loader.InitializeEntitiesAndCollections(hydratedObjects[i], reader, session, false);
-
- if (createSubselects[i])
+ for (int i = 0; i < translators.Count; i++)
{
- translator.Loader.CreateSubselects(subselectResultKeys[i], parameter, session);
+ ITranslator translator = translators[i];
+ QueryParameters parameter = parameters[i];
+
+ translator.Loader.InitializeEntitiesAndCollections(hydratedObjects[i], reader, session, false);
+
+ if (createSubselects[i])
+ {
+ translator.Loader.CreateSubselects(subselectResultKeys[i], parameter, session);
+ }
}
}
+
if (statsEnabled)
{
stopWatch.Stop();
@@ -636,25 +625,18 @@
return results;
}
- private IDbCommand PrepareQueriesCommand()
- {
- SqlType[] sqlTypes = types.ToArray();
- return session.Batcher.PrepareQueryCommand(CommandType.Text, SqlString, sqlTypes);
- }
-
protected SqlString SqlString
{
get
{
- if (sqlString == null)
+ if (!resultSetsCommand.HasQueries)
AggregateQueriesInformation();
- return sqlString;
+ return resultSetsCommand.Sql;
}
}
private void AggregateQueriesInformation()
{
- sqlString = new SqlString();
foreach (AbstractQueryImpl query in queries)
{
QueryParameters queryParameters = query.GetQueryParameters();
@@ -665,9 +647,8 @@
translators.Add(translator);
parameters.Add(queryParameters);
queryParameters = GetFilteredQueryParameters(queryParameters, translator);
- SqlCommandInfo commandInfo = translator.Loader.GetQueryStringAndTypes(session, queryParameters, types.Count);
- sqlString = sqlString.Append(commandInfo.Text).Append(session.Factory.ConnectionProvider.Driver.MultipleQueriesSeparator).Append(Environment.NewLine);
- types.AddRange(commandInfo.ParameterTypes);
+ SqlCommandInfo commandInfo = translator.Loader.GetQueryStringAndTypes(session, queryParameters, resultSetsCommand.ParametersCount);
+ resultSetsCommand.Append(commandInfo);
}
}
}
@@ -706,36 +687,6 @@
return filteredQueryParameters;
}
- private void BindParameters(IDbCommand command)
- {
- int colIndex = 0;
-
- for (int queryIndex = 0; queryIndex < queries.Count; queryIndex++)
- {
- int limitParameterSpan = BindLimitParametersFirstIfNeccesary(command, queryIndex, colIndex);
- colIndex = BindQueryParameters(command, queryIndex, colIndex + limitParameterSpan);
- colIndex += BindLimitParametersLastIfNeccesary(command, queryIndex, colIndex);
- }
- }
-
- private int BindLimitParametersLastIfNeccesary(IDbCommand command, int queryIndex, int colIndex)
- {
- QueryParameters parameter = parameters[queryIndex];
- RowSelection selection = parameter.RowSelection;
- if (Loader.Loader.UseLimit(selection, dialect) && !dialect.BindLimitParametersFirst)
- {
- return Loader.Loader.BindLimitParameters(command, colIndex, selection, session);
- }
- return 0;
- }
-
- private int BindQueryParameters(IDbCommand command, int queryIndex, int colIndex)
- {
- QueryParameters parameter = Parameters[queryIndex];
- colIndex += parameter.BindParameters(command, colIndex, session);
- return colIndex;
- }
-
public object GetResult(string key)
{
if (queryResults == null)
@@ -751,18 +702,6 @@
return queryResults[queryResultPositions[key]];
}
- private int BindLimitParametersFirstIfNeccesary(IDbCommand command, int queryIndex, int colIndex)
- {
- int limitParameterSpan = 0;
- QueryParameters parameter = Parameters[queryIndex];
- RowSelection selection = parameter.RowSelection;
- if (Loader.Loader.UseLimit(selection, dialect) && dialect.BindLimitParametersFirst)
- {
- limitParameterSpan += Loader.Loader.BindLimitParameters(command, colIndex, selection, session);
- }
- return limitParameterSpan;
- }
-
public override string ToString()
{
return "Multi Query: [" + SqlString + "]";
@@ -821,7 +760,7 @@
{
get
{
- if (sqlString == null)
+ if (!resultSetsCommand.HasQueries)
{
AggregateQueriesInformation();
}
@@ -856,7 +795,7 @@
{
get
{
- if (sqlString == null)
+ if (!resultSetsCommand.HasQueries)
AggregateQueriesInformation();
return parameters;
}
Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj
===================================================================
--- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-03-28 19:43:25 UTC (rev 5567)
+++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-03-29 14:23:44 UTC (rev 5568)
@@ -146,6 +146,7 @@
<Compile Include="Driver\DriverBase.cs" />
<Compile Include="Driver\FirebirdDriver.cs" />
<Compile Include="Driver\IDriver.cs" />
+ <Compile Include="Driver\IResultSetsCommand.cs" />
<Compile Include="Driver\MySqlDataDriver.cs" />
<Compile Include="Driver\NDataReader.cs" />
<Compile Include="Driver\NHybridDataReader.cs" />
@@ -155,6 +156,7 @@
<Compile Include="Driver\OracleClientDriver.cs" />
<Compile Include="Driver\OracleDataClientDriver.cs" />
<Compile Include="Driver\SqlClientDriver.cs" />
+ <Compile Include="Driver\BasicResultSetsCommand.cs" />
<Compile Include="Driver\SQLiteDriver.cs" />
<Compile Include="Engine\Cascade.cs" />
<Compile Include="Engine\IBatcher.cs" />
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|