private void PrepareForIndex(QueryTranslator q) { IQueryableCollection collPersister = q.GetCollectionPersister(collectionRole); if (!collPersister.HasIndex) { throw new QueryException("unindexed collection before []"); } string[] indexCols = collPersister.IndexColumnNames; if (indexCols.Length != 1) { throw new QueryException("composite-index appears in []: " + path); } string[] keyCols = collPersister.KeyColumnNames; JoinFragment ojf = q.CreateJoinFragment(useThetaStyleJoin); ojf.AddCrossJoin(collPersister.TableName, collectionName); ojf.AddFromFragmentString(join.ToFromFragmentString); if (collPersister.IsOneToMany) { IQueryable persister = (IQueryable)collPersister.ElementPersister; ojf.AddJoins( ((IJoinable)persister).FromJoinFragment(collectionName, true, false), ((IJoinable)persister).WhereJoinFragment(collectionName, true, false) ); } if (!continuation) { AddJoin(collPersister.TableName, collectionName, keyCols); } join.AddCondition(collectionName, indexCols, " = "); string[] eltCols = collPersister.ElementColumnNames; CollectionElement elem = new CollectionElement(); elem.ElementColumns = StringHelper.Qualify(collectionName, eltCols); elem.Type = collPersister.ElementType; elem.IsOneToMany = collPersister.IsOneToMany; elem.Alias = collectionName; elem.Join = join; collectionElements.Add(elem); //addlast SetExpectingCollectionIndex(); q.AddCollection(collectionName, collectionRole); q.AddJoin(collectionName, ojf); }
/// <summary> /// /// </summary> /// <param name="q"></param> /// <returns></returns> public string AddFromCollection(QueryTranslator q) { IType collectionElementType = PropertyType; if (collectionElementType == null) { throw new QueryException(string.Format("must specify 'elements' for collection valued property in from clause: {0}", path)); } if (collectionElementType.IsEntityType) { // an association IQueryableCollection collectionPersister = q.GetCollectionPersister(collectionRole); IQueryable entityPersister = (IQueryable)collectionPersister.ElementPersister; System.Type clazz = entityPersister.MappedClass; string[] collectionElementColumns = CurrentColumns(); string elementName; if (collectionPersister.IsOneToMany) { elementName = collectionName; // allow index() function q.DecoratePropertyMapping(elementName, collectionPersister); } else { // many to many q.AddCollection(collectionName, collectionRole); elementName = q.CreateNameFor(clazz); string[] keyColumnNames = entityPersister.IdentifierColumnNames; join.AddJoin(entityPersister.TableName, elementName, collectionElementColumns, keyColumnNames, joinType); } q.AddFrom(elementName, clazz, join); currentPropertyMapping = new CollectionPropertyMapping(collectionPersister); return(elementName); } else { // collection of values q.AddFromCollection(collectionName, collectionRole, join); return(collectionName); } }
private void PrepareForIndex(QueryTranslator q) { IQueryableCollection collPersister = q.GetCollectionPersister(collectionRole); if (!collPersister.HasIndex) { throw new QueryException("unindexed collection before []"); } string[] indexCols = collPersister.IndexColumnNames; if (indexCols.Length != 1) { throw new QueryException("composite-index appears in []: " + path); } JoinSequence fromJoins = new JoinSequence(q.Factory) .SetUseThetaStyle(useThetaStyleJoin) .SetRoot(collPersister, collectionName) .SetNext(joinSequence.Copy()); if (!continuation) { AddJoin(collectionName, collPersister.CollectionType); } joinSequence.AddCondition(new SqlString(collectionName + '.' + indexCols[0] + " = ")); CollectionElement elem = new CollectionElement(); elem.ElementColumns = collPersister.GetElementColumnNames(collectionName); elem.Type = collPersister.ElementType; elem.IsOneToMany = collPersister.IsOneToMany; elem.Alias = collectionName; elem.JoinSequence = joinSequence; collectionElements.Add(elem); //addlast SetExpectingCollectionIndex(); q.AddCollection(collectionName, collectionRole); q.AddJoin(collectionName, fromJoins); }
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; } }