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