private bool ProcessAsTableGroupJoin(bool includeAllSubclassJoins, SqlString[] withClauseFragments, JoinFragment joinFragment) { if (!NeedsTableGroupJoin(joins, withClauseFragments, includeAllSubclassJoins)) { return(false); } var first = joins[0]; string joinString = ANSIJoinFragment.GetJoinString(first.JoinType); joinFragment.AddFromFragmentString( new SqlString( joinString, " (", first.Joinable.TableName, " ", first.Alias )); foreach (var join in joins) { if (join != first) { joinFragment.AddJoin( join.Joinable.TableName, join.Alias, join.LHSColumns, JoinHelper.GetRHSColumnNames(join.AssociationType, factory), join.JoinType, SqlString.Empty); } AddSubclassJoins( joinFragment, join.Alias, join.Joinable, // TODO (from hibernate): Think about if this could be made always true // NH Specific: made always true (original check: join.JoinType == JoinType.InnerJoin) true, includeAllSubclassJoins ); } var tableGroupWithClause = GetTableGroupJoinWithClause(withClauseFragments, first); joinFragment.AddFromFragmentString(tableGroupWithClause); return(true); }
internal static bool ProcessAsTableGroupJoin(IReadOnlyList <IJoin> tableGroupJoinables, SqlString[] withClauseFragments, bool includeAllSubclassJoins, JoinFragment joinFragment, Func <string, bool> isSubclassIncluded, ISessionFactoryImplementor sessionFactoryImplementor) { if (!NeedsTableGroupJoin(tableGroupJoinables, withClauseFragments, includeAllSubclassJoins)) { return(false); } var first = tableGroupJoinables[0]; string joinString = ANSIJoinFragment.GetJoinString(first.JoinType); joinFragment.AddFromFragmentString( new SqlString( joinString, " (", first.Joinable.TableName, " ", first.Alias )); foreach (var join in tableGroupJoinables) { if (join != first) { joinFragment.AddJoin( join.Joinable.TableName, join.Alias, join.LHSColumns, JoinHelper.GetRHSColumnNames(join.AssociationType, sessionFactoryImplementor), join.JoinType, SqlString.Empty); } bool include = includeAllSubclassJoins && isSubclassIncluded(join.Alias); // TODO (from hibernate): Think about if this could be made always true // NH Specific: made always true (original check: join.JoinType == JoinType.InnerJoin) const bool innerJoin = true; joinFragment.AddJoins( join.Joinable.FromJoinFragment(join.Alias, innerJoin, include), join.Joinable.WhereJoinFragment(join.Alias, innerJoin, include)); } var withClause = GetTableGroupJoinWithClause(withClauseFragments, first, sessionFactoryImplementor); joinFragment.AddFromFragmentString(withClause); return(true); }
/// <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); }
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); }
/// <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); }