public void Token( string token, QueryTranslator q ) { if( q.IsName( StringHelper.Root( token ) ) ) { ParserHelper.Parse( pathExpressionParser, q.Unalias( token ), ParserHelper.PathSeparators, q ); q.AppendGroupByToken( pathExpressionParser.WhereColumn ); pathExpressionParser.AddAssociation( q ); } else { q.AppendGroupByToken( token ); } }
/// <summary> /// /// </summary> /// <param name="token"></param> /// <param name="q"></param> public void Token( string token, QueryTranslator q ) { if( q.IsName( StringHelper.Root( token ) ) ) { ParserHelper.Parse( pathExpressionParser, q.Unalias( token ), ParserHelper.PathSeparators, q ); q.AppendOrderByToken( pathExpressionParser.WhereColumn ); pathExpressionParser.AddAssociation( q ); } else if ( token.StartsWith( ParserHelper.HqlVariablePrefix ) ) { q.AddNamedParameter( token.Substring( 1 ) ); // this is only a temporary parameter to help with the parsing of hql - // when the type becomes known then this will be converted to its real // parameter type. //AppendToken( q, new SqlString( new object[ ] {new Parameter( StringHelper.SqlParameter )} ) ); } else { q.AppendOrderByToken( token ); } }
public void Token( string token, QueryTranslator q ) { // start by looking for HQL keywords.... string lcToken = token.ToLower( System.Globalization.CultureInfo.InvariantCulture ); if( lcToken.Equals( StringHelper.Comma ) ) { if( !( expectingJoin | expectingAs ) ) { throw new QueryException( "unexpected token: ," ); } expectingJoin = false; expectingAs = false; } else if( lcToken.Equals( "join" ) ) { if( !afterJoinType ) { if( !( expectingJoin | expectingAs ) ) { throw new QueryException( "unexpected token: join" ); } // inner joins can be abbreviated to 'join' joinType = JoinType.InnerJoin; expectingJoin = false; expectingAs = false; } else { afterJoinType = false; } } else if( lcToken.Equals( "fetch" ) ) { if( q.IsShallowQuery ) { throw new QueryException( "fetch may not be used with scroll() or iterate()" ); } if( joinType == JoinType.None ) { throw new QueryException( "unexpected token: fetch" ); } if( joinType == JoinType.FullJoin || joinType == JoinType.RightOuterJoin ) { throw new QueryException( "fetch may only be used with inner join or left outer join" ); } afterFetch = true; } else if( lcToken.Equals( "outer" ) ) { // 'outer' is optional and is ignored) if( !afterJoinType || ( joinType != JoinType.LeftOuterJoin && joinType != JoinType.RightOuterJoin ) ) { throw new QueryException( "unexpected token: outer" ); } } else if( joinTypes.Contains( lcToken ) ) { if( !( expectingJoin | expectingAs ) ) { throw new QueryException( "unexpected token: " + token ); } joinType = ( JoinType ) joinTypes[ lcToken ]; afterJoinType = true; expectingJoin = false; expectingAs = false; } else if( lcToken.Equals( "class" ) ) { if( !afterIn ) { throw new QueryException( "unexpected token: class" ); } if( joinType != JoinType.None ) { throw new QueryException( "outer or full join must be followed by path expression" ); } afterClass = true; } else if( lcToken.Equals( "in" ) ) { if( !expectingIn ) { throw new QueryException( "unexpected token: in" ); } afterIn = true; expectingIn = false; } else if( lcToken.Equals( "as" ) ) { if( !expectingAs ) { throw new QueryException( "unexpected token: as" ); } afterAs = true; expectingAs = false; } else { if( afterJoinType ) { throw new QueryException( "join expected: " + token ); } if( expectingJoin ) { throw new QueryException( "unexpected token: " + token ); } if( expectingIn ) { throw new QueryException( "in expected: " + token ); } // now anything that is not a HQL keyword if( afterAs || expectingAs ) { // (AS is always optional, for consistentcy with SQL/OQL // process the "new" HQL stype where aliases are assigned // _after_ the class name or path expression ie using the // AS construction if( entityName != null ) { q.SetAliasName( token, entityName ); } else { throw new QueryException( "unexpected: as " + token ); } afterAs = false; expectingJoin = true; expectingAs = false; entityName = null; } else if( afterIn ) { // process the "old" HQL style where aliases appear _first // ie using the IN or IN CLASS constructions if( alias == null ) { throw new QueryException( "alias not specified for: " + token ); } if( joinType != JoinType.None ) { throw new QueryException( "outer or full join must be followed by path expressions" ); } if( afterClass ) { // treat it as a classname IQueryable p = q.GetPersisterUsingImports( token ); if( p == null ) { throw new QueryException( "persister not found: " + token ); } q.AddFromClass( alias, p ); } else { // treat it as a path expression peParser.JoinType = JoinType.InnerJoin; peParser.UseThetaStyleJoin = true; ParserHelper.Parse( peParser, q.Unalias( token ), ParserHelper.PathSeparators, q ); if( !peParser.IsCollectionValued ) { throw new QueryException( "pathe expression did not resolve to collection: " + token ); } string nm = peParser.AddFromCollection( q ); q.SetAliasName( alias, nm ); } alias = null; afterIn = false; afterClass = false; expectingJoin = true; } else { // handle a path expression or class name that appears // at the start, in the "new" HQL style or an alias that // appears at the start in the "old HQL stype IQueryable p = q.GetPersisterUsingImports( token ); if( p != null ) { // starts with the name of a mapped class (new style) if( joinType != JoinType.None ) { throw new QueryException( "outer or full join must be followed by path expression" ); } entityName = q.CreateNameFor( p.MappedClass ); q.AddFromClass( entityName, p ); expectingAs = true; } else if( token.IndexOf( '.' ) < 0 ) { // starts with an alias (old style) // semi-bad thing about this: can't re-alias another alias... alias = token; expectingIn = true; } else { // starts with a path expression (new style) // force HQL style: from Person p inner join p.cars c //if (joinType==JoinType.None) throw new QueryException("path expression must be preceded by full, left, right or inner join"); //allow ODMG OQL style: from Person p, p.cars c if( joinType != JoinType.None ) { peParser.JoinType = joinType; } else { peParser.JoinType = JoinType.InnerJoin; } peParser.UseThetaStyleJoin = q.IsSubquery; ParserHelper.Parse( peParser, q.Unalias( token ), ParserHelper.PathSeparators, q ); entityName = peParser.AddFromAssociation( q ); joinType = JoinType.None; peParser.JoinType = JoinType.InnerJoin; if( afterFetch ) { peParser.Fetch( q, entityName ); afterFetch = false; } expectingAs = true; } } } }
private void DoToken( string token, QueryTranslator q ) { if( q.IsName( StringHelper.Root( token ) ) ) //path expression { DoPathExpression( q.Unalias( token ), q ); } else if( token.StartsWith( ParserHelper.HqlVariablePrefix ) ) //named query parameter { q.AddNamedParameter( token.Substring( 1 ) ); // this is only a temporary parameter to help with the parsing of hql - // when the type becomes known then this will be converted to its real // parameter type. AppendToken( q, new SqlString( new object[ ] {new Parameter( StringHelper.SqlParameter )} ) ); } else if( token.Equals( StringHelper.SqlParameter ) ) { //if the token is a "?" then we have a Parameter so convert it to a SqlCommand.Parameter // instead of appending a "?" to the WhereTokens q.AppendWhereToken( new SqlString( new object[ ] {new Parameter( StringHelper.SqlParameter)} ) ); } else { IQueryable persister = q.GetPersisterUsingImports( token ); if( persister != null ) // the name of a class { object discrim = persister.DiscriminatorSQLValue; if ( InFragment.Null == discrim || InFragment.NotNull == discrim ) { throw new QueryException( "subclass test not allowed for null or not null discriminator" ); } AppendToken( q, discrim.ToString() ); } else { object constant; string fieldName = null; string typeName = null; string importedName = null; int indexOfDot = token.IndexOf( StringHelper.Dot ); // don't even bother to do the lookups if the indexOfDot is not // greater than -1. This will save all the string modifications. // This allows us to resolve to the full type before obtaining the value e.g. FooStatus.OFF -> NHibernate.Model.FooStatus.OFF if( indexOfDot > -1 ) { fieldName = StringHelper.Unqualify( token ); typeName = StringHelper.Qualifier( token ); importedName = q.factory.GetImportedClassName( typeName ); } if( indexOfDot > - 1 && ( constant = ReflectHelper.GetConstantValue( importedName, fieldName ) ) != null ) { // need to get the NHibernate Type so we can convert the Enum or field from // a class into it's string representation for hql. IType type; try { type = TypeFactory.HeuristicType( constant.GetType().AssemblyQualifiedName ); } catch( MappingException me ) { throw new QueryException( me ); } if ( type == null ) { throw new QueryException( string.Format( "Could not determin the type of: {0}", token ) ); } try { AppendToken( q, ( ( ILiteralType ) type ).ObjectToSQLString( constant ) ); } catch( Exception e ) { throw new QueryException( "Could not format constant value to SQL literal: " + token, e ); } } else { //anything else string negatedToken = negated ? ( string ) negations[ token.ToLower( System.Globalization.CultureInfo.InvariantCulture ) ] : null; if( negatedToken != null && ( !betweenSpecialCase || !"or".Equals( negatedToken ) ) ) { AppendToken( q, negatedToken ); } else { AppendToken( q, token ); } } } } }
/// <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; } }