예제 #1
0
        // detect cases when withClause is used on multiple tables or when join keys depend on subclass columns
        private static bool NeedsTableGroupJoin(IReadOnlyList <IJoin> joins, SqlString[] withClauseFragments, bool includeSubclasses)
        {
            bool hasWithClause = withClauseFragments.Any(x => SqlStringHelper.IsNotEmpty(x));

            //NH Specific: No alias processing (see hibernate JoinSequence.NeedsTableGroupJoin)
            if (joins.Count > 1 && hasWithClause)
            {
                return(true);
            }

            foreach (var join in joins)
            {
                var entityPersister = GetEntityPersister(join.Joinable);
                if (entityPersister?.HasSubclassJoins(includeSubclasses) != true)
                {
                    continue;
                }

                if (hasWithClause)
                {
                    return(true);
                }

                if (entityPersister.ColumnsDependOnSubclassJoins(join.RHSColumns))
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #2
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);
        }
예제 #3
0
 public OuterJoinableAssociation(IAssociationType joinableType, String lhsAlias, String[] lhsColumns, String rhsAlias,
                                 JoinType joinType, SqlString withClause, ISessionFactoryImplementor factory,
                                 IDictionary <string, IFilter> enabledFilters)
 {
     this.joinableType = joinableType;
     this.lhsAlias     = lhsAlias;
     this.lhsColumns   = lhsColumns;
     this.rhsAlias     = rhsAlias;
     this.joinType     = joinType;
     joinable          = joinableType.GetAssociatedJoinable(factory);
     rhsColumns        = JoinHelper.GetRHSColumnNames(joinableType, factory);
     on = new SqlString(joinableType.GetOnCondition(rhsAlias, factory, enabledFilters));
     if (SqlStringHelper.IsNotEmpty(withClause))
     {
         on = on.Append(" and ( ").Append(withClause).Append(" )");
     }
     this.enabledFilters = enabledFilters;             // needed later for many-to-many/filter application
 }
예제 #4
0
        private void AddJoinNodes(IRestrictableStatement query, JoinSequence join, FromElement fromElement, bool supportRootAlias)
        {
            JoinFragment joinFragment = join.ToJoinFragment(
                _walker.EnabledFilters,
                fromElement.UseFromFragment || fromElement.IsDereferencedBySuperclassOrSubclassProperty,
                fromElement.WithClauseFragment,
                fromElement.WithClauseJoinAlias,
                supportRootAlias ? join.RootAlias : string.Empty
                );

            SqlString frag      = joinFragment.ToFromFragmentString;
            SqlString whereFrag = joinFragment.ToWhereFragmentString;

            // If the from element represents a JOIN_FRAGMENT and it is
            // a theta-style join, convert its type from JOIN_FRAGMENT
            // to FROM_FRAGMENT
            if (fromElement.Type == HqlSqlWalker.JOIN_FRAGMENT &&
                (join.IsThetaStyle || SqlStringHelper.IsNotEmpty(whereFrag)))
            {
                fromElement.Type = HqlSqlWalker.FROM_FRAGMENT;
                fromElement.JoinSequence.SetUseThetaStyle(true);                   // this is used during SqlGenerator processing
            }

            // If there is a FROM fragment and the FROM element is an explicit, then add the from part.
            if (fromElement.UseFromFragment /*&& StringHelper.isNotEmpty( frag )*/)
            {
                SqlString fromFragment = ProcessFromFragment(frag, join).Trim();
                if (log.IsDebugEnabled())
                {
                    log.Debug("Using FROM fragment [{0}]", fromFragment);
                }

                ProcessDynamicFilterParameters(fromFragment, fromElement, _walker);
            }

            _syntheticAndFactory.AddWhereFragment(
                joinFragment,
                whereFrag,
                query,
                fromElement,
                _walker
                );
        }