PageRenderTime 24ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/src/NHibernate/Engine/Query/HQLQueryPlan.cs

https://github.com/ngbrown/nhibernate-core
C# | 256 lines | 225 code | 28 blank | 3 comment | 28 complexity | 2b7658fdef596198aceb59bb72bb9d4c MD5 | raw file
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using NHibernate.Event;
  5. using NHibernate.Hql;
  6. using NHibernate.Linq;
  7. using NHibernate.Type;
  8. using NHibernate.Util;
  9. namespace NHibernate.Engine.Query
  10. {
  11. public partial interface IQueryPlan
  12. {
  13. ParameterMetadata ParameterMetadata { get; }
  14. ISet<string> QuerySpaces { get; }
  15. IQueryTranslator[] Translators { get; }
  16. ReturnMetadata ReturnMetadata { get; }
  17. void PerformList(QueryParameters queryParameters, ISessionImplementor statelessSessionImpl, IList results);
  18. int PerformExecuteUpdate(QueryParameters queryParameters, ISessionImplementor statelessSessionImpl);
  19. IEnumerable<T> PerformIterate<T>(QueryParameters queryParameters, IEventSource session);
  20. IEnumerable PerformIterate(QueryParameters queryParameters, IEventSource session);
  21. }
  22. public interface IQueryExpressionPlan : IQueryPlan
  23. {
  24. IQueryExpression QueryExpression { get; }
  25. }
  26. /// <summary> Defines a query execution plan for an HQL query (or filter). </summary>
  27. [Serializable]
  28. public partial class HQLQueryPlan : IQueryPlan
  29. {
  30. protected static readonly INHibernateLogger Log = NHibernateLogger.For(typeof(HQLQueryPlan));
  31. private readonly string _sourceQuery;
  32. protected HQLQueryPlan(string sourceQuery, IQueryTranslator[] translators)
  33. {
  34. Translators = translators;
  35. _sourceQuery = sourceQuery;
  36. FinaliseQueryPlan();
  37. }
  38. internal HQLQueryPlan(HQLQueryPlan source)
  39. {
  40. Translators = source.Translators;
  41. _sourceQuery = source._sourceQuery;
  42. QuerySpaces = source.QuerySpaces;
  43. ParameterMetadata = source.ParameterMetadata;
  44. ReturnMetadata = source.ReturnMetadata;
  45. SqlStrings = source.SqlStrings;
  46. }
  47. public ISet<string> QuerySpaces
  48. {
  49. get;
  50. private set;
  51. }
  52. public ParameterMetadata ParameterMetadata
  53. {
  54. get;
  55. private set;
  56. }
  57. public ReturnMetadata ReturnMetadata
  58. {
  59. get;
  60. private set;
  61. }
  62. public string[] SqlStrings
  63. {
  64. get;
  65. private set;
  66. }
  67. public IQueryTranslator[] Translators
  68. {
  69. get;
  70. private set;
  71. }
  72. public void PerformList(QueryParameters queryParameters, ISessionImplementor session, IList results)
  73. {
  74. if (Log.IsDebugEnabled())
  75. {
  76. Log.Debug("find: {0}", _sourceQuery);
  77. queryParameters.LogParameters(session.Factory);
  78. }
  79. bool hasLimit = queryParameters.RowSelection != null && queryParameters.RowSelection.DefinesLimits;
  80. bool needsLimit = hasLimit && Translators.Length > 1;
  81. QueryParameters queryParametersToUse;
  82. if (needsLimit)
  83. {
  84. Log.Warn("firstResult/maxResults specified on polymorphic query; applying in memory!");
  85. RowSelection selection = new RowSelection();
  86. selection.FetchSize = queryParameters.RowSelection.FetchSize;
  87. selection.Timeout = queryParameters.RowSelection.Timeout;
  88. queryParametersToUse = queryParameters.CreateCopyUsing(selection);
  89. }
  90. else
  91. {
  92. queryParametersToUse = queryParameters;
  93. }
  94. IList combinedResults = results ?? new List<object>();
  95. var distinction = new HashSet<object>(ReferenceComparer<object>.Instance);
  96. int includedCount = -1;
  97. for (int i = 0; i < Translators.Length; i++)
  98. {
  99. IList tmp = Translators[i].List(session, queryParametersToUse);
  100. if (needsLimit)
  101. {
  102. // NOTE : firstRow is zero-based
  103. int first = queryParameters.RowSelection.FirstRow == RowSelection.NoValue
  104. ? 0
  105. : queryParameters.RowSelection.FirstRow;
  106. int max = queryParameters.RowSelection.MaxRows == RowSelection.NoValue
  107. ? RowSelection.NoValue
  108. : queryParameters.RowSelection.MaxRows;
  109. int size = tmp.Count;
  110. for (int x = 0; x < size; x++)
  111. {
  112. object result = tmp[x];
  113. if (!distinction.Add(result))
  114. {
  115. continue;
  116. }
  117. includedCount++;
  118. if (includedCount < first)
  119. {
  120. continue;
  121. }
  122. combinedResults.Add(result);
  123. if (max >= 0 && includedCount > max)
  124. {
  125. // break the outer loop !!!
  126. return;
  127. }
  128. }
  129. }
  130. else
  131. ArrayHelper.AddAll(combinedResults, tmp);
  132. }
  133. }
  134. public IEnumerable PerformIterate(QueryParameters queryParameters, IEventSource session)
  135. {
  136. if (Log.IsDebugEnabled())
  137. {
  138. Log.Debug("enumerable: {0}", _sourceQuery);
  139. queryParameters.LogParameters(session.Factory);
  140. }
  141. if (Translators.Length == 0)
  142. {
  143. return CollectionHelper.EmptyEnumerable;
  144. }
  145. if (Translators.Length == 1)
  146. {
  147. return Translators[0].GetEnumerable(queryParameters, session);
  148. }
  149. var results = new IEnumerable[Translators.Length];
  150. for (int i = 0; i < Translators.Length; i++)
  151. {
  152. var result = Translators[i].GetEnumerable(queryParameters, session);
  153. results[i] = result;
  154. }
  155. return new JoinedEnumerable(results);
  156. }
  157. public IEnumerable<T> PerformIterate<T>(QueryParameters queryParameters, IEventSource session)
  158. {
  159. return PerformIterate(queryParameters, session).CastOrDefault<T>();
  160. }
  161. public int PerformExecuteUpdate(QueryParameters queryParameters, ISessionImplementor session)
  162. {
  163. if (Log.IsDebugEnabled())
  164. {
  165. Log.Debug("executeUpdate: {0}", _sourceQuery);
  166. queryParameters.LogParameters(session.Factory);
  167. }
  168. if (Translators.Length != 1)
  169. {
  170. Log.Warn("manipulation query [{0}] resulted in [{1}] split queries", _sourceQuery, Translators.Length);
  171. }
  172. int result = 0;
  173. for (int i = 0; i < Translators.Length; i++)
  174. {
  175. result += Translators[i].ExecuteUpdate(queryParameters, session);
  176. }
  177. return result;
  178. }
  179. void FinaliseQueryPlan()
  180. {
  181. BuildSqlStringsAndQuerySpaces();
  182. BuildMetaData();
  183. }
  184. void BuildMetaData()
  185. {
  186. if (Translators.Length == 0)
  187. {
  188. ParameterMetadata = new ParameterMetadata(null, null);
  189. ReturnMetadata = null;
  190. }
  191. else
  192. {
  193. ParameterMetadata = Translators[0].BuildParameterMetadata();
  194. if (Translators[0].IsManipulationStatement)
  195. {
  196. ReturnMetadata = null;
  197. }
  198. else
  199. {
  200. if (Translators.Length > 1)
  201. {
  202. int returns = Translators[0].ReturnTypes.Length;
  203. ReturnMetadata = new ReturnMetadata(Translators[0].ReturnAliases, new IType[returns]);
  204. }
  205. else
  206. {
  207. ReturnMetadata = new ReturnMetadata(Translators[0].ReturnAliases, Translators[0].ReturnTypes);
  208. }
  209. }
  210. }
  211. }
  212. void BuildSqlStringsAndQuerySpaces()
  213. {
  214. var combinedQuerySpaces = new HashSet<string>();
  215. var sqlStringList = new List<string>();
  216. foreach (var translator in Translators)
  217. {
  218. foreach (var qs in translator.QuerySpaces)
  219. {
  220. combinedQuerySpaces.Add(qs);
  221. }
  222. sqlStringList.AddRange(translator.CollectSqlStrings);
  223. }
  224. SqlStrings = sqlStringList.ToArray();
  225. QuerySpaces = combinedQuerySpaces;
  226. }
  227. }
  228. }