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; } }