EFIngresProvider/SqlGen/SqlGenerator/SqlGeneratorCommonVisitors.cs
/// <summary>
/// This is called from <see cref="VisitJoinExpression"/>.
///
/// This is responsible for maintaining the symbol table after visiting
/// a child of a join expression.
///
/// The child's sql statement may need to be completed.
///
/// The child's result could be one of
/// <list type="number">
/// <item>The same as the parent's - this is treated specially.</item>
/// <item>A sql select statement, which may need to be completed</item>
/// <item>An extent - just copy it to the from clause</item>
/// <item>Anything else (from a collection-valued expression) -
/// unnest and copy it.</item>
/// </list>
///
/// If the input was a Join, we need to create a new join symbol,
/// otherwise, we create a normal symbol.
///
/// We then call AddFromSymbol to add the AS clause, and update the symbol table.
///
///
///
/// If the child's result was the same as the parent's, we have to clean up
/// the list of symbols in the FromExtents list, since this contains symbols from
/// the children of both the parent and the child.
/// The happens when the child visited is a Join, and is the leftmost child of
/// the parent.
/// </summary>
/// <param name="fromExtentFragment"></param>
/// <param name="result"></param>
/// <param name="input"></param>
/// <param name="fromSymbolStart"></param>
This is called from .

This is responsible for maintaining the symbol table after visiting
a child of a join expression.

The child's sql statement may need to be completed.

The child's result could be one of

If the input was a Join, we need to create a new join symbol,
otherwise, we create a normal symbol.

We then call AddFromSymbol to add the AS clause, and update the symbol table.



If the child's result was the same as the parent's, we have to clean up
the list of symbols in the FromExtents list, since this contains symbols from
the children of both the parent and the child.
The happens when the child visited is a Join, and is the leftmost child of
the parent.
The same as the parent's - this is treated specially.A sql select statement, which may need to be completedAn extent - just copy it to the from clauseAnything else (from a collection-valued expression)
unnest and copy it.
This is called from . This is responsible for maintaining the symbol table after visiting a child of a join expression . The child ' s sql statement may need to be completed . The child ' s result could be one of If the input was a Join we need to create a new join symbol otherwise we create a normal symbol . We then call AddFromSymbol to add the AS clause and update the symbol table . If the child ' s result was the same as the parent ' s we have to clean up the list of symbols in the FromExtents list since this contains symbols from the children of both the parent and the child . The happens when the child visited is a Join and is the leftmost child of the parent . The same as the parent ' s - this is treated specially . A sql select statement which may need to be completedAn extent - just copy it to the from clauseAnything else ( from a collection - valued expression ) unnest and copy it .
private void ProcessJoinInputResult(ISqlFragment fromExtentFragment, SqlSelectStatement result, DbExpressionBinding input, int fromSymbolStart)
        {
            Symbol fromSymbol = null;
            if (result != fromExtentFragment)
            {
                SqlSelectStatement sqlSelectStatement = fromExtentFragment as SqlSelectStatement;
                if (sqlSelectStatement != null)
                {
                    if (sqlSelectStatement.Select.IsEmpty)
                    {
                        List<Symbol> columns = AddDefaultColumns(sqlSelectStatement);
                        if (IsJoinExpression(input.Expression)
                            || IsApplyExpression(input.Expression))
                        {
                            List<Symbol> extents = sqlSelectStatement.FromExtents;
                            JoinSymbol newJoinSymbol = new JoinSymbol(input.VariableName, input.VariableType, extents);
                            newJoinSymbol.IsNestedJoin = true;
                            newJoinSymbol.ColumnList = columns;
                            fromSymbol = newJoinSymbol;
                        }
                        else
                        {
                            JoinSymbol oldJoinSymbol = sqlSelectStatement.FromExtents[0] as JoinSymbol;
                            if (oldJoinSymbol != null)
                            {
                                JoinSymbol newJoinSymbol = new JoinSymbol(input.VariableName, input.VariableType, oldJoinSymbol.ExtentList);
                                newJoinSymbol.IsNestedJoin = true;
                                newJoinSymbol.ColumnList = columns;
                                newJoinSymbol.FlattenedExtentList = oldJoinSymbol.FlattenedExtentList;
                                fromSymbol = newJoinSymbol;
                            }
                            else if (sqlSelectStatement.FromExtents[0].OutputColumnsRenamed)
                            {
                                fromSymbol = new Symbol(input.VariableName, input.VariableType, sqlSelectStatement.FromExtents[0].Columns);
                            }
                        }
                    }
                    else if (sqlSelectStatement.OutputColumnsRenamed)
                    {
                        fromSymbol = new Symbol(input.VariableName, input.VariableType, sqlSelectStatement.OutputColumns);
                    }
                    result.From.Append(" (");
                    result.From.Append(sqlSelectStatement);
                    result.From.Append(" )");
                }
                else if (input.Expression is DbScanExpression)
                {
                    result.From.Append(fromExtentFragment);
                }
                else 
                {
                    WrapNonQueryExtent(result, fromExtentFragment, input.Expression.ExpressionKind);
                }
                if (fromSymbol == null) 
                {
                    fromSymbol = new Symbol(input.VariableName, input.VariableType);
                }
                AddFromSymbol(result, input.VariableName, fromSymbol);
                result.AllJoinExtents.Add(fromSymbol);
            }
            else 
            {
                List<Symbol> extents = new List<Symbol>();
                 We cannot call extents.AddRange, since the is no simple way to
                 get the range of symbols fromSymbolStart..result.FromExtents.Count
                 from result.FromExtents.
                 We copy these symbols to create the JoinSymbol later.
                for (int i = fromSymbolStart; i < result.FromExtents.Count; ++i)
                {
                    extents.Add(result.FromExtents[i]);
                }
                result.FromExtents.RemoveRange(fromSymbolStart, result.FromExtents.Count - fromSymbolStart);
                fromSymbol = new JoinSymbol(input.VariableName, input.VariableType, extents);
                result.FromExtents.Add(fromSymbol);
                 this Join Symbol does not have its own select statement, so we
                 do not set IsNestedJoin
                 We do not call AddFromSymbol(), since we do not want to add
                 "AS alias" to the FROM clause- it has been done when the extent was added earlier.
                symbolTable.Add(input.VariableName, fromSymbol);
            }
        }
private void ProcessJoinInputResult ( ISqlFragment fromExtentFragment , SqlSelectStatement result , DbExpressionBinding input , int fromSymbolStart ) { Symbol fromSymbol = null ; if ( result != fromExtentFragment ) { SqlSelectStatement sqlSelectStatement = fromExtentFragment as SqlSelectStatement ; if ( sqlSelectStatement != null ) { if ( sqlSelectStatement . Select . IsEmpty ) { List < Symbol > columns = AddDefaultColumns ( sqlSelectStatement ) ; if ( IsJoinExpression ( input . Expression ) || IsApplyExpression ( input . Expression ) ) { List < Symbol > extents = sqlSelectStatement . FromExtents ; JoinSymbol newJoinSymbol = new JoinSymbol ( input . VariableName , input . VariableType , extents ) ; newJoinSymbol . IsNestedJoin = true ; newJoinSymbol . ColumnList = columns ; fromSymbol = newJoinSymbol ; } else { JoinSymbol oldJoinSymbol = sqlSelectStatement . FromExtents [ 0 ] as JoinSymbol ; if ( oldJoinSymbol != null ) { JoinSymbol newJoinSymbol = new JoinSymbol ( input . VariableName , input . VariableType , oldJoinSymbol . ExtentList ) ; newJoinSymbol . IsNestedJoin = true ; newJoinSymbol . ColumnList = columns ; newJoinSymbol . FlattenedExtentList = oldJoinSymbol . FlattenedExtentList ; fromSymbol = newJoinSymbol ; } else if ( sqlSelectStatement . FromExtents [ 0 ] . OutputColumnsRenamed ) { fromSymbol = new Symbol ( input . VariableName , input . VariableType , sqlSelectStatement . FromExtents [ 0 ] . Columns ) ; } } } else if ( sqlSelectStatement . OutputColumnsRenamed ) { fromSymbol = new Symbol ( input . VariableName , input . VariableType , sqlSelectStatement . OutputColumns ) ; } result . From . Append ( " " ) ; result . From . Append ( sqlSelectStatement ) ; result . From . Append ( " " ) ; } else if ( input . Expression is DbScanExpression ) { result . From . Append ( fromExtentFragment ) ; } else { WrapNonQueryExtent ( result , fromExtentFragment , input . Expression . ExpressionKind ) ; } if ( fromSymbol == null ) { fromSymbol = new Symbol ( input . VariableName , input . VariableType ) ; } AddFromSymbol ( result , input . VariableName , fromSymbol ) ; result . AllJoinExtents . Add ( fromSymbol ) ; } else { List < Symbol > extents = new List < Symbol > ( ) ; for ( int i = fromSymbolStart ; i < result . FromExtents . Count ; ++ i ) { extents . Add ( result . FromExtents [ i ] ) ; } result . FromExtents . RemoveRange ( fromSymbolStart , result . FromExtents . Count - fromSymbolStart ) ; fromSymbol = new JoinSymbol ( input . VariableName , input . VariableType , extents ) ; result . FromExtents . Add ( fromSymbol ) ; symbolTable . Add ( input . VariableName , fromSymbol ) ; } }
This is called from .
This is called from .
// The child has its own select statement, and is not reusing // our select statement. // This should look a lot like VisitInputExpression(). // this is a copy of the code in CreateNewSelectStatement. // if the oldStatement has a join as its input, ... // clone the join symbol, so that we "reuse" the // join symbol.  Normally, we create a new symbol - see the next block // of code. // Note: sqlSelectStatement.FromExtents will not do, since it might // just be an alias of joinSymbol, and we want an actual JoinSymbol. // This indicates that the sqlSelectStatement is a blocking scope // i.e. it hides/renames extent columns // bracket it // i.e. not a join symbol // result == fromExtentFragment.  The child extents have been merged into the parent's. // we are adding extents to the current sql statement via flattening. // We are replacing the child's extents with a single Join symbol. // The child's extents are all those following the index fromSymbolStart. // // We cannot call extents.AddRange, since the is no simple way to // get the range of symbols fromSymbolStart..result.FromExtents.Count // from result.FromExtents. // We copy these symbols to create the JoinSymbol later. // this Join Symbol does not have its own select statement, so we // do not set IsNestedJoin // We do not call AddFromSymbol(), since we do not want to add // "AS alias" to the FROM clause- it has been done when the extent was added earlier.
fromExtentFragment
ISqlFragment
None
result
SqlSelectStatement
None
input
DbExpressionBinding
None
fromSymbolStart
int
None