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