public Join(ISessionFactoryImplementor factory, IAssociationType associationType, string alias, JoinType joinType, string[] lhsColumns) { this.associationType = associationType; this.joinable = associationType.GetAssociatedJoinable(factory); this.alias = alias; this.joinType = joinType; this.lhsColumns = lhsColumns; this.rhsColumns = lhsColumns.Length > 0 ? JoinHelper.GetRHSColumnNames(joinable, associationType) : Array.Empty <string>(); }
private SqlString GetTableGroupJoinWithClause(SqlString[] withClauseFragments, Join first) { SqlStringBuilder fromFragment = new SqlStringBuilder(); fromFragment.Add(")").Add(" on "); String[] lhsColumns = first.LHSColumns; var isAssociationJoin = lhsColumns.Length > 0; if (isAssociationJoin) { String rhsAlias = first.Alias; String[] rhsColumns = JoinHelper.GetRHSColumnNames(first.AssociationType, factory); for (int j = 0; j < lhsColumns.Length; j++) { fromFragment.Add(lhsColumns[j]); fromFragment.Add("="); fromFragment.Add(rhsAlias); fromFragment.Add("."); fromFragment.Add(rhsColumns[j]); if (j < lhsColumns.Length - 1) { fromFragment.Add(" and "); } } } for (var i = 0; i < withClauseFragments.Length; i++) { var withClause = withClauseFragments[i]; if (SqlStringHelper.IsEmpty(withClause)) { continue; } if (withClause.StartsWithCaseInsensitive(" and ")) { if (!isAssociationJoin) { withClause = withClause.Substring(4); } } else if (isAssociationJoin) { fromFragment.Add(" and "); } fromFragment.Add(withClause); } return(fromFragment.ToSqlString()); }
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); }
private static SqlString GetTableGroupJoinWithClause(SqlString[] withClauseFragments, IJoin first, ISessionFactoryImplementor factory) { SqlStringBuilder fromFragment = new SqlStringBuilder(); fromFragment.Add(")").Add(" on "); string[] lhsColumns = first.LHSColumns; var isAssociationJoin = lhsColumns.Length > 0; if (isAssociationJoin) { string rhsAlias = first.Alias; string[] rhsColumns = JoinHelper.GetRHSColumnNames(first.AssociationType, factory); fromFragment.Add(lhsColumns[0]).Add("=").Add(rhsAlias).Add(".").Add(rhsColumns[0]); for (int j = 1; j < lhsColumns.Length; j++) { fromFragment.Add(" and ").Add(lhsColumns[j]).Add("=").Add(rhsAlias).Add(".").Add(rhsColumns[j]); } } AppendWithClause(fromFragment, isAssociationJoin, withClauseFragments); return(fromFragment.ToSqlString()); }
internal JoinFragment ToJoinFragment( IDictionary <string, IFilter> enabledFilters, bool includeExtraJoins, SqlString withClauseFragment, string withClauseJoinAlias, string withRootAlias) { QueryJoinFragment joinFragment = new QueryJoinFragment(factory.Dialect, useThetaStyle); if (rootJoinable != null) { joinFragment.AddCrossJoin(rootJoinable.TableName, withRootAlias); string filterCondition = rootJoinable.FilterFragment(withRootAlias, enabledFilters); // JoinProcessor needs to know if the where clause fragment came from a dynamic filter or not so it // can put the where clause fragment in the right place in the SQL AST. 'hasFilterCondition' keeps track // of that fact. joinFragment.HasFilterCondition = joinFragment.AddCondition(filterCondition); if (includeExtraJoins) { //TODO: not quite sure about the full implications of this! AddExtraJoins(joinFragment, withRootAlias, rootJoinable, true); } } IJoinable last = rootJoinable; for (int i = 0; i < joins.Count; i++) { Join join = joins[i]; string on = join.AssociationType.GetOnCondition(join.Alias, factory, enabledFilters); SqlString condition = new SqlString(); if (last != null && IsManyToManyRoot(last) && ((IQueryableCollection)last).ElementType == join.AssociationType) { // the current join represents the join between a many-to-many association table // and its "target" table. Here we need to apply any additional filters // defined specifically on the many-to-many string manyToManyFilter = ((IQueryableCollection)last) .GetManyToManyFilterFragment(join.Alias, enabledFilters); condition = new SqlString("".Equals(manyToManyFilter) ? on : "".Equals(on) ? manyToManyFilter : on + " and " + manyToManyFilter); } else { // NH Different behavior : NH1179 and NH1293 // Apply filters in Many-To-One association var enabledForManyToOne = FilterHelper.GetEnabledForManyToOne(enabledFilters); condition = new SqlString(string.IsNullOrEmpty(on) && enabledForManyToOne.Count > 0 ? join.Joinable.FilterFragment(join.Alias, enabledForManyToOne) : on); } if (withClauseFragment != null) { if (join.Alias.Equals(withClauseJoinAlias)) { condition = condition.Append(" and ").Append(withClauseFragment); } } // NH: the variable "condition" have to be a SqlString because it may contains Parameter instances with BackTrack joinFragment.AddJoin( join.Joinable.TableName, join.Alias, join.LHSColumns, JoinHelper.GetRHSColumnNames(join.AssociationType, factory), join.JoinType, condition ); if (includeExtraJoins) { //TODO: not quite sure about the full implications of this! AddExtraJoins(joinFragment, join.Alias, join.Joinable, join.JoinType == JoinType.InnerJoin); } last = join.Joinable; } if (next != null) { joinFragment.AddFragment(next.ToJoinFragment(enabledFilters, includeExtraJoins)); } joinFragment.AddCondition(conditions.ToSqlString()); if (isFromPart) { joinFragment.ClearWherePart(); } return(joinFragment); }
internal JoinFragment ToJoinFragment( IDictionary <string, IFilter> enabledFilters, bool includeAllSubclassJoins, bool renderSubclassJoins, SqlString withClauseFragment) { QueryJoinFragment joinFragment = new QueryJoinFragment(factory.Dialect, useThetaStyle); if (rootJoinable != null) { joinFragment.AddCrossJoin(rootJoinable.TableName, rootAlias); string filterCondition = rootJoinable.FilterFragment(rootAlias, enabledFilters); // JoinProcessor needs to know if the where clause fragment came from a dynamic filter or not so it // can put the where clause fragment in the right place in the SQL AST. 'hasFilterCondition' keeps track // of that fact. joinFragment.HasFilterCondition = joinFragment.AddCondition(filterCondition); AddSubclassJoins(joinFragment, rootAlias, rootJoinable, true, includeAllSubclassJoins); } var withClauses = new SqlString[joins.Count]; IJoinable last = rootJoinable; for (int i = 0; i < joins.Count; i++) { Join join = joins[i]; withClauses[i] = GetWithClause(enabledFilters, ref withClauseFragment, join, last); last = join.Joinable; } if (rootJoinable == null && ProcessAsTableGroupJoin(includeAllSubclassJoins, withClauses, joinFragment)) { return(joinFragment); } for (int i = 0; i < joins.Count; i++) { Join join = joins[i]; // NH: the variable "condition" have to be a SqlString because it may contains Parameter instances with BackTrack joinFragment.AddJoin( join.Joinable.TableName, join.Alias, join.LHSColumns, JoinHelper.GetRHSColumnNames(join.AssociationType, factory), join.JoinType, withClauses[i] ); AddSubclassJoins(joinFragment, join.Alias, join.Joinable, join.JoinType == JoinType.InnerJoin, renderSubclassJoins); } if (next != null) { joinFragment.AddFragment(next.ToJoinFragment(enabledFilters, includeAllSubclassJoins)); } joinFragment.AddCondition(conditions.ToSqlString()); if (isFromPart) { joinFragment.ClearWherePart(); } return(joinFragment); }