|
From: <fab...@us...> - 2011-06-14 14:00:54
|
Revision: 5925
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5925&view=rev
Author: fabiomaulo
Date: 2011-06-14 14:00:44 +0000 (Tue, 14 Jun 2011)
Log Message:
-----------
Classic QueryTranslator using parameter specifications
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Hql/Classic/GroupByParser.cs
trunk/nhibernate/src/NHibernate/Hql/Classic/OrderByParser.cs
trunk/nhibernate/src/NHibernate/Hql/Classic/QueryTranslator.cs
trunk/nhibernate/src/NHibernate/Hql/Classic/SelectParser.cs
trunk/nhibernate/src/NHibernate/Hql/Classic/WhereParser.cs
trunk/nhibernate/src/NHibernate/SqlCommand/SqlString.cs
Modified: trunk/nhibernate/src/NHibernate/Hql/Classic/GroupByParser.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Hql/Classic/GroupByParser.cs 2011-06-13 16:01:13 UTC (rev 5924)
+++ trunk/nhibernate/src/NHibernate/Hql/Classic/GroupByParser.cs 2011-06-14 14:00:44 UTC (rev 5925)
@@ -27,9 +27,13 @@
q.AppendGroupByToken(pathExpressionParser.WhereColumn);
pathExpressionParser.AddAssociation(q);
}
- else if (token.StartsWith(ParserHelper.HqlVariablePrefix))
+ else if (token.StartsWith(ParserHelper.HqlVariablePrefix)) //named query parameter
{
- q.AddNamedParameter(token.Substring(1));
+ var name = token.Substring(1);
+ q.AppendGroupByParameter(name);
+ }
+ else if (token.Equals(StringHelper.SqlParameter))
+ {
q.AppendGroupByParameter();
}
else
Modified: trunk/nhibernate/src/NHibernate/Hql/Classic/OrderByParser.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Hql/Classic/OrderByParser.cs 2011-06-13 16:01:13 UTC (rev 5924)
+++ trunk/nhibernate/src/NHibernate/Hql/Classic/OrderByParser.cs 2011-06-14 14:00:44 UTC (rev 5925)
@@ -27,7 +27,11 @@
}
else if (token.StartsWith(ParserHelper.HqlVariablePrefix))
{
- q.AddNamedParameter(token.Substring(1));
+ var name = token.Substring(1);
+ q.AppendOrderByParameter(name);
+ }
+ else if (StringHelper.SqlParameter.Equals(token))
+ {
q.AppendOrderByParameter();
}
else
Modified: trunk/nhibernate/src/NHibernate/Hql/Classic/QueryTranslator.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Hql/Classic/QueryTranslator.cs 2011-06-13 16:01:13 UTC (rev 5924)
+++ trunk/nhibernate/src/NHibernate/Hql/Classic/QueryTranslator.cs 2011-06-14 14:00:44 UTC (rev 5925)
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using System.Collections;
using System.Data;
using System.Diagnostics;
@@ -11,9 +12,9 @@
using NHibernate.Engine;
using NHibernate.Engine.Query;
using NHibernate.Event;
-using NHibernate.Hql.Util;
using NHibernate.Impl;
using NHibernate.Loader;
+using NHibernate.Param;
using NHibernate.Persister.Collection;
using NHibernate.Persister.Entity;
using NHibernate.SqlCommand;
@@ -21,8 +22,8 @@
using NHibernate.Type;
using NHibernate.Util;
using NHibernate.Dialect.Function;
-using System.Collections.Specialized;
using System.Collections.Generic;
+using IQueryable = NHibernate.Persister.Entity.IQueryable;
namespace NHibernate.Hql.Classic
{
@@ -79,6 +80,8 @@
private bool hasScalars;
private bool shallowQuery;
private QueryTranslator superQuery;
+ private IList<IParameterSpecification> collectedParameters = new List<IParameterSpecification>();
+ private int positionalParameterFound;
private class FetchedCollections
{
@@ -268,7 +271,108 @@
Compile();
}
+ private int GetPositionalParameterPosition()
+ {
+ return superQuery != null ? superQuery.GetPositionalParameterPosition() : positionalParameterFound++;
+ }
+
+ public SqlString GetNamedParameter(string name)
+ {
+ var parameterSpecification = new NamedParameterSpecification(1, 0, name);
+ var parameter = Parameter.Placeholder;
+ parameter.BackTrack = parameterSpecification.GetIdsForBackTrack(Factory).First();
+
+ AddNamedParameter(name);
+ collectedParameters.Add(parameterSpecification);
+ return new SqlString(parameter);
+ }
+
+ public SqlString GetPositionalParameter()
+ {
+ var parameterSpecification = new PositionalParameterSpecification(1, 0, GetPositionalParameterPosition());
+ var parameter = Parameter.Placeholder;
+ parameter.BackTrack = parameterSpecification.GetIdsForBackTrack(Factory).First();
+ collectedParameters.Add(parameterSpecification);
+ return new SqlString(parameter);
+ }
+
+ public IEnumerable<IParameterSpecification> CollectedParameterSpecifications
+ {
+ get { return ((superQuery != null) ? superQuery.CollectedParameterSpecifications:Enumerable.Empty<IParameterSpecification>()).Concat(collectedParameters); }
+ }
+
+ public override ISqlCommand CreateSqlCommand(QueryParameters queryParameters, ISessionImplementor session)
+ {
+ // A distinct-copy of parameter specifications collected during query construction
+ var parameterSpecs = new HashSet<IParameterSpecification>(CollectedParameterSpecifications);
+ SqlString sql = SqlString.Copy();
+
+ // dynamic-filter parameters: during the HQL->SQL parsing, filters can be added as SQL_TOKEN/string and the SqlGenerator will not find it
+ sql = ExpandDynamicFilterParameters(sql, parameterSpecs, session);
+ AdjustQueryParametersForSubSelectFetching(sql, parameterSpecs, session, queryParameters); // NOTE: see TODO below
+
+ sql = AddLimitsParametersIfNeeded(sql, parameterSpecs, queryParameters, session);
+ // TODO: for sub-select fetching we have to try to assign the QueryParameter.ProcessedSQL here (with limits) but only after use IParameterSpecification for any kind of queries
+
+ // The PreprocessSQL method can modify the SqlString but should never add parameters (or we have to override it)
+ sql = PreprocessSQL(sql, queryParameters, session.Factory.Dialect);
+
+ // After the last modification to the SqlString we can collect all parameters types.
+ parameterSpecs.ResetEffectiveExpectedType(queryParameters);
+
+ return new SqlCommandImpl(sql, parameterSpecs, queryParameters, session.Factory);
+ }
+
/// <summary>
+ /// Obtain an <c>IDbCommand</c> with all parameters pre-bound. Bind positional parameters,
+ /// named parameters, and limit parameters.
+ /// </summary>
+ /// <remarks>
+ /// Creates an IDbCommand object and populates it with the values necessary to execute it against the
+ /// database to Load an Entity.
+ /// </remarks>
+ /// <param name="queryParameters">The <see cref="QueryParameters"/> to use for the IDbCommand.</param>
+ /// <param name="scroll">TODO: find out where this is used...</param>
+ /// <param name="session">The SessionImpl this Command is being prepared in.</param>
+ /// <returns>A CommandWrapper wrapping an IDbCommand that is ready to be executed.</returns>
+ protected internal override IDbCommand PrepareQueryCommand(QueryParameters queryParameters, bool scroll, ISessionImplementor session)
+ {
+ var sqlCommand = (SqlCommandImpl)CreateSqlCommand(queryParameters, session);
+ var parameterSpecs = sqlCommand.Specifications;
+ var query = sqlCommand.Query;
+ var sqlQueryParametersList = sqlCommand.SqlQueryParametersList;
+
+ parameterSpecs.SetQueryParameterLocations(sqlQueryParametersList, session.Factory);
+
+ IDbCommand command = session.Batcher.PrepareQueryCommand(CommandType.Text, query, sqlCommand.ParameterTypes);
+
+ try
+ {
+ RowSelection selection = queryParameters.RowSelection;
+ if (selection != null && selection.Timeout != RowSelection.NoValue)
+ {
+ command.CommandTimeout = selection.Timeout;
+ }
+
+ sqlCommand.Bind(command, sqlQueryParametersList, 0, session);
+
+ session.Batcher.ExpandQueryParameters(command, query);
+ }
+ catch (HibernateException)
+ {
+ session.Batcher.CloseCommand(command, null);
+ throw;
+ }
+ catch (Exception sqle)
+ {
+ session.Batcher.CloseCommand(command, null);
+ ADOExceptionReporter.LogExceptions(sqle);
+ throw;
+ }
+ return command;
+ }
+
+ /// <summary>
/// Compile a "normal" query. This method may be called multiple
/// times. Subsequent invocations are no-ops.
/// </summary>
@@ -672,15 +776,17 @@
internal void AppendOrderByToken(string token)
{
- if (StringHelper.SqlParameter.Equals(token))
- orderByTokens.Add(SqlString.Parameter);
- else
- orderByTokens.Add(new SqlString(token));
+ orderByTokens.Add(new SqlString(token));
}
+ internal void AppendOrderByParameter(string name)
+ {
+ orderByTokens.Add(GetNamedParameter(name));
+ }
+
internal void AppendOrderByParameter()
{
- orderByTokens.Add(SqlString.Parameter);
+ orderByTokens.Add(GetPositionalParameter());
}
internal void AppendGroupByToken(string token)
@@ -688,9 +794,14 @@
groupByTokens.Add(new SqlString(token));
}
+ internal void AppendGroupByParameter(string name)
+ {
+ groupByTokens.Add(GetNamedParameter(name));
+ }
+
internal void AppendGroupByParameter()
{
- groupByTokens.Add(SqlString.Parameter);
+ groupByTokens.Add(GetPositionalParameter());
}
internal void AppendScalarSelectToken(string token)
@@ -703,9 +814,14 @@
scalarSelectTokens.Add(new SqlString(tokens));
}
+ internal void AppendScalarSelectParameter(string name)
+ {
+ scalarSelectTokens.Add(GetNamedParameter(name));
+ }
+
internal void AppendScalarSelectParameter()
{
- scalarSelectTokens.Add(SqlString.Parameter);
+ scalarSelectTokens.Add(GetPositionalParameter());
}
internal void AddJoin(string name, JoinSequence joinSequence)
@@ -1087,10 +1203,21 @@
int parenCount = 1;
for (; tokenIdx < tokens.Count && parenCount > 0; tokenIdx++)
{
- if (tokens[tokenIdx].StartsWithCaseInsensitive(ParserHelper.HqlVariablePrefix) || tokens[tokenIdx].ToString().Equals(StringHelper.SqlParameter))
+ if (tokens[tokenIdx].Parts.Count == 1 && (tokens[tokenIdx].Parts.First() is Parameter))
{
- functionTokens.Add(SqlString.Parameter);
+ // the parameter was processed
+ functionTokens.Add(tokens[tokenIdx]);
+ continue;
}
+ if (tokens[tokenIdx].StartsWithCaseInsensitive(ParserHelper.HqlVariablePrefix))
+ {
+ string name = tokens[tokenIdx].Substring(1).ToString();
+ functionTokens.Add(GetNamedParameter(name));
+ }
+ else if (StringHelper.SqlParameter.Equals(tokens[tokenIdx].ToString()))
+ {
+ functionTokens.Add(GetPositionalParameter());
+ }
else
{
functionTokens.Add(tokens[tokenIdx]);
Modified: trunk/nhibernate/src/NHibernate/Hql/Classic/SelectParser.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Hql/Classic/SelectParser.cs 2011-06-13 16:01:13 UTC (rev 5924)
+++ trunk/nhibernate/src/NHibernate/Hql/Classic/SelectParser.cs 2011-06-14 14:00:44 UTC (rev 5925)
@@ -170,7 +170,11 @@
if (token.StartsWith(ParserHelper.HqlVariablePrefix))
{
- q.AddNamedParameter(token.Substring(1));
+ string name = token.Substring(1);
+ q.AppendScalarSelectParameter(name);
+ }
+ else if (token.Equals(StringHelper.SqlParameter))
+ {
q.AppendScalarSelectParameter();
}
else if (constantToken)
@@ -237,7 +241,11 @@
}
else if (token.StartsWith(ParserHelper.HqlVariablePrefix))
{
- q.AddNamedParameter(token.Substring(1));
+ string name = token.Substring(1);
+ q.AppendScalarSelectParameter(name);
+ }
+ else if (token.Equals(StringHelper.SqlParameter))
+ {
q.AppendScalarSelectParameter();
}
else
Modified: trunk/nhibernate/src/NHibernate/Hql/Classic/WhereParser.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Hql/Classic/WhereParser.cs 2011-06-13 16:01:13 UTC (rev 5924)
+++ trunk/nhibernate/src/NHibernate/Hql/Classic/WhereParser.cs 2011-06-14 14:00:44 UTC (rev 5925)
@@ -470,17 +470,17 @@
}
else if (token.StartsWith(ParserHelper.HqlVariablePrefix)) //named query parameter
{
- q.AddNamedParameter(token.Substring(1));
+ var name = token.Substring(1);
// this is only a temporary parameter to help with the parsing of hql -
// when the type becomes known then this will be converted to its real
// parameter type.
- AppendToken(q, SqlString.Parameter);
+ AppendToken(q, q.GetNamedParameter(name));
}
else if (token.Equals(StringHelper.SqlParameter))
{
//if the token is a "?" then we have a Parameter so convert it to a SqlCommand.Parameter
// instead of appending a "?" to the WhereTokens
- AppendToken(q, SqlString.Parameter);
+ AppendToken(q, q.GetPositionalParameter());
}
else
{
Modified: trunk/nhibernate/src/NHibernate/SqlCommand/SqlString.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/SqlCommand/SqlString.cs 2011-06-13 16:01:13 UTC (rev 5924)
+++ trunk/nhibernate/src/NHibernate/SqlCommand/SqlString.cs 2011-06-14 14:00:44 UTC (rev 5925)
@@ -26,11 +26,6 @@
public static readonly SqlString Empty = new SqlString(new object[0]);
- public static SqlString Parameter
- {
- get { return new SqlString(SqlCommand.Parameter.Placeholder); }
- }
-
public SqlString(string sqlPart)
{
if (StringHelper.IsNotEmpty(sqlPart))
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|