public void Token(string token, QueryTranslator q) { SessionFactoryHelper helper = new SessionFactoryHelper(q.Factory); string lctoken = token.ToLowerInvariant(); if (first) { first = false; if ("distinct".Equals(lctoken)) { q.Distinct = true; return; } else if ("all".Equals(lctoken)) { q.Distinct = false; return; } } if (afterNew) { afterNew = false; holderClass = helper.GetImportedClass(token); if (holderClass == null) { throw new QueryException("class not found: " + token); } q.HolderClass = holderClass; insideNew = true; } else if (token.Equals(StringHelper.Comma)) { if (readyForAliasOrExpression) { throw new QueryException("alias or expression expected in SELECT"); } q.AppendScalarSelectToken(StringHelper.CommaSpace); readyForAliasOrExpression = true; } else if ("new".Equals(lctoken)) { afterNew = true; readyForAliasOrExpression = false; } else if (StringHelper.OpenParen.Equals(token)) { parenCount++; if (!funcStack.HasFunctions && holderClass != null && !readyForAliasOrExpression) { //opening paren in new Foo ( ... ) readyForAliasOrExpression = true; } else if (funcStack.HasFunctions) { q.AppendScalarSelectToken(token); } else { throw new QueryException("HQL function expected before '(' in SELECT clause."); } readyForAliasOrExpression = true; } else if (StringHelper.ClosedParen.Equals(token)) { parenCount--; if (parenCount < 0) { throw new QueryException("'(' expected before ')' in SELECT clause."); } if (insideNew && !funcStack.HasFunctions && !readyForAliasOrExpression) { //if we are inside a new Result(), but not inside a nested function insideNew = false; } else if (funcStack.HasFunctions) { q.AppendScalarSelectToken(token); IType scalarType = funcStack.GetReturnType(); funcStack.Pop(); // Can't have an alias or expression right after the closing parenthesis of a function call. readyForAliasOrExpression = false; // if all functions were parsed add the type of the first function in stack if (!funcStack.HasFunctions) { q.AddSelectScalar(scalarType); } } } else if (IsHQLFunction(lctoken, q) && token == q.Unalias(token)) { if (!readyForAliasOrExpression && !funcStack.HasFunctions) { // The syntax control inside a functions is delegated to the render throw new QueryException("',' expected before function in SELECT: " + token); } if (funcStack.HasFunctions && funcStack.FunctionGrammar.IsKnownArgument(lctoken)) { // Some function, like extract, may have KnownArgument with the same name of another function q.AppendScalarSelectToken(token); } else { // Is a nested function funcStack.Push(GetFunction(lctoken, q)); q.AppendScalarSelectToken(token); if (!funcStack.SqlFunction.HasArguments && !funcStack.SqlFunction.HasParenthesesIfNoArguments) { q.AddSelectScalar(funcStack.GetReturnType()); funcStack.Pop(); readyForAliasOrExpression = funcStack.HasFunctions; } } } else if (funcStack.HasFunctions) { bool constantToken = false; var expectedParen = parenCount + ((insideNew) ? -1 : 0); if (!readyForAliasOrExpression && expectedParen != funcStack.NestedFunctionCount) { throw new QueryException("'(' expected after HQL function in SELECT"); } try { ParserHelper.Parse(funcStack.PathExpressionParser, q.Unalias(token), ParserHelper.PathSeparators, q); } catch (QueryException) { if (IsPathExpression(token)) { throw; } // If isn't a path the token is added like part of function arguments constantToken = true; } if (token.StartsWith(ParserHelper.HqlVariablePrefix)) { string name = token.Substring(1); q.AppendScalarSelectParameter(name); } else if (token.Equals(StringHelper.SqlParameter)) { q.AppendScalarSelectParameter(); } else if (constantToken) { q.AppendScalarSelectToken(token); } else { if (funcStack.PathExpressionParser.IsCollectionValued) { q.AddCollection( funcStack.PathExpressionParser.CollectionName, funcStack.PathExpressionParser.CollectionRole); } q.AppendScalarSelectToken(funcStack.PathExpressionParser.WhereColumn); funcStack.PathExpressionParser.AddAssociation(q); } // after a function argument readyForAliasOrExpression = false; } else { if (!readyForAliasOrExpression) { throw new QueryException("',' expected in SELECT before:" + token); } try { //High probablly to find a valid pathExpression ParserHelper.Parse(pathExpressionParser, q.Unalias(token), ParserHelper.PathSeparators, q); if (pathExpressionParser.IsCollectionValued) { q.AddCollection( pathExpressionParser.CollectionName, pathExpressionParser.CollectionRole); } else if (pathExpressionParser.WhereColumnType.IsEntityType) { q.AddSelectClass(pathExpressionParser.SelectName); } q.AppendScalarSelectTokens(pathExpressionParser.WhereColumns); q.AddSelectScalar(pathExpressionParser.WhereColumnType); pathExpressionParser.AddAssociation(q); } catch (QueryException) { // Accept costants in SELECT: NH-280 // TODO: Parse a costant expression like 5+3+8 (now is not supported in SELECT) if (IsStringCostant(token)) { q.AppendScalarSelectToken(token); q.AddSelectScalar(NHibernateUtil.String); } else if (IsIntegerConstant(token)) { q.AppendScalarSelectToken(token); q.AddSelectScalar(GetIntegerConstantType(token)); } else if (IsFloatingPointConstant(token)) { q.AppendScalarSelectToken(token); q.AddSelectScalar(GetFloatingPointConstantType()); } else if (token.StartsWith(ParserHelper.HqlVariablePrefix)) { string name = token.Substring(1); q.AppendScalarSelectParameter(name); } else if (token.Equals(StringHelper.SqlParameter)) { q.AppendScalarSelectParameter(); } else { throw; } } readyForAliasOrExpression = false; } }
/// <summary> /// /// </summary> /// <param name="token"></param> /// <param name="q"></param> public void Token(string token, QueryTranslator q) { string lctoken = token.ToLower(System.Globalization.CultureInfo.InvariantCulture); if (first) { first = false; if (lctoken.Equals("distinct")) { q.Distinct = true; return; } else if (lctoken.Equals("all")) { q.Distinct = false; return; } } if (afterNew) { afterNew = false; holderClass = q.GetImportedClass(token); if (holderClass == null) { throw new QueryException("class not found: " + token); } q.HolderClass = holderClass; insideNew = true; } else if (token.Equals(StringHelper.Comma)) { if (ready) { throw new QueryException("alias or expression expected in SELECT"); } q.AppendScalarSelectToken(StringHelper.CommaSpace); ready = true; } else if ("new".Equals(lctoken)) { afterNew = true; ready = false; } else if (StringHelper.OpenParen.Equals(token)) { if (!aggregate && holderClass != null && !ready) { //opening paren in new Foo ( ... ) ready = true; } else if (aggregate) { q.AppendScalarSelectToken(token); } else { throw new QueryException("aggregate function expected before ( in SELECT"); } ready = true; } else if (StringHelper.ClosedParen.Equals(token)) { if (insideNew && !aggregate && !ready) { //if we are inside a new Result(), but not inside a nested function insideNew = false; } else if (aggregate && ready) { q.AppendScalarSelectToken(token); aggregateFuncTokenList.RemoveAt(0); if (aggregateFuncTokenList.Count < 1) { aggregate = false; ready = false; } } else { throw new QueryException("( expected before ) in select"); } } else if (countArguments.Contains(lctoken)) { if (!ready || !aggregate) { throw new QueryException(token + " only allowed inside aggregate function in SELECT"); } q.AppendScalarSelectToken(token); if ("*".Equals(token)) { q.AddSelectScalar(NHibernateUtil.Int32); } //special case } else if (GetFunction(lctoken, q) != null && token == q.Unalias(token)) { // the name of an SQL function if (!ready) { throw new QueryException(", expected before aggregate function in SELECT: " + token); } aggregate = true; aggregateAddSelectScalar = true; aggregateFuncTokenList.Insert(0, lctoken); ready = false; q.AppendScalarSelectToken(token); if (!AggregateHasArgs(lctoken, q)) { q.AddSelectScalar(AggregateType(aggregateFuncTokenList, null, q)); if (!AggregateFuncNoArgsHasParenthesis(lctoken, q)) { aggregateFuncTokenList.RemoveAt(0); if (aggregateFuncTokenList.Count < 1) { aggregate = false; ready = false; } else { ready = true; } } } } else if (aggregate) { bool constantToken = false; if (!ready) { throw new QueryException("( expected after aggregate function in SELECT"); } try { ParserHelper.Parse(aggregatePathExpressionParser, q.Unalias(token), ParserHelper.PathSeparators, q); } catch (QueryException) { constantToken = true; } if (constantToken) { q.AppendScalarSelectToken(token); } else { if (aggregatePathExpressionParser.IsCollectionValued) { q.AddCollection( aggregatePathExpressionParser.CollectionName, aggregatePathExpressionParser.CollectionRole); } q.AppendScalarSelectToken(aggregatePathExpressionParser.WhereColumn); if (aggregateAddSelectScalar) { q.AddSelectScalar(AggregateType(aggregateFuncTokenList, aggregatePathExpressionParser.WhereColumnType, q)); aggregateAddSelectScalar = false; } aggregatePathExpressionParser.AddAssociation(q); } } else { if (!ready) { throw new QueryException(", expected in SELECT"); } ParserHelper.Parse(pathExpressionParser, q.Unalias(token), ParserHelper.PathSeparators, q); if (pathExpressionParser.IsCollectionValued) { q.AddCollection( pathExpressionParser.CollectionName, pathExpressionParser.CollectionRole); } else if (pathExpressionParser.WhereColumnType.IsEntityType) { q.AddSelectClass(pathExpressionParser.SelectName); } q.AppendScalarSelectTokens(pathExpressionParser.WhereColumns); q.AddSelectScalar(pathExpressionParser.WhereColumnType); pathExpressionParser.AddAssociation(q); ready = false; } }