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. |