📄 whereparser.cs
字号:
public void End(QueryTranslator q)
{
if (expectingPathContinuation)
{
expectingPathContinuation = false;
PathExpressionParser.CollectionElement element = pathExpressionParser.LastCollectionElement();
if (element.ElementColumns.Length != 1)
{
throw new QueryException("path expression ended in composite collection element");
}
AppendToken(q, element.ElementColumns[0]);
AddToCurrentJoin(element);
}
Token(StringHelper.ClosedParen, q);
}
private void CloseExpression(QueryTranslator q, string lcToken)
{
bool lastBoolTest = booleanTests[booleanTests.Count - 1];
booleanTests.RemoveAt(booleanTests.Count - 1);
if (lastBoolTest)
{
//it was a boolean expression
if (booleanTests.Count > 0)
{
// the next one up must also be
booleanTests[booleanTests.Count - 1] = true;
}
// Add any joins
SqlStringBuilder lastJoin = joins[joins.Count - 1];
joins.RemoveAt(joins.Count - 1);
AppendToken(q, lastJoin.ToSqlString());
}
else
{
//unaryCounts.removeLast(); //check that its zero? (As an assertion)
SqlStringBuilder join = joins[joins.Count - 1];
joins.RemoveAt(joins.Count - 1);
joins[joins.Count - 1].Add(join.ToSqlString());
}
bool lastNots = nots[nots.Count - 1];
nots.RemoveAt(nots.Count - 1);
if (lastNots)
{
negated = !negated;
}
if (!StringHelper.ClosedParen.Equals(lcToken))
{
AppendToken(q, StringHelper.ClosedParen);
}
}
private void OpenExpression(QueryTranslator q, string lcToken)
{
nots.Add(false);
booleanTests.Add(false);
joins.Add(new SqlStringBuilder());
if (!StringHelper.OpenParen.Equals(lcToken))
{
AppendToken(q, StringHelper.OpenParen);
}
}
private void Preprocess(string token, QueryTranslator q)
{
// ugly hack for cases like "foo.bar.collection.elements"
// (multi-part path expression ending in elements or indices)
string[] tokens = StringHelper.Split(".", token, true);
if (tokens.Length > 5 &&
("elements".Equals(tokens[tokens.Length - 1]) || "indices".Equals(tokens[tokens.Length - 1])))
{
pathExpressionParser.Start(q);
for (int i = 0; i < tokens.Length - 3; i++)
{
pathExpressionParser.Token(tokens[i], q);
}
pathExpressionParser.Token(null, q);
pathExpressionParser.End(q);
AddJoin(pathExpressionParser.WhereJoin, q);
pathExpressionParser.IgnoreInitialJoin();
}
}
private void DoPathExpression(string token, QueryTranslator q)
{
Preprocess(token, q);
StringTokenizer tokens = new StringTokenizer(token, ".", true);
pathExpressionParser.Start(q);
foreach (string tok in tokens)
{
pathExpressionParser.Token(tok, q);
}
pathExpressionParser.End(q);
if (pathExpressionParser.IsCollectionValued)
{
OpenExpression(q, string.Empty);
AppendToken(q, pathExpressionParser.GetCollectionSubquery(q.EnabledFilters));
CloseExpression(q, string.Empty);
// this is ugly here, but needed because its a subquery
q.AddQuerySpaces(q.GetCollectionPersister(pathExpressionParser.CollectionRole).CollectionSpaces);
}
else
{
if (pathExpressionParser.IsExpectingCollectionIndex)
{
expectingIndex++;
}
else
{
AddJoin(pathExpressionParser.WhereJoin, q);
AppendToken(q, pathExpressionParser.WhereColumn);
}
}
}
private void AddJoin(JoinSequence joinSequence, QueryTranslator q)
{
q.AddFromJoinOnly(pathExpressionParser.Name, joinSequence);
try
{
AddToCurrentJoin(joinSequence.ToJoinFragment(q.EnabledFilters, true).ToWhereFragmentString);
}
catch (MappingException me)
{
throw new QueryException(me);
}
}
private void DoToken(string token, QueryTranslator q)
{
if (q.IsName(StringHelper.Root(token))) //path expression
{
DoPathExpression(q.Unalias(token), q);
}
else if (token.StartsWith(ParserHelper.HqlVariablePrefix)) //named query parameter
{
q.AddNamedParameter(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);
}
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);
}
else
{
IQueryable persister = q.GetPersisterUsingImports(token);
if (persister != null) // the name of a class
{
string discrim = persister.DiscriminatorSQLValue;
if (InFragment.Null == discrim || InFragment.NotNull == discrim)
{
throw new QueryException("subclass test not allowed for null or not null discriminator");
}
AppendToken(q, discrim);
}
else
{
object constant;
string fieldName = null;
System.Type importedType = null;
int indexOfDot = token.IndexOf(StringHelper.Dot);
// don't even bother to do the lookups if the indexOfDot is not
// greater than -1. This will save all the string modifications.
// This allows us to resolve to the full type before obtaining the value e.g. FooStatus.OFF -> NHibernate.Model.FooStatus.OFF
if (indexOfDot > -1)
{
fieldName = StringHelper.Unqualify(token);
string typeName = StringHelper.Qualifier(token);
importedType = SessionFactoryHelper.GetImportedClass(q.Factory, typeName);
}
if (indexOfDot > -1 && importedType != null &&
(constant = ReflectHelper.GetConstantValue(importedType, fieldName)) != null)
{
// need to get the NHibernate Type so we can convert the Enum or field from
// a class into it's string representation for hql.
IType type;
try
{
type = TypeFactory.HeuristicType(constant.GetType().AssemblyQualifiedName);
}
catch (MappingException me)
{
throw new QueryException(me);
}
if (type == null)
{
throw new QueryException(string.Format("Could not determin the type of: {0}", token));
}
try
{
AppendToken(q, ((ILiteralType)type).ObjectToSQLString(constant, q.Factory.Dialect));
}
catch (Exception e)
{
throw new QueryException("Could not format constant value to SQL literal: " + token, e);
}
}
else
{
//anything else
string negatedToken = null;
if (negated)
negations.TryGetValue(token.ToLowerInvariant(), out negatedToken);
if (negatedToken != null && (!betweenSpecialCase || !"or".Equals(negatedToken)))
{
AppendToken(q, negatedToken);
}
else
{
AppendToken(q, token);
}
}
}
}
}
private void AddToCurrentJoin(SqlString sql)
{
joins[joins.Count - 1].Add(sql);
}
private void AddToCurrentJoin(PathExpressionParser.CollectionElement ce)
{
try
{
AddToCurrentJoin(ce.JoinSequence.ToJoinFragment().ToWhereFragmentString + ce.IndexValue.ToSqlString());
}
catch (MappingException me)
{
throw new QueryException(me);
}
}
private void SpecialCasesBefore(string lcToken)
{
if ("between".Equals(lcToken) || "not between".Equals(lcToken))
{
betweenSpecialCase = true;
}
}
private void SpecialCasesAfter(string lcToken)
{
if (betweenSpecialCase && "and".Equals(lcToken))
{
betweenSpecialCase = false;
}
}
protected virtual void AppendToken(QueryTranslator q, string token)
{
if (expectingIndex > 0)
{
pathExpressionParser.SetLastCollectionElementIndexValue(new SqlString(token));
}
else
{
// a String.Empty can get passed in here. If that occurs
// then don't create a new SqlString for it - just ignore
// it since it adds nothing to the sql being generated.
if (token != null && token.Length > 0)
{
q.AppendWhereToken(new SqlString(token));
}
}
}
protected virtual void AppendToken(QueryTranslator q, SqlString token)
{
if (expectingIndex > 0)
{
pathExpressionParser.SetLastCollectionElementIndexValue(token);
}
else
{
q.AppendWhereToken(token);
}
}
private bool ContinuePathExpression(string token, QueryTranslator q)
{
expectingPathContinuation = false;
PathExpressionParser.CollectionElement element = pathExpressionParser.LastCollectionElement();
if (token.StartsWith("."))
{
// the path expression continues after a ]
DoPathExpression(GetElementName(element, q) + token, q); // careful with this!
AddToCurrentJoin(element);
return true; //NOTE: EARLY EXIT!
}
else
{
// the path expression ends at the ]
if (element.ElementColumns.Length != 1)
{
throw new QueryException("path expression ended in composite collection element");
}
AppendToken(q, element.ElementColumns[0]);
AddToCurrentJoin(element);
return false;
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -