public static void Parse( IParser p, string text, string seperators, QueryTranslator q ) { StringTokenizer tokens = new StringTokenizer( text, seperators, true ); p.Start( q ); foreach( string token in tokens ) { p.Token( token, q ); } p.End( q ); }
public string ContinueFromManyToMany( System.Type clazz, string[ ] joinColumns, QueryTranslator q ) { Start( q ); continuation = true; currentName = q.CreateNameFor( clazz ); q.AddType( currentName, clazz ); IQueryable classPersister = q.GetPersister( clazz ); join.AddJoin( classPersister.TableName, currentName, joinColumns, classPersister.IdentifierColumnNames, joinType ); currentPropertyMapping = classPersister; return currentName; }
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="q"></param> public override void End( QueryTranslator q ) { if( !IsCollectionValued ) { IType type = PropertyType; if( type.IsEntityType ) { // "finish off" the join Token( ".", q ); Token( null, q ); } else if( type.IsPersistentCollectionType ) { // default to element set if no elements() specified Token( ".", q ); Token( CollectionPropertyMapping.CollectionElements, q ); } } base.End( q ); }
/// <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 ); } }
private void DereferenceCollection(String propertyName, String role, QueryTranslator q) { collectionRole = role; IQueryableCollection collPersister = q.GetCollectionPersister( role ); string[] colNames = collPersister.KeyColumnNames; string name = q.CreateNameForCollection(role); AddJoin( collPersister.TableName, name, colNames ); if ( collPersister.HasWhere ) { join.AddCondition( collPersister.GetSQLWhereString( name ) ); } collectionName = name; collectionOwnerName = currentName; currentName = name; currentProperty = propertyName; componentPath = null; //componentPath = new StringBuilder(); currentPropertyMapping = new CollectionPropertyMapping( collPersister ); }
private void SetType( QueryTranslator q ) { if( currentProperty == null ) { type = PropertyMapping.Type; } else { type = PropertyType; } }
private void DoPathExpression( string token, QueryTranslator q ) { Preprocess( token, q ); StringTokenizer tokens = new StringTokenizer( token, ".", true ); pathExpressionParser.Start( q ); foreach( string tok in tokens ) { pathExpressionParser.Token( tok, q ); } pathExpressionParser.End( q ); if( pathExpressionParser.IsCollectionValued ) { OpenExpression( q, string.Empty ); AppendToken( q, pathExpressionParser.GetCollectionSubquery() ); CloseExpression( q, string.Empty ); // this is ugly here, but needed because its a subquery q.AddQuerySpace( q.GetCollectionPersister( pathExpressionParser.CollectionRole ).CollectionSpace ); } else { if( pathExpressionParser.IsExpectingCollectionIndex ) { expectingIndex++; } else { AddJoin( pathExpressionParser.WhereJoin, q ); AppendToken( q, pathExpressionParser.WhereColumn ); } } }
/// <summary> /// /// </summary> /// <param name="q"></param> /// <param name="token"></param> protected virtual void AppendToken( QueryTranslator q, SqlString token ) { if( expectingIndex > 0 ) { pathExpressionParser.LastCollectionElementIndexValue = token.ToString(); } else { q.AppendWhereToken( token ); } }
/// <summary> /// /// </summary> /// <param name="q"></param> public void AddAssociation( QueryTranslator q ) { q.AddJoin( Name, join ); }
/// <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; } }
public virtual void Start( QueryTranslator q ) { entityName = null; alias = null; afterIn = false; afterAs = false; afterClass = false; expectingJoin = false; expectingIn = false; expectingAs = false; joinType = JoinType.None; }
/// <summary> /// /// </summary> /// <param name="q"></param> public virtual void End( QueryTranslator q ) { ignoreInitialJoin = false; IType propertyType = PropertyType; if( propertyType != null && propertyType.IsPersistentCollectionType ) { collectionRole = ( ( PersistentCollectionType ) propertyType ).Role; collectionName = q.CreateNameForCollection( collectionRole ); PrepareForIndex( q ); } else { columns = CurrentColumns( ); SetType( q ); } //important!! continuation = false; }
public void End( QueryTranslator q ) { }
/// <summary> /// Compile a subquery /// </summary> /// <param name="superquery"></param> protected internal void Compile( QueryTranslator superquery ) { this.factory = superquery.factory; this.tokenReplacements = superquery.tokenReplacements; this.superQuery = superquery; this.shallowQuery = true; Compile( ); }
public void Start( QueryTranslator q ) { }
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 ); } } } } }
private bool ContinuePathExpression( string token, QueryTranslator q ) { expectingPathContinuation = false; PathExpressionParser.CollectionElement element = pathExpressionParser.LastCollectionElement(); if( token.StartsWith( "." ) ) { // the path expression continues after a ] DoPathExpression( GetElementName( element, q ) + token, q ); // careful with this! AddToCurrentJoin( element ); return true; //NOTE: EARLY EXIT! } else { // the path expression ends at the ] if( element.ElementColumns.Length != 1 ) { throw new QueryException( "path expression ended in composite collection element" ); } AppendToken( q, element.ElementColumns[ 0 ] ); AddToCurrentJoin( element ); return false; } }
private void Reset( QueryTranslator q ) { join = q.CreateJoinFragment( useThetaStyleJoin ); dotcount = 0; currentName = null; currentProperty = null; collectionName = null; collectionRole = null; componentPath = null; type = null; collectionName = null; columns = null; expectingCollectionIndex = false; continuation = false; currentPropertyMapping = null; }
public virtual void End( QueryTranslator q ) { if( alias != null && expectingIn ) { throw new QueryException( "in expected: <end-of-text>" + " (possibly an invalid or unmapped class name was used in the query)"); } }
/// <summary> /// /// </summary> /// <param name="q"></param> public void Start( QueryTranslator q ) { if( !continuation ) { Reset( q ); path = null; } }
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 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 ); }
private void Preprocess( string token, QueryTranslator q ) { // ugly hack for cases like "foo.bar.collection.elements" // (multi-part path expression ending in elements or indices) string[ ] tokens = StringHelper.Split( ".", token, true ); if( tokens.Length > 5 && ( "elements".Equals( tokens[ tokens.Length - 1 ] ) || "indices".Equals( tokens[ tokens.Length - 1 ] ) ) ) { pathExpressionParser.Start( q ); for( int i = 0; i < tokens.Length - 3; i++ ) { pathExpressionParser.Token( tokens[ i ], q ); } pathExpressionParser.Token( null, q ); pathExpressionParser.End( q ); AddJoin( pathExpressionParser.WhereJoin, q ); pathExpressionParser.IgnoreInitialJoin(); } }
/// <summary> /// /// </summary> /// <param name="q"></param> /// <returns></returns> public string AddFromAssociation( QueryTranslator q ) { if ( IsCollectionValued ) { return AddFromCollection( q ); } else { q.AddFrom( currentName, join ); return currentName; } }
private void AddJoin( JoinFragment ojf, QueryTranslator q ) { JoinFragment fromClause = q.CreateJoinFragment( true ); fromClause.AddJoins( ojf.ToFromFragmentString, new SqlString( String.Empty ) ); q.AddJoin( pathExpressionParser.Name, fromClause ); //TODO: HACK with ToString() AddToCurrentJoin( ojf.ToWhereFragmentString.ToString() ); }
/// <summary> /// /// </summary> /// <param name="q"></param> /// <param name="entityName"></param> public void Fetch( QueryTranslator q, string entityName ) { if ( IsCollectionValued ) { q.SetCollectionToFetch( CollectionRole, CollectionName, CollectionOwnerName, entityName ); } else { q.AddEntityToFetch( entityName, oneToOneOwnerName ); } }
/// <summary> /// /// </summary> /// <param name="propertyName"></param> /// <param name="propertyType"></param> /// <param name="q"></param> /// <remarks>NOTE: we avoid joining to the next table if the named property is just the foreign key value</remarks> private void DereferenceEntity( string propertyName, EntityType propertyType, QueryTranslator q ) { //if its "id" bool isIdShortcut = EntityID.Equals(propertyName) && !propertyType.IsUniqueKeyReference; //or its the id property name string idPropertyName; try { idPropertyName = propertyType.GetIdentifierOrUniqueKeyPropertyName( q.Factory ); } catch (MappingException me) { throw new QueryException(me); } bool isNamedIdPropertyShortcut = idPropertyName != null && idPropertyName.Equals( propertyName ); if ( isIdShortcut || isNamedIdPropertyShortcut ) { // special shortcut for id properties, skip the join! // this must only occur at the _end_ of a path expression DereferenceProperty( propertyName ); } else { System.Type entityClass = propertyType.AssociatedClass; String name = q.CreateNameFor( entityClass ); q.AddType( name, entityClass ); IQueryable memberPersister = q.GetPersister( entityClass ); //String[] keyColNames = memberPersister.getIdentifierColumnNames(); string[] keyColNames; try { keyColNames = propertyType.GetReferencedColumns( q.Factory ); } catch (MappingException me) { throw new QueryException(me); } AddJoin( memberPersister.TableName, name, keyColNames ); if ( propertyType.IsOneToOne ) { oneToOneOwnerName = currentName; } currentName = name; currentProperty = propertyName; q.AddPathAliasAndJoin( path.Substring( 0, path.LastIndexOf( StringHelper.Dot ) ), name, join ); componentPath = null; //componentPath = new StringBuilder( ); currentPropertyMapping = memberPersister; } }
public void Token( string token, QueryTranslator q ) { if( token != null ) { path += token; } string alias = q.GetPathAlias( path ); if( alias != null ) { Reset( q ); //reset the dotcount (but not the path) currentName = alias; //after reset! currentPropertyMapping = q.GetPropertyMapping( currentName ); if( !ignoreInitialJoin ) { JoinFragment ojf = q.GetPathJoin( path ); join.AddCondition( ojf.ToWhereFragmentString ); //after reset! // we don't need to worry about any condition in the ON clause // here (toFromFragmentString), since anything in the ON condition // is already applied to the whole query } } else if( ".".Equals( token ) ) { dotcount++; } else { if( dotcount == 0 ) { if( !continuation ) { if( !q.IsName( token ) ) { throw new QueryException( "undefined alias or unknown mapping: " + token ); } currentName = token; currentPropertyMapping = q.GetPropertyMapping( currentName ); } } else if( dotcount == 1 ) { if( currentName != null ) { currentProperty = token; } else if( collectionName != null ) { //IQueryableCollection p = q.GetCollectionPersister( collectionRole ); //DoCollectionProperty( token, p, collectionName ); continuation = false; } else { throw new QueryException( "unexpected" ); } } else { // dotcount>=2 // Do the corresponding RHS IType propertyType = PropertyType; if( propertyType == null ) { throw new QueryException( "unresolved property: " + currentProperty ); } if( propertyType.IsComponentType ) { DereferenceComponent( token ); } else if( propertyType.IsEntityType ) { DereferenceEntity( token, (EntityType) propertyType, q ); } else if( propertyType.IsPersistentCollectionType ) { DereferenceCollection( token, ( (PersistentCollectionType) propertyType).Role, q ); } else if( token != null ) { throw new QueryException( "dereferenced: " + currentProperty ); } } } }
/// <summary> /// /// </summary> /// <param name="q"></param> /// <param name="token"></param> protected virtual void AppendToken( QueryTranslator q, string token ) { if( expectingIndex > 0 ) { pathExpressionParser.LastCollectionElementIndexValue = token; } else { // a String.Empty can get passed in here. If that occurs // then don't create a new SqlString for it - just ignore // it since it adds nothing to the sql being generated. if( token != null && token.Length > 0 ) { q.AppendWhereToken( new SqlString( token ) ); } } }