EFIngresProvider/SqlGen/SqlGenerator/SqlGeneratorCommonVisitors.cs
/// <summary>
/// This handles the processing of join expressions.
/// The extents on a left spine are flattened, while joins
/// not on the left spine give rise to new nested sub queries.
///
/// Joins work differently from the rest of the visiting, in that
/// the parent (i.e. the join node) creates the SqlSelectStatement
/// for the children to use.
///
/// The "parameter" IsInJoinContext indicates whether a child extent should
/// add its stuff to the existing SqlSelectStatement, or create a new SqlSelectStatement
/// By passing true, we ask the children to add themselves to the parent join,
/// by passing false, we ask the children to create new Select statements for
/// themselves.
///
/// This method is called from <see cref="Visit(DbApplyExpression)"/> and
/// <see cref="Visit(DbJoinExpression)"/>.
/// </summary>
/// <param name="inputs"></param>
/// <param name="joinKind"></param>
/// <param name="joinString"></param>
/// <param name="joinCondition"></param>
/// <returns> A <see cref="SqlSelectStatement"/></returns>
This handles the processing of join expressions.
The extents on a left spine are flattened, while joins
not on the left spine give rise to new nested sub queries.

Joins work differently from the rest of the visiting, in that
the parent  creates the SqlSelectStatement
for the children to use.

The "parameter" IsInJoinContext indicates whether a child extent should
add its stuff to the existing SqlSelectStatement, or create a new SqlSelectStatement
By passing true, we ask the children to add themselves to the parent join,
by passing false, we ask the children to create new Select statements for
themselves.

This method is called from  and
.
This handles the processing of join expressions . The extents on a left spine are flattened while joins not on the left spine give rise to new nested sub queries . Joins work differently from the rest of the visiting in that the parent creates the SqlSelectStatement for the children to use . The " parameter " IsInJoinContext indicates whether a child extent should add its stuff to the existing SqlSelectStatement or create a new SqlSelectStatement By passing true we ask the children to add themselves to the parent join by passing false we ask the children to create new Select statements for themselves . This method is called from and .
private ISqlFragment VisitJoinExpression(IList<DbExpressionBinding> inputs, DbExpressionKind joinKind, string joinString, DbExpression joinCondition)
        {
            if (!IsParentAJoin)
            {
                selectStatementStack.Push(new SqlSelectStatement { AllJoinExtents = new List<Symbol>() });
            }
            var result = CurrentSelectStatement;
            symbolTable.EnterScope();
            var separator = "";
            var isLeftMostInput = true;
            var inputCount = inputs.Count;
            foreach (var input in Enumerable.Range(0, inputs.Count).Select(x => inputs[x]))
            {
                if (separator.Length != 0)
                {
                    result.From.AppendLine();
                }
                result.From.Append(separator + " ");
                var needsJoinContext = input.Expression.ExpressionKind == DbExpressionKind.Scan ||
                                       (isLeftMostInput && IsApplyOrJoinExpression(input.Expression));
                isParentAJoinStack.Push(needsJoinContext ? true : false);
                var fromSymbolStart = result.FromExtents.Count;
                var fromExtentFragment = input.Expression.Accept(this);
                isParentAJoinStack.Pop();
                ProcessJoinInputResult(fromExtentFragment, result, input, fromSymbolStart);
                separator = joinString;
                isLeftMostInput = false;
            }
            switch (joinKind)
            {
                case DbExpressionKind.FullOuterJoin:
                case DbExpressionKind.InnerJoin:
                case DbExpressionKind.LeftOuterJoin:
                    result.From.Append(" on ");
                    isParentAJoinStack.Push(false);
                    result.From.Append(joinCondition.Accept(this));
                    isParentAJoinStack.Pop();
                    break;
            }
            symbolTable.ExitScope();
            if (!IsParentAJoin)
            {
                selectStatementStack.Pop();
            }
            return result;
        }
private ISqlFragment VisitJoinExpression ( IList < DbExpressionBinding > inputs , DbExpressionKind joinKind , string joinString , DbExpression joinCondition ) { if ( ! IsParentAJoin ) { selectStatementStack . Push ( new SqlSelectStatement { AllJoinExtents = new List < Symbol > ( ) } ) ; } var result = CurrentSelectStatement ; symbolTable . EnterScope ( ) ; var separator = " " ; var isLeftMostInput = true ; var inputCount = inputs . Count ; foreach ( var input in Enumerable . Range ( 0 , inputs . Count ) . Select ( x => inputs [ x ] ) ) { if ( separator . Length != 0 ) { result . From . AppendLine ( ) ; } result . From . Append ( separator + " " ) ; var needsJoinContext = input . Expression . ExpressionKind == DbExpressionKind . Scan || ( isLeftMostInput && IsApplyOrJoinExpression ( input . Expression ) ) ; isParentAJoinStack . Push ( needsJoinContext ? true : false ) ; var fromSymbolStart = result . FromExtents . Count ; var fromExtentFragment = input . Expression . Accept ( this ) ; isParentAJoinStack . Pop ( ) ; ProcessJoinInputResult ( fromExtentFragment , result , input , fromSymbolStart ) ; separator = joinString ; isLeftMostInput = false ; } switch ( joinKind ) { case DbExpressionKind . FullOuterJoin : case DbExpressionKind . InnerJoin : case DbExpressionKind . LeftOuterJoin : result . From . Append ( " " ) ; isParentAJoinStack . Push ( false ) ; result . From . Append ( joinCondition . Accept ( this ) ) ; isParentAJoinStack . Pop ( ) ; break ; } symbolTable . ExitScope ( ) ; if ( ! IsParentAJoin ) { selectStatementStack . Pop ( ) ; } return result ; }
This handles the processing of join expressions.
This handles the processing of join expressions .
// If the parent is not a join( or says that it is not), // we should create a new SqlSelectStatement. // otherwise, we add our child extents to the parent's FROM clause. // Process each of the inputs, and then the joinCondition if it exists. // It would be nice if we could call VisitInputExpression - that would // avoid some code duplication // but the Join postprocessing is messy and prevents this reuse. // Change this if other conditions are required // to force the child to produce a nested SqlStatement. // if the child reuses our select statement, it will append the from // symbols to our FromExtents list.  So, we need to remember the // start of the child's entries. // Visit the on clause/join condition.
None
inputs
IList<DbExpressionBinding>
None
joinKind
DbExpressionKind
None
joinString
string
None
joinCondition
DbExpression
None