Example #1
0
        /// <summary>
        /// Generate a sequence of <c>LEFT OUTER JOIN</c> clauses for the given associations.
        /// </summary>
        protected JoinFragment MergeOuterJoins(IList <OuterJoinableAssociation> associations)
        {
            JoinFragment outerjoin = Dialect.CreateOuterJoinFragment();

            OuterJoinableAssociation last = null;

            foreach (OuterJoinableAssociation oj in associations)
            {
                if (last != null && last.IsManyToManyWith(oj))
                {
                    oj.AddManyToManyJoin(outerjoin, (IQueryableCollection)last.Joinable);
                }
                else
                {
                    oj.AddJoins(outerjoin);
                    // NH Different behavior : NH1179 and NH1293
                    // Apply filters in Many-To-One association
                    if (enabledFiltersForManyToOne.Count > 0)
                    {
                        string manyToOneFilterFragment = oj.Joinable.FilterFragment(oj.RHSAlias, enabledFiltersForManyToOne);
                        bool   joinClauseDoesNotContainsFilterAlready =
                            outerjoin.ToFromFragmentString.IndexOfCaseInsensitive(manyToOneFilterFragment) == -1;
                        if (joinClauseDoesNotContainsFilterAlready)
                        {
                            outerjoin.AddCondition(manyToOneFilterFragment);
                        }
                    }
                }
                last = oj;
            }

            return(outerjoin);
        }
        private void InitStatementString(OuterJoinableAssociation rootAssociation, SqlString projection, SqlString condition, SqlString orderBy, SqlString groupBy, SqlString having, LockMode lockMode)
        {
            SqlString selectClause = projection;

            if (selectClause == null)
            {
                int joins = CountEntityPersisters(associations);

                Suffixes = BasicLoader.GenerateSuffixes(joins + 1);
                var suffix = Suffixes[joins];
                selectClause = new SqlString(GetSelectFragment(rootAssociation, suffix, null) + SelectString(associations));
            }

            JoinFragment ojf = MergeOuterJoins(associations);

            SqlSelectBuilder select = new SqlSelectBuilder(Factory)
                                      .SetLockMode(lockMode, alias)
                                      .SetSelectClause(selectClause)
                                      .SetFromClause(Dialect.AppendLockHint(lockMode, persister.FromTableFragment(alias)) + persister.FromJoinFragment(alias, true, true))
                                      .SetWhereClause(condition)
                                      .SetOuterJoins(ojf.ToFromFragmentString, ojf.ToWhereFragmentString + WhereFragment)
                                      .SetOrderByClause(
                projection == null
                                                ? OrderBy(associations, orderBy)
                                                : orderBy)
                                      .SetGroupByClause(groupBy)
                                      .SetHavingClause(having);

            if (Factory.Settings.IsCommentsEnabled)
            {
                select.SetComment(Comment);
            }

            SqlString = select.ToSqlString();
        }
        protected void InitProjection(SqlString projectionString, SqlString whereString, SqlString orderByString, SqlString groupByString, SqlString havingString, IDictionary <string, IFilter> enabledFilters, LockMode lockMode, IList <EntityProjection> entityProjections)
        {
            AddAssociations();

            int countEntities = entityProjections.Count;

            if (countEntities > 0)
            {
                var associations = new OuterJoinableAssociation[countEntities];
                var eagerProps   = new bool[countEntities];
                var suffixes     = new string[countEntities];
                for (var i = 0; i < countEntities; i++)
                {
                    var e = entityProjections[i];
                    associations[i] = CreateAssociation(e.Persister.EntityMetamodel.EntityType, e.TableAlias);
                    if (e.FetchLazyProperties)
                    {
                        eagerProps[i] = true;
                    }
                    suffixes[i] = e.ColumnAliasSuffix;
                }

                InitPersisters(associations, lockMode);

                Suffixes             = suffixes;
                EagerPropertyFetches = eagerProps;
            }
            else
            {
                Persisters = Array.Empty <ILoadable>();
                Suffixes   = Array.Empty <string>();
            }

            InitStatementString(null, projectionString, whereString, orderByString, groupByString, havingString, lockMode);
        }
        /// <summary>
        /// Adds an association and extracts the aliases the association's 'with clause' is dependent on
        /// </summary>
        private void AddAssociation(string subalias, OuterJoinableAssociation association)
        {
            var dependentAlias = new DependentAlias
            {
                Alias = subalias,
            };

            _dependentAliases.Add(dependentAlias);

            var on = association.On.ToString();

            if (!string.IsNullOrEmpty(on))
            {
                var dependencies = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
                foreach (Match match in aliasRegex.Matches(on))
                {
                    string alias = match.Value;
                    if (string.Equals(alias, subalias, StringComparison.OrdinalIgnoreCase))
                    {
                        continue;
                    }
                    dependencies.Add(alias);
                }
                dependentAlias.DependsOn = dependencies.ToArray();
            }

            associations.Add(association);
        }
Example #5
0
        /// <summary>
        /// Generate a select list of columns containing all properties of the entity classes
        /// </summary>
        /// <param name="associations"></param>
        /// <param name="factory"></param>
        /// <returns></returns>
        public string SelectString(IList associations, ISessionFactoryImplementor factory)
        {
            if (associations.Count == 0)
            {
                return(string.Empty);
            }
            else
            {
                StringBuilder buf = new StringBuilder(associations.Count * 100);
                buf.Append(StringHelper.CommaSpace);
                int aliasCount = 0;
                for (int i = 0; i < associations.Count; i++)
                {
                    OuterJoinableAssociation join = ( OuterJoinableAssociation )associations[i];
                    string selectFragment         = join.Joinable.SelectFragment(
                        join.Subalias,
                        Suffixes[aliasCount],
                        join.JoinType == JoinType.LeftOuterJoin
                        ).ToString();

                    buf.Append(selectFragment);
                    if (join.Joinable.ConsumesAlias())
                    {
                        aliasCount++;
                    }
                    if (i < associations.Count - 1 &&
                        !selectFragment.Trim().Equals(string.Empty))
                    {
                        buf.Append(StringHelper.CommaSpace);
                    }
                }
                return(buf.ToString());
            }
        }
Example #6
0
 private void FillEntityPersisterProperties(int i, OuterJoinableAssociation oj, ILoadable persister)
 {
     persisters[i]           = persister;
     aliases[i]              = oj.RHSAlias;
     EagerPropertyFetches[i] = oj.SelectMode == SelectMode.FetchLazyProperties;
     ChildFetchEntities[i]   = oj.SelectMode == SelectMode.ChildFetch;
 }
Example #7
0
        /// <summary>
        /// Adds an association and extracts the aliases the association's 'with clause' is dependent on
        /// </summary>
        private void AddAssociation(string subalias, OuterJoinableAssociation association)
        {
            subalias = subalias.ToLower();

            var dependencies = new List <string>();
            var on           = association.On.ToString();

            if (!String.IsNullOrEmpty(on))
            {
                foreach (Match match in aliasRegex.Matches(on))
                {
                    string alias = match.Groups[1].Value;
                    if (alias == subalias)
                    {
                        continue;
                    }
                    dependencies.Add(alias.ToLower());
                }
            }

            _dependentAliases.Add(new DependentAlias
            {
                Alias     = subalias,
                DependsOn = dependencies.ToArray()
            });

            associations.Add(association);
        }
Example #8
0
        internal void AddExplicitEntityJoinAssociation(
            IOuterJoinLoadable persister,
            string tableAlias,
            JoinType joinType,
            string path,
            string pathAlias)
        {
            OuterJoinableAssociation assoc =
                InitAssociation(new OuterJoinableAssociation(
                                    persister.EntityType,
                                    string.Empty,
                                    Array.Empty <string>(),
                                    tableAlias,
                                    joinType,
                                    GetWithClause(path, pathAlias),
                                    Factory,
                                    enabledFilters,
                                    GetSelectMode(path))
            {
                ForceFilter = true
            },
                                path);

            AddAssociation(assoc);
        }
Example #9
0
        /// <summary>
        /// Add on association (one-to-one, many-to-one, or a collection) to a list
        /// of associations to be fetched by outerjoin
        /// </summary>
        private void AddAssociationToJoinTree(IAssociationType type, string[] aliasedLhsColumns, string alias,
                                              string path, int currentDepth, JoinType joinType)
        {
            IJoinable joinable = type.GetAssociatedJoinable(Factory);

            string subalias = GenerateTableAlias(associations.Count + 1, path, joinable);

            OuterJoinableAssociation assoc =
                new OuterJoinableAssociation(type, alias, aliasedLhsColumns, subalias, joinType, GetWithClause(path), Factory, enabledFilters);

            assoc.ValidateJoin(path);
            AddAssociation(subalias, assoc);

            int nextDepth = currentDepth + 1;

            if (!joinable.IsCollection)
            {
                IOuterJoinLoadable pjl = joinable as IOuterJoinLoadable;
                if (pjl != null)
                {
                    WalkEntityTree(pjl, subalias, path, nextDepth);
                }
            }
            else
            {
                IQueryableCollection qc = joinable as IQueryableCollection;
                if (qc != null)
                {
                    WalkCollectionTree(qc, subalias, path, nextDepth);
                }
            }
        }
Example #10
0
 protected int ToOwner(OuterJoinableAssociation oj, int joins, bool dontIgnore)
 {
     if (dontIgnore)
     {
         return(oj.Owner == -1 ? joins : oj.Owner);                 //TODO: UGLY AS SIN!
     }
     else
     {
         return(-1);
     }
 }
Example #11
0
 public bool IsManyToManyWith(OuterJoinableAssociation other)
 {
     if (joinable.IsCollection)
     {
         IQueryableCollection persister = (IQueryableCollection)joinable;
         if (persister.IsManyToMany)
         {
             return(persister.ElementType == other.JoinableType);
         }
     }
     return(false);
 }
Example #12
0
        /// <summary>
        /// Generate a sequence of <c>LEFT OUTER JOIN</c> clauses for the given associations.
        /// </summary>
        protected JoinFragment MergeOuterJoins(IList <OuterJoinableAssociation> associations)
        {
            JoinFragment outerjoin = Dialect.CreateOuterJoinFragment();

            var sortedAssociations        = GetSortedAssociations(associations);
            OuterJoinableAssociation last = null;

            foreach (OuterJoinableAssociation oj in sortedAssociations)
            {
                if (last != null && last.IsManyToManyWith(oj))
                {
                    oj.AddManyToManyJoin(outerjoin, (IQueryableCollection)last.Joinable);
                }
                else
                {
                    // NH Different behavior : NH1179 and NH1293
                    // Apply filters for entity joins and Many-To-One associations
                    SqlString filter = null;
                    var       enabledFiltersForJoin = oj.ForceFilter ? enabledFilters : enabledFiltersForManyToOne;
                    if (oj.ForceFilter || enabledFiltersForJoin.Count > 0)
                    {
                        string manyToOneFilterFragment = oj.Joinable.FilterFragment(oj.RHSAlias, enabledFiltersForJoin);
                        bool   joinClauseDoesNotContainsFilterAlready =
                            oj.On?.IndexOfCaseInsensitive(manyToOneFilterFragment) == -1;
                        if (joinClauseDoesNotContainsFilterAlready)
                        {
                            filter = new SqlString(manyToOneFilterFragment);
                        }
                    }

                    if (TableGroupJoinHelper.ProcessAsTableGroupJoin(new[] { oj }, new[] { oj.On, filter }, true, outerjoin, alias => true, factory))
                    {
                        continue;
                    }

                    oj.AddJoins(outerjoin);

                    // Ensure that the join condition is added to the join, not the where clause.
                    // Adding the condition to the where clause causes left joins to become inner joins.
                    if (SqlStringHelper.IsNotEmpty(filter))
                    {
                        outerjoin.AddFromFragmentString(filter);
                    }
                }
                last = oj;
            }

            return(outerjoin);
        }
Example #13
0
        /// <summary>
        /// Generate a select list of columns containing all properties of the entity classes
        /// </summary>
        public string SelectString(IList <OuterJoinableAssociation> associations)
        {
            if (associations.Count == 0)
            {
                return(string.Empty);
            }
            else
            {
                SqlStringBuilder buf = new SqlStringBuilder(associations.Count * 3);

                int entityAliasCount     = 0;
                int collectionAliasCount = 0;

                for (int i = 0; i < associations.Count; i++)
                {
                    OuterJoinableAssociation join = associations[i];
                    OuterJoinableAssociation next = (i == associations.Count - 1) ? null : associations[i + 1];

                    IJoinable joinable     = join.Joinable;
                    string    entitySuffix = (suffixes == null || entityAliasCount >= suffixes.Length) ? null : suffixes[entityAliasCount];

                    string collectionSuffix = (collectionSuffixes == null || collectionAliasCount >= collectionSuffixes.Length)
                                                                                                                                                        ? null
                                                                                                                                                        : collectionSuffixes[collectionAliasCount];

                    string selectFragment =
                        joinable.SelectFragment(next == null ? null : next.Joinable, next == null ? null : next.RHSAlias, join.RHSAlias,
                                                entitySuffix, collectionSuffix, join.JoinType == JoinType.LeftOuterJoin);

                    if (selectFragment.Trim().Length > 0)
                    {
                        buf.Add(StringHelper.CommaSpace)
                        .Add(selectFragment);
                    }
                    if (joinable.ConsumesEntityAlias())
                    {
                        entityAliasCount++;
                    }

                    if (joinable.ConsumesCollectionAlias() && join.JoinType == JoinType.LeftOuterJoin)
                    {
                        collectionAliasCount++;
                    }
                }

                return(buf.ToSqlString().ToString());
            }
        }
Example #14
0
        /// <summary>
        /// Get the order by string required for collection fetching
        /// </summary>
        protected SqlString OrderBy(IList <OuterJoinableAssociation> associations)
        {
            SqlStringBuilder buf = new SqlStringBuilder();

            OuterJoinableAssociation last = null;

            foreach (OuterJoinableAssociation oj in associations)
            {
                if (oj.JoinType == JoinType.LeftOuterJoin)
                {
                    if (oj.Joinable.IsCollection)
                    {
                        IQueryableCollection queryableCollection = (IQueryableCollection)oj.Joinable;
                        if (queryableCollection.HasOrdering)
                        {
                            string orderByString = queryableCollection.GetSQLOrderByString(oj.RHSAlias);
                            buf.Add(orderByString).Add(StringHelper.CommaSpace);
                        }
                    }
                    else
                    {
                        // it might still need to apply a collection ordering based on a
                        // many-to-many defined order-by...
                        if (last != null && last.Joinable.IsCollection)
                        {
                            IQueryableCollection queryableCollection = (IQueryableCollection)last.Joinable;
                            if (queryableCollection.IsManyToMany && last.IsManyToManyWith(oj))
                            {
                                if (queryableCollection.HasManyToManyOrdering)
                                {
                                    string orderByString = queryableCollection.GetManyToManyOrderByString(oj.RHSAlias);
                                    buf.Add(orderByString).Add(StringHelper.CommaSpace);
                                }
                            }
                        }
                    }
                }
                last = oj;
            }

            if (buf.Count > 0)
            {
                buf.RemoveAt(buf.Count - 1);
            }

            return(buf.ToSqlString());
        }
Example #15
0
        /// <summary>
        /// Generate a select list of columns containing all properties of the entity classes
        /// </summary>
        public string SelectString(IList <OuterJoinableAssociation> associations)
        {
            if (associations.Count == 0)
            {
                return(string.Empty);
            }
            else
            {
                SqlStringBuilder buf = new SqlStringBuilder(associations.Count * 3);

                int entityAliasCount     = 0;
                int collectionAliasCount = 0;

                for (int i = 0; i < associations.Count; i++)
                {
                    OuterJoinableAssociation join = associations[i];
                    OuterJoinableAssociation next = (i == associations.Count - 1) ? null : associations[i + 1];

                    IJoinable joinable     = join.Joinable;
                    string    entitySuffix = (suffixes == null || entityAliasCount >= suffixes.Length) ? null : suffixes[entityAliasCount];

                    string collectionSuffix = (collectionSuffixes == null || collectionAliasCount >= collectionSuffixes.Length)
                                                                                                                                                        ? null
                                                                                                                                                        : collectionSuffixes[collectionAliasCount];

                    string selectFragment =
                        GetSelectFragment(join, entitySuffix, collectionSuffix, next);

                    if (!string.IsNullOrWhiteSpace(selectFragment))
                    {
                        buf.Add(StringHelper.CommaSpace)
                        .Add(selectFragment);
                    }
                    if (joinable.ConsumesEntityAlias() && join.SelectMode != SelectMode.JoinOnly)
                    {
                        entityAliasCount++;
                    }

                    if (joinable.ConsumesCollectionAlias() && join.ShouldFetchCollectionPersister())
                    {
                        collectionAliasCount++;
                    }
                }

                return(buf.ToSqlString().ToString());
            }
        }
Example #16
0
        /// <summary>
        /// Generate a sequence of <c>LEFT OUTER JOIN</c> clauses for the given associations.
        /// </summary>
        protected JoinFragment MergeOuterJoins(IList <OuterJoinableAssociation> associations)
        {
            IList <OuterJoinableAssociation> sortedAssociations = new List <OuterJoinableAssociation>();

            var indices = GetTopologicalSortOrder(_dependentAliases);

            for (int index = indices.Length - 1; index >= 0; index--)
            {
                sortedAssociations.Add(associations[indices[index]]);
            }

            JoinFragment outerjoin = Dialect.CreateOuterJoinFragment();

            OuterJoinableAssociation last = null;

            foreach (OuterJoinableAssociation oj in sortedAssociations)
            {
                if (last != null && last.IsManyToManyWith(oj))
                {
                    oj.AddManyToManyJoin(outerjoin, (IQueryableCollection)last.Joinable);
                }
                else
                {
                    oj.AddJoins(outerjoin);
                    // NH Different behavior : NH1179 and NH1293
                    // Apply filters in Many-To-One association
                    if (enabledFiltersForManyToOne.Count > 0)
                    {
                        string manyToOneFilterFragment = oj.Joinable.FilterFragment(oj.RHSAlias, enabledFiltersForManyToOne);
                        bool   joinClauseDoesNotContainsFilterAlready =
                            outerjoin.ToFromFragmentString.IndexOfCaseInsensitive(manyToOneFilterFragment) == -1;
                        if (joinClauseDoesNotContainsFilterAlready)
                        {
                            // Ensure that the join condition is added to the join, not the where clause.
                            // Adding the condition to the where clause causes left joins to become inner joins.
                            outerjoin.AddFromFragmentString(new SqlString(manyToOneFilterFragment));
                        }
                    }
                }
                last = oj;
            }

            return(outerjoin);
        }
        internal void AddExplicitEntityJoinAssociation(
            IOuterJoinLoadable persister,
            string tableAlias,
            JoinType joinType,
            SqlString withClause)
        {
            OuterJoinableAssociation assoc =
                new OuterJoinableAssociation(
                    persister.EntityType,
                    string.Empty,
                    Array.Empty <string>(),
                    tableAlias,
                    joinType,
                    withClause,
                    Factory,
                    enabledFilters);

            AddAssociation(tableAlias, assoc);
        }
Example #18
0
        /// <summary>
        /// Get the position of the join with the given alias in the list of joins, or -1 if not found
        /// </summary>
        /// <param name="alias"></param>
        /// <param name="associations"></param>
        /// <returns></returns>
        private static int GetPosition(string alias, IList associations)
        {
            int result = 0;

            for (int i = 0; i < associations.Count; i++)
            {
                OuterJoinableAssociation oj = associations[i] as OuterJoinableAssociation;
                if (oj.Joinable.ConsumesAlias())
                {
                    if (oj.Subalias.Equals(alias))
                    {
                        return(result);
                    }
                    result++;
                }
            }

            return(-1);
        }
Example #19
0
        private static HashSet <string> GetDependsOn(OuterJoinableAssociation association)
        {
            if (SqlStringHelper.IsEmpty(association.On))
            {
                return(null);
            }

            var dependencies = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            foreach (Match match in aliasRegex.Matches(association.On.ToString()))
            {
                string alias = match.Value;
                if (string.Equals(alias, association.RHSAlias, StringComparison.OrdinalIgnoreCase))
                {
                    continue;
                }

                dependencies.Add(alias);
            }

            return(dependencies);
        }
        private void InitClassPersisters(IOuterJoinLoadable persister, IList associations)
        {
            int joins = associations.Count;

            lockModeArray = CreateLockModeArray(joins + 1, LockMode.None);

            classPersisters = new ILoadable[joins + 1];
            Owners          = new int[joins + 1];
            for (int i = 0; i < joins; i++)
            {
                OuterJoinableAssociation oj = ( OuterJoinableAssociation )associations[i];
                Persisters[i] = (ILoadable)oj.Joinable;
                Owners[i]     = ToOwner(oj, joins, oj.IsOneToOne);
            }
            classPersisters[joins] = persister;
            Owners[joins]          = -1;

            if (ArrayHelper.IsAllNegative(Owners))
            {
                Owners = null;
            }
        }
Example #21
0
        /// <summary>
        /// Add on association (one-to-one, many-to-one, or a collection) to a list
        /// of associations to be fetched by outerjoin
        /// </summary>
        private void AddAssociationToJoinTree(IAssociationType type, string[] aliasedLhsColumns, string alias,
                                              string path, string subPathAlias, int currentDepth, JoinType joinType)
        {
            IJoinable joinable = type.GetAssociatedJoinable(Factory);

            string subalias = GenerateTableAlias(associations.Count + 1, path, subPathAlias, joinable);
            var    qc       = joinable.IsCollection ? (IQueryableCollection)joinable : null;

            var assoc =
                new OuterJoinableAssociation(
                    type,
                    alias,
                    aliasedLhsColumns,
                    subalias,
                    joinType,
                    //for many-to-many with clause is applied with OuterJoinableAssociation created for entity persister so simply skip it here
                    qc?.IsManyToMany == true ? null : GetWithClause(path, subPathAlias),
                    Factory,
                    enabledFilters,
                    GetSelectMode(path));

            assoc.ValidateJoin(path);
            AddAssociation(assoc);

            int nextDepth = currentDepth + 1;

            if (qc == null)
            {
                IOuterJoinLoadable pjl = joinable as IOuterJoinLoadable;
                if (pjl != null)
                {
                    WalkEntityTree(pjl, subalias, path, nextDepth);
                }
            }
            else
            {
                WalkCollectionTree(qc, subalias, path, subPathAlias, nextDepth);
            }
        }
Example #22
0
        protected static string GetSelectFragment(OuterJoinableAssociation join, string entitySuffix, string collectionSuffix, OuterJoinableAssociation next = null)
        {
            switch (join.SelectMode)
            {
            case SelectMode.Undefined:
            case SelectMode.Fetch:
#pragma warning disable 618
                return(join.Joinable.SelectFragment(
                           next?.Joinable,
                           next?.RHSAlias,
                           join.RHSAlias,
                           entitySuffix,
                           collectionSuffix,
                           join.ShouldFetchCollectionPersister()));

#pragma warning restore 618

            case SelectMode.FetchLazyProperties:
                return(ReflectHelper.CastOrThrow <ISupportSelectModeJoinable>(join.Joinable, "fetch lazy propertie")
                       .SelectFragment(
                           next?.Joinable,
                           next?.RHSAlias,
                           join.RHSAlias,
                           entitySuffix,
                           collectionSuffix,
                           join.ShouldFetchCollectionPersister(),
                           true));

            case SelectMode.ChildFetch:
                return(ReflectHelper.CastOrThrow <ISupportSelectModeJoinable>(join.Joinable, "child fetch select mode").IdentifierSelectFragment(join.RHSAlias, entitySuffix));

            case SelectMode.JoinOnly:
                return(string.Empty);

            default:
                throw new ArgumentOutOfRangeException(nameof(join.SelectMode), $"{join.SelectMode} is unexpected.");
            }
        }
		public bool IsManyToManyWith(OuterJoinableAssociation other)
		{
			if (joinable.IsCollection)
			{
				IQueryableCollection persister = (IQueryableCollection) joinable;
				if (persister.IsManyToMany)
				{
					return persister.ElementType == other.JoinableType;
				}
			}
			return false;
		}
		/// <summary>
		///  Add on association (one-to-one or many-to-one) to a list of associations be fetched by outerjoin (if necessary)
		/// </summary>
		/// <param name="type"></param>
		/// <param name="aliasedForeignKeyColumns"></param>
		/// <param name="persister"></param>
		/// <param name="alias"></param>
		/// <param name="associations"></param>
		/// <param name="visitedPersisters"></param>
		/// <param name="path"></param>
		/// <param name="currentDepth"></param>
		/// <param name="joinType"></param>
		/// <param name="factory"></param>
		private void WalkAssociationTree(
			IAssociationType type,
			string[ ] aliasedForeignKeyColumns,
			IJoinable persister,
			string alias,
			IList associations,
			ISet visitedPersisters,
			string path,
			int currentDepth,
			JoinType joinType,
			ISessionFactoryImplementor factory )
		{
			IJoinable joinable = type.GetJoinable( factory );

			int maxFetchDepth = factory.MaximumFetchDepth;

			bool enabled = ( joinType == JoinType.InnerJoin ) || (
				( maxFetchDepth <= 0 || currentDepth < maxFetchDepth ) &&
				!visitedPersisters.Contains( joinable ) &&
				( !joinable.IsCollection || !ContainsCollectionPersister( associations ) )
				);

			if ( enabled )
			{
				visitedPersisters.Add( persister );
				OuterJoinableAssociation assoc = new OuterJoinableAssociation();
				associations.Add( assoc );

				// After adding to collection!!
				string subalias = GenerateTableAlias(
					joinable.Name,
					associations.Count,
					path,
					joinable.IsManyToMany );

				assoc.Joinable = joinable;
				assoc.TableName = joinable.TableName;
				assoc.PrimaryKeyColumns = type.GetReferencedColumns( factory );
				assoc.ForeignKeyColumns = aliasedForeignKeyColumns;
				assoc.Subalias = subalias;
				assoc.Owner = GetPosition( alias, associations );
				assoc.IsOneToOne = type.IsEntityType &&
					( (EntityType) type ).IsOneToOne &&
					!( (EntityType) type ).IsUniqueKeyReference;
				assoc.JoinType = joinType;

				if ( assoc.ForeignKeyColumns.Length != assoc.PrimaryKeyColumns.Length ||
					assoc.ForeignKeyColumns.Length == 0 )
				{
					throw new MappingException( string.Format( "Invalid join columns for association: {0}", path ) );
				}

				int nextDepth = currentDepth + 1;
				if ( !joinable.IsCollection )
				{
					if ( joinable is IOuterJoinLoadable )
					{
						WalkClassTree( (IOuterJoinLoadable) joinable, subalias, associations, visitedPersisters, path, nextDepth, factory );
					}
				}
				else
				{
					if ( joinable is IQueryableCollection )
					{
						WalkCollectionTree( (IQueryableCollection) joinable, subalias, associations, visitedPersisters, path, nextDepth, factory ) ;
					}
				}
			}
		}
		protected int ToOwner( OuterJoinableAssociation oj, int joins, bool dontIgnore )
		{
			if ( dontIgnore )
			{
				return oj.Owner == -1 ? joins : oj.Owner;  //TODO: UGLY AS SIN!
			}
			else
			{
				return -1;
			}
		}
Example #26
0
        /// <summary>
        ///  Add on association (one-to-one or many-to-one) to a list of associations be fetched by outerjoin (if necessary)
        /// </summary>
        /// <param name="type"></param>
        /// <param name="aliasedForeignKeyColumns"></param>
        /// <param name="persister"></param>
        /// <param name="alias"></param>
        /// <param name="associations"></param>
        /// <param name="visitedPersisters"></param>
        /// <param name="path"></param>
        /// <param name="currentDepth"></param>
        /// <param name="joinType"></param>
        /// <param name="factory"></param>
        private void WalkAssociationTree(
            IAssociationType type,
            string[] aliasedForeignKeyColumns,
            IJoinable persister,
            string alias,
            IList associations,
            ISet visitedPersisters,
            string path,
            int currentDepth,
            JoinType joinType,
            ISessionFactoryImplementor factory)
        {
            IJoinable joinable = type.GetJoinable(factory);

            int maxFetchDepth = factory.MaximumFetchDepth;

            bool enabled = (joinType == JoinType.InnerJoin) || (
                (maxFetchDepth <= 0 || currentDepth < maxFetchDepth) &&
                !visitedPersisters.Contains(joinable) &&
                (!joinable.IsCollection || !ContainsCollectionPersister(associations))
                );

            if (enabled)
            {
                visitedPersisters.Add(joinable);
                OuterJoinableAssociation assoc = new OuterJoinableAssociation();
                associations.Add(assoc);

                // After adding to collection!!
                string subalias = GenerateTableAlias(
                    joinable.Name,
                    associations.Count,
                    path,
                    joinable.IsManyToMany);

                assoc.Joinable          = joinable;
                assoc.TableName         = joinable.TableName;
                assoc.PrimaryKeyColumns = type.GetReferencedColumns(factory);
                assoc.ForeignKeyColumns = aliasedForeignKeyColumns;
                assoc.Subalias          = subalias;
                assoc.Owner             = GetPosition(alias, associations);
                assoc.IsOneToOne        = type.IsEntityType &&
                                          ((EntityType)type).IsOneToOne &&
                                          !((EntityType)type).IsUniqueKeyReference;
                assoc.JoinType = joinType;

                if (assoc.ForeignKeyColumns.Length != assoc.PrimaryKeyColumns.Length ||
                    assoc.ForeignKeyColumns.Length == 0)
                {
                    throw new MappingException(string.Format("Invalid join columns for association: {0}", path));
                }

                int nextDepth = currentDepth + 1;
                if (!joinable.IsCollection)
                {
                    if (joinable is IOuterJoinLoadable)
                    {
                        WalkClassTree((IOuterJoinLoadable)joinable, subalias, associations, visitedPersisters, path, nextDepth, factory);
                    }
                }
                else
                {
                    if (joinable is IQueryableCollection)
                    {
                        WalkCollectionTree((IQueryableCollection)joinable, subalias, associations, visitedPersisters, path, nextDepth, factory);
                    }
                }
            }
        }
Example #27
0
		/// <summary>
		/// Add on association (one-to-one, many-to-one, or a collection) to a list
		/// of associations to be fetched by outerjoin
		/// </summary>
		private void AddAssociationToJoinTree(IAssociationType type, string[] aliasedLhsColumns, string alias,
			string path, int currentDepth, JoinType joinType)
		{
			IJoinable joinable = type.GetAssociatedJoinable(Factory);

			string subalias = GenerateTableAlias(associations.Count + 1, path, joinable);

			OuterJoinableAssociation assoc =
				new OuterJoinableAssociation(type, alias, aliasedLhsColumns, subalias, joinType, GetWithClause(path), Factory, enabledFilters);
			assoc.ValidateJoin(path);
			AddAssociation(subalias, assoc);

			int nextDepth = currentDepth + 1;

			if (!joinable.IsCollection)
			{
				IOuterJoinLoadable pjl = joinable as IOuterJoinLoadable;
				if (pjl != null)
					WalkEntityTree(pjl, subalias, path, nextDepth);
			}
			else
			{
				IQueryableCollection qc = joinable as IQueryableCollection;
				if (qc != null)
					WalkCollectionTree(qc, subalias, path, nextDepth);
			}
		}
Example #28
0
 internal OuterJoinableAssociation InitAssociation(OuterJoinableAssociation association, string path)
 {
     association.EntityFetchLazyProperties = GetEntityFetchLazyProperties(path);
     return(association);
 }
Example #29
0
 protected static string GetSelectFragment(OuterJoinableAssociation join, string entitySuffix, string collectionSuffix, OuterJoinableAssociation next = null)
 {
     return(join.GetSelectFragment(entitySuffix, collectionSuffix, next));
 }
Example #30
0
 /// <summary>
 /// Adds an association
 /// </summary>
 private void AddAssociation(OuterJoinableAssociation association)
 {
     associations.Add(association);
 }
Example #31
0
        internal string GetSelectFragment(string entitySuffix, string collectionSuffix, OuterJoinableAssociation next)
        {
            switch (SelectMode)
            {
            case SelectMode.Undefined:
            case SelectMode.Fetch:
#pragma warning disable 618
                return(Joinable.SelectFragment(
                           next?.Joinable,
                           next?.RHSAlias,
                           RHSAlias,
                           entitySuffix,
                           collectionSuffix,
                           ShouldFetchCollectionPersister()));

#pragma warning restore 618

            case SelectMode.FetchLazyProperties:
#pragma warning disable 618
                return(ReflectHelper.CastOrThrow <ISupportSelectModeJoinable>(Joinable, "fetch lazy properties")
                       .SelectFragment(
                           next?.Joinable,
                           next?.RHSAlias,
                           RHSAlias,
                           entitySuffix,
                           collectionSuffix,
                           ShouldFetchCollectionPersister(),
                           true));

#pragma warning restore 618

            case SelectMode.FetchLazyPropertyGroup:
                return(ReflectHelper.CastOrThrow <ISupportLazyPropsJoinable>(Joinable, "fetch lazy property")
                       .SelectFragment(
                           next?.Joinable,
                           next?.RHSAlias,
                           RHSAlias,
                           collectionSuffix,
                           ShouldFetchCollectionPersister(),
                           new EntityLoadInfo(entitySuffix)
                {
                    LazyProperties = EntityFetchLazyProperties,
                    IncludeLazyProps = SelectMode == SelectMode.FetchLazyProperties,
                }));

            case SelectMode.ChildFetch:
                return(ReflectHelper.CastOrThrow <ISupportSelectModeJoinable>(Joinable, "child fetch select mode")
                       .IdentifierSelectFragment(RHSAlias, entitySuffix));

            case SelectMode.JoinOnly:
                return(string.Empty);

            default:
                throw new ArgumentOutOfRangeException(nameof(SelectMode), $"{SelectMode} is unexpected.");
            }
        }
Example #32
0
		/// <summary>
		/// Adds an association and extracts the aliases the association's 'with clause' is dependent on
		/// </summary>
		private void AddAssociation(string subalias, OuterJoinableAssociation association)
		{
			subalias = subalias.ToLower();

			var dependencies = new List<string>();
			var on = association.On.ToString();
			if (!String.IsNullOrEmpty(on))
			{
				foreach (Match match in aliasRegex.Matches(on))
				{
					string alias = match.Groups[1].Value;
					if (alias == subalias) continue;
					dependencies.Add(alias.ToLower());
				}
			}

			_dependentAliases.Add(new DependentAlias
			{
				Alias = subalias,
				DependsOn = dependencies.ToArray()
			});

			associations.Add(association);
		}
		/// <summary>
		/// Add on association (one-to-one, many-to-one, or a collection) to a list
		/// of associations to be fetched by outerjoin
		/// </summary>
		private void AddAssociationToJoinTree(
			IAssociationType type,
			string[] aliasedLhsColumns,
			string alias,
			string path,
			int currentDepth,
			JoinType joinType)
		{
			IJoinable joinable = type.GetAssociatedJoinable(Factory);

			string subalias = GenerateTableAlias(
				associations.Count + 1, //before adding to collection!
				path,
				joinable
				);

			OuterJoinableAssociation assoc = new OuterJoinableAssociation(
				type,
				alias,
				aliasedLhsColumns,
				subalias,
				joinType,
				Factory,
				enabledFilters
				);
			assoc.ValidateJoin(path);
			associations.Add(assoc);

			int nextDepth = currentDepth + 1;

			if (!joinable.IsCollection)
			{
				if (joinable is IOuterJoinLoadable)
				{
					WalkEntityTree(
						(IOuterJoinLoadable) joinable,
						subalias,
						path,
						nextDepth
						);
				}
			}
			else
			{
				if (joinable is IQueryableCollection)
				{
					WalkCollectionTree(
						(IQueryableCollection) joinable,
						subalias,
						path,
						nextDepth
						);
				}
			}
		}