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

📄 nativesqlqueryplan.cs

📁 NHibernate NET开发者所需的
💻 CS
字号:
using System;
using System.Collections;
using System.Data;
using log4net;
using NHibernate.Action;
using NHibernate.Engine.Query.Sql;
using NHibernate.Event;
using NHibernate.Exceptions;
using NHibernate.Loader.Custom.Sql;
using NHibernate.SqlCommand;
using NHibernate.SqlTypes;
using NHibernate.Type;
using NHibernate.Util;

namespace NHibernate.Engine.Query
{
	/// <summary> Defines a query execution plan for a native-SQL query. </summary>
	[Serializable]
	public class NativeSQLQueryPlan
	{
		private static readonly ILog log = LogManager.GetLogger(typeof(NativeSQLQueryPlan));

		private readonly string sourceQuery;
		private readonly SQLCustomQuery customQuery;

		public NativeSQLQueryPlan(NativeSQLQuerySpecification specification, ISessionFactoryImplementor factory)
		{
			sourceQuery = specification.QueryString;
			customQuery = new SQLCustomQuery(specification.SqlQueryReturns, specification.QueryString, specification.QuerySpaces, factory);
		}

		public string SourceQuery
		{
			get { return sourceQuery; }
		}

		public SQLCustomQuery CustomQuery
		{
			get { return customQuery; }
		}

		private int[] GetNamedParameterLocs(string name)
		{
			object loc = customQuery.NamedParameterBindPoints[name];
			if (loc == null)
			{
				throw new QueryException("Named parameter does not appear in Query: " + name, customQuery.SQL.ToString());
			}
			if (Convert.GetTypeCode(loc) == TypeCode.Int32)
			{
				return new int[] {Convert.ToInt32(loc)};
			}
			else
			{
				return ArrayHelper.ToIntArray((IList)loc);
			}
		}

		/// <summary> 
		/// Bind positional parameter values to the <tt>PreparedStatement</tt>
		/// (these are parameters specified by a JDBC-style ?).
		/// </summary>
		private int BindPositionalParameters(IDbCommand st, QueryParameters queryParameters, int start, ISessionImplementor session)
		{
			object[] values = queryParameters.FilteredPositionalParameterValues;
			IType[] types = queryParameters.FilteredPositionalParameterTypes;
			int span = 0;
			for (int i = 0; i < values.Length; i++)
			{
				types[i].NullSafeSet(st, values[i], start + span, session);
				span += types[i].GetColumnSpan(session.Factory);
			}
			return span;
		}

		/// <summary> 
		/// Bind named parameters to the <tt>PreparedStatement</tt>. This has an
		/// empty implementation on this superclass and should be implemented by
		/// subclasses (queries) which allow named parameters.
		/// </summary>
		private void BindNamedParameters(IDbCommand ps, IDictionary namedParams, int start, ISessionImplementor session)
		{
			if (namedParams != null)
			{
				// assumes that types are all of span 1
				int result = 0;
				foreach (DictionaryEntry param in namedParams)
				{
					string name = (string)param.Key;
					TypedValue typedval = (TypedValue)param.Value;

					int[] locs = GetNamedParameterLocs(name);
					for (int i = 0; i < locs.Length; i++)
					{
						if (log.IsDebugEnabled)
						{
							log.Debug(string.Format("BindNamedParameters() {0} -> {1} [{2}]", typedval.Value, name, (locs[i] + start)));
						}
						typedval.Type.NullSafeSet(ps, typedval.Value, locs[i] + start, session);
					}
					result += locs.Length;
				}
				return;
			}
			else
			{
				return;
			}
		}

		private void CoordinateSharedCacheCleanup(ISessionImplementor session)
		{
			BulkOperationCleanupAction action = new BulkOperationCleanupAction(session, CustomQuery.QuerySpaces);

			action.Init();

			if (session.IsEventSource)
			{
				((IEventSource)session).ActionQueue.AddAction(action);
			}
		}

		// DONE : H3.2 Executable query (now can be supported for named SQL query/ storedProcedure)
		public int PerformExecuteUpdate(QueryParameters queryParameters, ISessionImplementor session)
		{
			CoordinateSharedCacheCleanup(session);

			if (queryParameters.Callable)
			{
				throw new ArgumentException("callable not yet supported for native queries");
			}

			RowSelection selection = queryParameters.RowSelection;

			int result;
			try
			{
				queryParameters.ProcessFilters(customQuery.SQL, session);
				SqlString sql = queryParameters.FilteredSQL;
				SqlType[] sqlTypes = GetParameterTypes(queryParameters, session);
				
				IDbCommand ps = session.Batcher.PrepareCommand(CommandType.Text, sql, sqlTypes);

				try
				{
					if (selection != null && selection.Timeout != RowSelection.NoValue)
					{
						// NH Difference : set Timeout for native query
						ps.CommandTimeout = selection.Timeout;
					}
					int col = 0; // NH Different (initialized to 1 in JAVA)
					col += BindPositionalParameters(ps, queryParameters, col, session);
					BindNamedParameters(ps, queryParameters.NamedParameters, col, session);
					result = session.Batcher.ExecuteNonQuery(ps);
				}
				finally
				{
					if (ps != null)
					{
						session.Batcher.CloseCommand(ps, null);
					}
				}
			}
			catch (HibernateException)
			{
				throw;
			}
			catch (Exception sqle)
			{
				throw ADOExceptionHelper.Convert(session.Factory.SQLExceptionConverter, sqle,
				                                 "could not execute native bulk manipulation query:" + sourceQuery);
			}

			return result;
		}

		private SqlType[] GetParameterTypes(QueryParameters parameters, ISessionImplementor session)
		{
			ArrayList paramTypeList = new ArrayList();
			int span = 0;

			foreach (IType type in parameters.FilteredPositionalParameterTypes)
			{
				paramTypeList.Add(type);
				span += type.GetColumnSpan(session.Factory);
			}

			if (parameters.NamedParameters != null && parameters.NamedParameters.Count > 0)
			{
				int offset = paramTypeList.Count;

				// convert the named parameters to an array of types
				foreach (DictionaryEntry e in parameters.NamedParameters)
				{
					string name = (string)e.Key;
					TypedValue typedval = (TypedValue)e.Value;
					int[] locs = GetNamedParameterLocs(name);
					span += typedval.Type.GetColumnSpan(session.Factory) * locs.Length;

					for (int i = 0; i < locs.Length; i++)
					{
						ArrayHelper.SafeSetValue(paramTypeList, locs[i] + offset, typedval.Type);
					}
				}
			}
			return ConvertITypesToSqlTypes(paramTypeList, span, session);
		}

		private SqlType[] ConvertITypesToSqlTypes(ArrayList nhTypes, int totalSpan, ISessionImplementor session)
		{
			SqlType[] result = new SqlType[totalSpan];

			int index = 0;
			foreach (IType type in nhTypes)
			{
				int span = type.SqlTypes(session.Factory).Length;
				Array.Copy(type.SqlTypes(session.Factory), 0, result, index, span);
				index += span;
			}

			return result;
		}
	}
}

⌨️ 快捷键说明

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