public QueryUnderConstruction FlattenAsPossible()

in Microsoft.Azure.Cosmos/src/Linq/QueryUnderConstruction.cs [220:286]


        public QueryUnderConstruction FlattenAsPossible()
        {
            // Flatten should be done when the current query can be translated without the need of using sub query
            // The cases that need to use sub query are: 
            //     1. Select clause appears after Distinct
            //     2. There are any operations after Take that is not a pure Select.
            //     3. There are nested Select, Where or OrderBy
            //     4. Group by clause appears after Select
            QueryUnderConstruction parentQuery = null;
            QueryUnderConstruction flattenQuery = null;
            bool seenSelect = false;
            bool seenAnyNonSelectOp = false;
            for (QueryUnderConstruction query = this; query != null; query = query.inputQuery)
            {
                foreach (Binding binding in query.FromParameters.GetBindings())
                {
                    if ((binding.ParameterDefinition != null) && (binding.ParameterDefinition is SqlSubqueryCollection))
                    {
                        flattenQuery = this;
                        break;
                    }
                }

                // In Select -> SelectMany cases, fromParameter substitution is not yet supported .
                // Therefore these are un-flattenable.
                if (query.inputQuery != null &&
                    (query.FromParameters.GetBindings().First().Parameter.Name == query.inputQuery.Alias.Name) &&
                    query.FromParameters.GetBindings().Any(b => b.ParameterDefinition != null))
                {
                    flattenQuery = this;
                    break;
                }

                // In case of Select/Order By -> Group by cases, the Select/Order By query should not be flattened and kept as a subquery
                if (((query.inputQuery?.selectClause != null) || (query.inputQuery?.orderByClause != null)) && (query.groupByClause != null))
                {
                    flattenQuery = this;
                    break;
                }

                if (flattenQuery != null) break;

                if (((query.topSpec != null || query.offsetSpec != null || query.limitSpec != null) && seenAnyNonSelectOp) ||
                    (query.selectClause != null && query.selectClause.HasDistinct && seenSelect))
                {
                    parentQuery.inputQuery = query.FlattenAsPossible();
                    flattenQuery = this;
                    break;
                }

                seenSelect = seenSelect || ((query.selectClause != null) && !query.selectClause.HasDistinct);
                seenAnyNonSelectOp |=
                    (query.whereClause != null) ||
                    (query.orderByClause != null) ||
                    (query.groupByClause != null) ||    
                    (query.topSpec != null) ||
                    (query.offsetSpec != null) ||
                    query.FromParameters.GetBindings().Any(b => b.ParameterDefinition != null) ||
                    ((query.selectClause != null) && (query.selectClause.HasDistinct || 
                    this.HasSelectAggregate()));
                parentQuery = query;
            }

            if (flattenQuery == null) flattenQuery = this.Flatten();

            return flattenQuery;
        }