private static IEnumerable<IReturn> GenerateCustomReturns(IEnumerable<INativeSQLQueryReturn> queryReturns, bool queryHadAliases, SQLQueryContext context)
		{
			IDictionary<string, NonScalarReturn> customReturnsByAlias = new Dictionary<string, NonScalarReturn>();

			foreach (var nativeRtn in queryReturns)
			{
				var nativeScalarRtn = nativeRtn as NativeSQLQueryScalarReturn;
				if (nativeScalarRtn != null)
				{
					yield return new ScalarReturn(nativeScalarRtn.Type, nativeScalarRtn.ColumnAlias);
					continue;
				}

				var nativeJoinRtn = nativeRtn as NativeSQLQueryJoinReturn;
				if (nativeJoinRtn != null)
				{
					var owner = customReturnsByAlias[nativeJoinRtn.OwnerAlias];
					var fetchReturn = new NonScalarReturn(context, queryHadAliases, nativeJoinRtn.Alias, nativeJoinRtn.LockMode, owner);
					yield return customReturnsByAlias[fetchReturn.Alias] = fetchReturn;
					continue;
				}

				var nativeNonScalarRtn = nativeRtn as NativeSQLQueryNonScalarReturn;
				if (nativeNonScalarRtn != null)
				{
					var nonFetchReturn = new NonScalarReturn(context, queryHadAliases, nativeNonScalarRtn.Alias, nativeNonScalarRtn.LockMode);
					yield return customReturnsByAlias[nonFetchReturn.Alias] = nonFetchReturn;
				}
			}
		}
		public SQLCustomQuery(INativeSQLQueryReturn[] queryReturns, string sqlQuery, ICollection<string> additionalQuerySpaces,
		                      ISessionFactoryImplementor factory)
		{
			log.Debug("starting processing of sql query [" + sqlQuery + "]");
			var processor = new SQLQueryContext(queryReturns, factory);

			var parser = new SQLQueryParser(factory, sqlQuery, processor);
			this.sql = parser.Process();
			this.customQueryReturns = GenerateCustomReturns(queryReturns, parser.QueryHasAliases, processor).ToList();
			this.parametersSpecifications = parser.CollectedParametersSpecifications.ToList();

			if (additionalQuerySpaces != null)
			{
				this.querySpaces.AddAll(additionalQuerySpaces);
			}
		}
		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);
				}
			}
		}
		public SQLQueryParser(ISessionFactoryImplementor factory, string sqlQuery, SQLQueryContext context)
		{
			this.factory = factory;
			originalQueryString = sqlQuery;
			this.context = context;
		}
		public NonScalarReturn(SQLQueryContext context, bool queryHasAliases, string alias, LockMode lockMode)
			: this(context, queryHasAliases, alias, lockMode, null)
		{}