public SqlLoader(string[] aliases, ISqlLoadable[] persisters, ISessionFactoryImplementor factory, string sqlQuery, ICollection additionalQuerySpaces) : base(factory.Dialect) { this.sqlQuery = sqlQuery; this.aliases = aliases; // Remember the factory for the PopulateSqlString call. this.factory = factory; alias2Persister = new Hashtable(); ArrayList resultTypeList = new ArrayList(); for (int i = 0; i < persisters.Length; i++) { ISqlLoadable persister = persisters[i]; alias2Persister.Add(aliases[i], persister); // TODO: Does not consider any other tables referenced in the query querySpaces.AddAll(persister.PropertySpaces); resultTypeList.Add(persister.Type); } if (additionalQuerySpaces != null) { querySpaces.AddAll(additionalQuerySpaces); } resultTypes = ( IType[] )resultTypeList.ToArray(typeof(IType)); RenderStatement(persisters); PostInstantiate(); }
public SqlLoader( string[ ] aliases, ISqlLoadable[ ] persisters, ISessionFactoryImplementor factory, string sqlQuery, ICollection additionalQuerySpaces ) : base( factory.Dialect ) { this.sqlQuery = sqlQuery; this.aliases = aliases; // Remember the factory for the PopulateSqlString call. this.factory = factory; alias2Persister = new Hashtable(); ArrayList resultTypeList = new ArrayList(); for( int i = 0; i < persisters.Length; i++ ) { ISqlLoadable persister = persisters[ i ]; alias2Persister.Add( aliases[ i ], persister ); // TODO: Does not consider any other tables referenced in the query querySpaces.AddAll( persister.PropertySpaces ); resultTypeList.Add( persister.Type ); } if( additionalQuerySpaces != null ) { querySpaces.AddAll( additionalQuerySpaces ); } resultTypes = ( IType[ ] ) resultTypeList.ToArray( typeof( IType ) ); RenderStatement( persisters ); PostInstantiate(); }
private string ResolveCollectionProperties( string aliasName, string propertyName, IDictionary fieldResults, ISqlLoadable elementPersister, ISqlLoadableCollection currentPersister, string suffix, string persisterSuffix) { if ("*".Equals(propertyName)) { if (fieldResults.Count > 0) { throw new QueryException("Using return-propertys together with * syntax is not supported."); } string selectFragment = currentPersister.SelectFragment(aliasName, suffix); aliasesFound++; return selectFragment + ", " + ResolveProperties(aliasName, propertyName, fieldResults, elementPersister, persisterSuffix); } else if ("element.*".Equals(propertyName)) { return ResolveProperties(aliasName, "*", fieldResults, elementPersister, persisterSuffix); } else { string[] columnAliases; // Let return-propertys override whatever the persister has for aliases. columnAliases = (string[]) fieldResults[propertyName]; if (columnAliases == null) { columnAliases = currentPersister.GetCollectionPropertyColumnAliases(propertyName, suffix); } if (columnAliases == null || columnAliases.Length == 0) { throw new QueryException("No column name found for property [" + propertyName + "] for alias [" + aliasName + "]", sqlQuery); } if (columnAliases.Length != 1) { // TODO: better error message since we actually support composites if names are explicitly listed. throw new QueryException("SQL queries only support properties mapped to a single column - property [" + propertyName + "] is mapped to " + columnAliases.Length + " columns.", sqlQuery); } aliasesFound++; return columnAliases[0]; } }
private void AddPersister(string alias, IDictionary <string, string[]> propertyResult, ISqlLoadable persister) { alias2Persister[alias] = persister; string suffix = GenerateEntitySuffix(); log.Debug("mapping alias [{0}] to entity-suffix [{1}]", alias, suffix); alias2Suffix[alias] = suffix; entityPropertyResultMaps[alias] = propertyResult; }
private void ProcessRootReturn(NativeSQLQueryRootReturn rootReturn) { if (alias2Persister.ContainsKey(rootReturn.Alias)) { // already been processed... return; } ISqlLoadable persister = GetSQLLoadable(rootReturn.ReturnEntityName); AddPersister(rootReturn.Alias, rootReturn.PropertyResultsMap, persister); }
private void AddCollection(string role, string alias, IDictionary <string, string[]> propertyResults) { ISqlLoadableCollection collectionPersister = (ISqlLoadableCollection)Factory.GetCollectionPersister(role); alias2CollectionPersister[alias] = collectionPersister; string suffix = GenerateCollectionSuffix(); log.Debug("mapping alias [{0}] to collection-suffix [{1}]", alias, suffix); alias2CollectionSuffix[alias] = suffix; collectionPropertyResultMaps[alias] = propertyResults; if (collectionPersister.IsOneToMany) { ISqlLoadable persister = (ISqlLoadable)collectionPersister.ElementPersister; AddPersister(alias, Filter(propertyResults), persister); } }
private string ResolveProperties(string aliasName, string propertyName) { IDictionary <string, string[]> fieldResults = context.GetPropertyResultsMapByAlias(aliasName); ISqlLoadable persister = context.GetEntityPersisterByAlias(aliasName); string suffix = context.GetEntitySuffixByAlias(aliasName); if ("*".Equals(propertyName)) { if (fieldResults.Count != 0) { throw new QueryException("Using return-propertys together with * syntax is not supported."); } aliasesFound++; return(persister.SelectFragment(aliasName, suffix)); } else { string[] columnAliases; // Let return-propertys override whatever the persister has for aliases. if (!fieldResults.TryGetValue(propertyName, out columnAliases)) { columnAliases = persister.GetSubclassPropertyColumnAliases(propertyName, suffix); } if (columnAliases == null || columnAliases.Length == 0) { throw new QueryException("No column name found for property [" + propertyName + "] for alias [" + aliasName + "]", originalQueryString); } if (columnAliases.Length != 1) { // TODO: better error message since we actually support composites if names are explicitly listed. throw new QueryException( "SQL queries only support properties mapped to a single column - property [" + propertyName + "] is mapped to " + columnAliases.Length + " columns.", originalQueryString); } aliasesFound++; return(columnAliases[0]); } }
private void ProcessJoinReturn(NativeSQLQueryJoinReturn fetchReturn) { string alias = fetchReturn.Alias; if (alias2Persister.ContainsKey(alias) || alias2CollectionPersister.ContainsKey(alias)) { // already been processed... return; } string ownerAlias = fetchReturn.OwnerAlias; // Make sure the owner alias is known... if (!alias2Return.ContainsKey(ownerAlias)) { throw new HibernateException(string.Format("Owner alias [{0}] is unknown for alias [{1}]", ownerAlias, alias)); } // If this return's alias has not been processed yet, do so b4 further processing of this return if (!alias2Persister.ContainsKey(ownerAlias)) { ProcessReturn(alias2Return[ownerAlias]); } ISqlLoadable ownerPersister = alias2Persister[ownerAlias]; IType returnType = ownerPersister.GetPropertyType(fetchReturn.OwnerProperty); if (returnType.IsCollectionType) { string role = ownerPersister.EntityName + '.' + fetchReturn.OwnerProperty; AddCollection(role, alias, fetchReturn.PropertyResultsMap); } else if (returnType.IsEntityType) { EntityType eType = (EntityType)returnType; string returnEntityName = eType.GetAssociatedEntityName(); ISqlLoadable persister = GetSQLLoadable(returnEntityName); AddPersister(alias, fetchReturn.PropertyResultsMap, persister); } }
public NonScalarReturn(SQLQueryContext context, bool queryHasAliases, string alias, LockMode lockMode, NonScalarReturn owner) { if (context == null) { throw new ArgumentNullException("context"); } if (string.IsNullOrEmpty(alias)) { throw new HibernateException("alias must be specified"); } this.alias = alias; this.lockMode = lockMode; this.owner = owner; this.collectionPersister = context.GetCollectionPersister(alias); if (this.collectionPersister != null) { var collectionPropertyResultMap = context.GetCollectionPropertyResultsMap(alias); this.collectionAliases = queryHasAliases ? new GeneratedCollectionAliases(collectionPropertyResultMap, this.collectionPersister, context.GetCollectionSuffix(alias)) : (ICollectionAliases)new ColumnCollectionAliases(collectionPropertyResultMap, this.collectionPersister); } if (this.collectionPersister == null || this.CollectionPersister.ElementType.IsEntityType) { this.entityPersister = context.GetEntityPersister(alias); if (this.entityPersister != null) { var entityPropertyResultMap = context.GetEntityPropertyResultsMap(alias); this.entityAliases = queryHasAliases ? new DefaultEntityAliases(entityPropertyResultMap, this.entityPersister, context.GetEntitySuffix(alias)) : new ColumnEntityAliases(entityPropertyResultMap, this.entityPersister); } } }
private void AddPersister(string alias, IDictionary<string, string[]> propertyResult, ISqlLoadable persister) { alias2Persister[alias] = persister; string suffix = GenerateEntitySuffix(); log.Debug("mapping alias [" + alias + "] to entity-suffix [" + suffix + "]"); alias2Suffix[alias] = suffix; entityPropertyResultMaps[alias] = propertyResult; }
private string ResolveProperties( string aliasName, string propertyName, IDictionary fieldResults, ISqlLoadable currentPersister, string suffix) { /*int currentPersisterIndex = getPersisterIndex( aliasName ); if ( !aliasName.Equals( aliases[currentPersisterIndex] ) ) { throw new QueryException( "Alias [" + aliasName + "] does not correspond to return alias " + aliases[currentPersisterIndex], sqlQuery ); }*/ if ("*".Equals(propertyName)) { if (fieldResults.Count > 0) { throw new QueryException("Using return-propertys together with * syntax is not supported."); } aliasesFound++; return currentPersister.SelectFragment(aliasName, suffix); } else { string[] columnAliases; // Let return-propertys override whatever the persister has for aliases. columnAliases = (string[]) fieldResults[propertyName]; if (columnAliases == null) { columnAliases = currentPersister.GetSubclassPropertyColumnAliases(propertyName, suffix); } if (columnAliases == null || columnAliases.Length == 0) { throw new QueryException("No column name found for property [" + propertyName + "] for alias [" + aliasName + "]", sqlQuery); } if (columnAliases.Length != 1) { // TODO: better error message since we actually support composites if names are explicitly listed. throw new QueryException("SQL queries only support properties mapped to a single column - property [" + propertyName + "] is mapped to " + columnAliases.Length + " columns.", sqlQuery); } aliasesFound++; return columnAliases[0]; } }
/// <summary> /// Inspired by the parsing done in TJDO /// TODO: Should record how many properties we have referred to - and throw exception if we don't get them all aka AbstractQueryImpl /// </summary> /// <returns></returns> public string SubstituteBrackets() { string sqlString = sqlQuery; StringBuilder result = new StringBuilder(); int left, right; // replace {....} with corresponding column aliases for (int curr = 0; curr < sqlString.Length; curr = right + 1) { if ((left = sqlString.IndexOf('{', curr)) < 0) { result.Append(sqlString.Substring(curr)); break; } result.Append(sqlString.Substring(curr, left - curr)); if ((right = sqlString.IndexOf('}', left + 1)) < 0) { throw new QueryException("Unmatched braces for alias path", sqlString); } string aliasPath = sqlString.Substring(left + 1, right - left - 1); int firstDot = aliasPath.IndexOf('.'); string aliasName = firstDot == -1 ? aliasPath : aliasPath.Substring(0, firstDot); ISqlLoadable currentPersister = GetPersisterByResultAlias(aliasName); if (currentPersister == null) { // TODO: Do we throw this or pass through as per Hibernate to allow for escape sequences as per HB-898 throw new QueryException(string.Format("Alias [{0}] does not correspond to any of the supplied return aliases = {1}", aliasName, aliases), sqlQuery); //result.Append( "{" + aliasPath + "}" ); //continue; } int currentPersisterIndex = GetPersisterIndex(aliasName); if (firstDot == -1) { // TODO: should this one also be aliased/quoted instead of just directly inserted ? result.Append(aliasPath); } else { if (aliasName != aliases[currentPersisterIndex]) { throw new QueryException(string.Format("Alias [{0}] does not correspond to return alias {1}", aliasName, aliases[currentPersisterIndex]), sqlQuery); } string propertyName = aliasPath.Substring(firstDot + 1); if ("*".Equals(propertyName)) { result.Append(currentPersister.SelectFragment(aliasName, Suffixes[currentPersisterIndex])); } else { // Here it would be nice just to be able to do result.Append( getAliasFor( currentPersister, propertyName )) // but that requires more exposure of the internal maps of the persister... // but it should be possible as propertyname should be unique for all persisters string[] columnAliases; /* * if ( AbstractEntityPersister.ENTITY_CLASS.Equals( propertyName ) * { * columnAliases = new string[1]; * columnAliases[0] = currentPersister.GetDiscriminatorAlias( suffixes[ currentPersisterIndex ] ) ; * } * else */ columnAliases = currentPersister.GetSubclassPropertyColumnAliases(propertyName, Suffixes[currentPersisterIndex]); if (columnAliases == null || columnAliases.Length == 0) { throw new QueryException(string.Format("No column name found for property [{0}]", propertyName), sqlQuery); } if (columnAliases.Length != 1) { throw new QueryException(string.Format("SQL queries only support properties mapped to a single column. Property [{0}] is mapped to {1} columns.", propertyName, columnAliases.Length), sqlQuery); } result.Append(columnAliases[0]); } } } // Possibly handle :something parameters for the query? return(result.ToString()); }
/// <summary> /// /// </summary> /// <param name="sqlQuery"></param> /// <param name="aliases"></param> /// <param name="classes"></param> /// <param name="queryParameters"></param> /// <param name="querySpaces"></param> /// <returns></returns> public IList FindBySQL( string sqlQuery, string[ ] aliases, System.Type[ ] classes, QueryParameters queryParameters, ICollection querySpaces ) { if( log.IsDebugEnabled ) { log.Debug( "SQL Query: " + sqlQuery ); } ISqlLoadable[ ] persisters = new ISqlLoadable[classes.Length]; for( int i = 0; i < classes.Length; i++ ) { persisters[ i ] = GetSqlLoadable( classes[ i ] ); } // TODO: 2.1+ We could cache these SqlLoader loader = new SqlLoader( aliases, persisters, factory, sqlQuery, querySpaces ); AutoFlushIfRequired( loader.QuerySpaces ); // TODO: Do we need to use the .NET synchronised methods here? dontFlushFromFind++; try { return loader.List( this, queryParameters ); } catch( HibernateException ) { // Do not call Convert on HibernateExceptions throw; } catch( Exception sqle ) { throw Convert( sqle, "error in FindBySQL" ); } finally { // TODO: Do we need to use the .NET synchronised methods here? dontFlushFromFind--; } }