⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 queryplancache.cs

📁 NHibernate NET开发者所需的
💻 CS
字号:
using System;
using System.Collections.Generic;
using Iesi.Collections.Generic;
using log4net;
using NHibernate.Engine.Query.Sql;
using NHibernate.Util;

namespace NHibernate.Engine.Query
{
	/// <summary> Acts as a cache for compiled query plans, as well as query-parameter metadata. </summary>
	[Serializable]
	public class QueryPlanCache
	{
		private static readonly ILog log = LogManager.GetLogger(typeof(QueryPlanCache));

		private readonly ISessionFactoryImplementor factory;

		// simple cache of param metadata based on query string.  Ideally, the
		// original "user-supplied query" string should be used to retrieve this
		// metadata (i.e., not the para-list-expanded query string) to avoid
		// unnecessary cache entries.
		// Used solely for caching param metadata for native-sql queries, see
		// getSQLParameterMetadata() for a discussion as to why...
		private readonly SimpleMRUCache sqlParamMetadataCache = new SimpleMRUCache();

		// the cache of the actual plans...
		private readonly SoftLimitMRUCache planCache = new SoftLimitMRUCache(128);

		public QueryPlanCache(ISessionFactoryImplementor factory)
		{
			this.factory = factory;
		}

		public ParameterMetadata GetSQLParameterMetadata(string query)
		{
			ParameterMetadata metadata = (ParameterMetadata)sqlParamMetadataCache[query];
			if (metadata == null)
			{
				// for native-sql queries, the param metadata is determined outside
				// any relation to a query plan, because query plan creation and/or
				// retrieval for a native-sql query depends on all of the return
				// types having been set, which might not be the case up-front when
				// param metadata would be most useful
				metadata = BuildNativeSQLParameterMetadata(query);
				sqlParamMetadataCache.Put(query, metadata);
			}
			return metadata;
		}

		public HQLQueryPlan GetHQLQueryPlan(string queryString, bool shallow, IDictionary<string, IFilter> enabledFilters)
		{
			HQLQueryPlanKey key = new HQLQueryPlanKey(queryString, shallow, enabledFilters);
			HQLQueryPlan plan = (HQLQueryPlan)planCache[key];

			if (plan == null)
			{
				if (log.IsDebugEnabled)
				{
					log.Debug("unable to locate HQL query plan in cache; generating (" + queryString + ")");
				}
				plan = new HQLQueryPlan(queryString, shallow, enabledFilters, factory);
			}
			else
			{
				if (log.IsDebugEnabled)
				{
					log.Debug("located HQL query plan in cache (" + queryString + ")");
				}
			}

			planCache.Put(key, plan);

			return plan;
		}

		public FilterQueryPlan GetFilterQueryPlan(string filterString, string collectionRole, bool shallow, IDictionary<string, IFilter> enabledFilters)
		{
			FilterQueryPlanKey key = new FilterQueryPlanKey(filterString, collectionRole, shallow, enabledFilters);
			FilterQueryPlan plan = (FilterQueryPlan)planCache[key];

			if (plan == null)
			{
				if (log.IsDebugEnabled)
				{
					log.Debug("unable to locate collection-filter query plan in cache; generating (" + collectionRole + " : " + filterString + ")");
				}
				plan = new FilterQueryPlan(filterString, collectionRole, shallow, enabledFilters, factory);
			}
			else
			{
				if (log.IsDebugEnabled)
				{
					log.Debug("located collection-filter query plan in cache (" + collectionRole + " : " + filterString + ")");
				}
			}

			planCache.Put(key, plan);

			return plan;
		}

		public NativeSQLQueryPlan GetNativeSQLQueryPlan(NativeSQLQuerySpecification spec)
		{
			NativeSQLQueryPlan plan = (NativeSQLQueryPlan)planCache[spec];

			if (plan == null)
			{
				if (log.IsDebugEnabled)
				{
					log.Debug("unable to locate native-sql query plan in cache; generating (" + spec.QueryString + ")");
				}
				plan = new NativeSQLQueryPlan(spec, factory);
			}
			else
			{
				if (log.IsDebugEnabled)
				{
					log.Debug("located native-sql query plan in cache (" + spec.QueryString + ")");
				}
			}

			planCache.Put(spec, plan);
			return plan;
		}

		private ParameterMetadata BuildNativeSQLParameterMetadata(string sqlString)
		{
			ParamLocationRecognizer recognizer = ParamLocationRecognizer.parseLocations(sqlString);

			OrdinalParameterDescriptor[] ordinalDescriptors = new OrdinalParameterDescriptor[recognizer.OrdinalParameterLocationList.Count];
			for (int i = 0; i < recognizer.OrdinalParameterLocationList.Count; i++)
			{
				int position = recognizer.OrdinalParameterLocationList[i];
				ordinalDescriptors[i] = new OrdinalParameterDescriptor(i, null, position);
			}

			IDictionary<string, NamedParameterDescriptor> namedParamDescriptorMap = new Dictionary<string, NamedParameterDescriptor>();

			foreach (KeyValuePair<string, ParamLocationRecognizer.NamedParameterDescription> entry in recognizer.NamedParameterDescriptionMap)
			{
				string name = entry.Key;
				ParamLocationRecognizer.NamedParameterDescription description = entry.Value;
				namedParamDescriptorMap[name] =
					new NamedParameterDescriptor(name, null, description.BuildPositionsArray(), description.JpaStyle);				
			}

			return new ParameterMetadata(ordinalDescriptors, namedParamDescriptorMap);
		}

		[Serializable]
		private class HQLQueryPlanKey
		{
			private readonly string query;
			private readonly bool shallow;
			private readonly ISet<string> filterNames;
			private readonly int hashCode;

			public HQLQueryPlanKey(string query, bool shallow, IDictionary<string, IFilter> enabledFilters)
			{
				this.query = query;
				this.shallow = shallow;

				if (enabledFilters == null || (enabledFilters.Count == 0))
				{
					filterNames = new HashedSet<string>();
				}
				else
				{
					filterNames = new HashedSet<string>(enabledFilters.Keys);
				}

				int hash = query.GetHashCode();
				hash = 29 * hash + (shallow ? 1 : 0);
				hash = 29 * hash + CollectionHelper.GetHashCode(filterNames);
				hashCode = hash;
			}

			public override bool Equals(object obj)
			{
				if (this == obj)
				{
					return true;
				}

				HQLQueryPlanKey that = obj as HQLQueryPlanKey;
				if (that == null)
				{
					return false;
				}

				if (shallow != that.shallow)
				{
					return false;
				}

				if (!CollectionHelper.SetEquals(filterNames, that.filterNames))
				{
					return false;
				}

				if (!query.Equals(that.query))
				{
					return false;
				}

				return true;
			}

			public override int GetHashCode()
			{
				return hashCode;
			}
		}

		[Serializable]
		private class FilterQueryPlanKey
		{
			private readonly string query;
			private readonly string collectionRole;
			private readonly bool shallow;
			private readonly ISet<string> filterNames;
			private readonly int hashCode;

			public FilterQueryPlanKey(string query, string collectionRole, bool shallow, IDictionary<string, IFilter> enabledFilters)
			{
				this.query = query;
				this.collectionRole = collectionRole;
				this.shallow = shallow;

				if (enabledFilters == null || (enabledFilters.Count == 0))
				{
					filterNames = new HashedSet<string>();
				}
				else
				{
					filterNames = new HashedSet<string>(enabledFilters.Keys);
				}

				int hash = query.GetHashCode();
				hash = 29 * hash + collectionRole.GetHashCode();
				hash = 29 * hash + (shallow ? 1 : 0);
				hash = 29 * hash + CollectionHelper.GetHashCode(filterNames);
				hashCode = hash;
			}

			public override bool Equals(object obj)
			{
				if (this == obj)
				{
					return true;
				}
				if (obj == null || GetType() != obj.GetType())
				{
					return false;
				}

				FilterQueryPlanKey that = (FilterQueryPlanKey)obj;

				if (shallow != that.shallow)
				{
					return false;
				}
				if (!CollectionHelper.SetEquals(filterNames, that.filterNames))
				{
					return false;
				}
				if (!query.Equals(that.query))
				{
					return false;
				}
				if (!collectionRole.Equals(that.collectionRole))
				{
					return false;
				}

				return true;
			}

			public override int GetHashCode()
			{
				return hashCode;
			}
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -