Beispiel #1
0
        private static IEnumerable <CosmosElement> ProjectOnGroupings(
            IEnumerable <IGrouping <GroupByKey, CosmosElement> > groupings,
            SqlSelectClause sqlSelectClause)
        {
            foreach (IGrouping <GroupByKey, CosmosElement> grouping in groupings)
            {
                IEnumerable <CosmosElement> dataSource = grouping;
                if (AggregateProjectionDector.HasAggregate(sqlSelectClause.SelectSpec))
                {
                    // If there is an aggregate then we need to just project out the one document
                    // But we need to transform the query to first evaluate the aggregate on all the documents
                    AggregateProjectionTransformer aggregateProjectionTransformer = new AggregateProjectionTransformer(dataSource);
                    SqlSelectSpec transformedSpec = aggregateProjectionTransformer
                                                    .TransformAggregatesInProjection(sqlSelectClause.SelectSpec);
                    CosmosElement aggregationResult = transformedSpec.Accept(
                        Projector.Singleton,
                        dataSource.FirstOrDefault());
                    if (aggregationResult != null)
                    {
                        dataSource = new CosmosElement[] { aggregationResult };
                    }
                    else
                    {
                        dataSource = Array.Empty <CosmosElement>();
                    }
                }
                else
                {
                    dataSource = dataSource
                                 .Select(element => sqlSelectClause.SelectSpec.Accept(
                                             Projector.Singleton,
                                             element))
                                 .Where(projection => projection != Undefined);
                }

                if (dataSource.Any())
                {
                    yield return(dataSource.First());
                }
            }
        }
Beispiel #2
0
        public static IEnumerable <CosmosElement> ExecuteQuery(
            IEnumerable <CosmosElement> dataSource,
            SqlQuery sqlQuery,
            IReadOnlyDictionary <string, PartitionKeyRange> ridToPartitionKeyRange = null)
        {
            if (dataSource == null)
            {
                throw new ArgumentNullException($"{nameof(dataSource)} must not be null.");
            }

            if (sqlQuery == null)
            {
                throw new ArgumentNullException($"{nameof(sqlQuery)} must not be null.");
            }

            PerformStaticAnalysis(sqlQuery);

            if (ridToPartitionKeyRange == null)
            {
                ridToPartitionKeyRange = SinglePartitionRidToPartitionKeyRange.Value;
            }

            // From clause binds the data for the rest of the pipeline
            if (sqlQuery.FromClause != null)
            {
                dataSource = ExecuteFromClause(
                    dataSource,
                    sqlQuery.FromClause);
            }
            else
            {
                dataSource = NoFromClauseDataSource;
            }

            // We execute the filter here to reduce the data set as soon as possible.
            if (sqlQuery.WhereClause != null)
            {
                dataSource = ExecuteWhereClause(
                    dataSource,
                    sqlQuery.WhereClause);
            }

            // We sort before the projection,
            // since the projection might remove the order by items.
            if (sqlQuery.OrderByClause != null)
            {
                dataSource = ExecuteOrderByClause(
                    dataSource,
                    sqlQuery.OrderByClause,
                    ridToPartitionKeyRange);
            }
            else
            {
                // Even for non order by queries we need to order by partition key ranges and document ids
                dataSource = ExecuteCrossPartitionOrdering(
                    dataSource,
                    ridToPartitionKeyRange);
            }

            IEnumerable <IGrouping <GroupByKey, CosmosElement> > groupings;

            // We need to create the groupings at this point for the rest of the pipeline
            if (sqlQuery.GroupByClause != null)
            {
                groupings = ExecuteGroupByClause(
                    dataSource,
                    sqlQuery.GroupByClause);
            }
            else
            {
                if (AggregateProjectionDector.HasAggregate(sqlQuery.SelectClause.SelectSpec))
                {
                    groupings = CreateOneGroupingForWholeCollection(dataSource);
                }
                else
                {
                    groupings = CreateOneGroupingForEachDocument(dataSource);
                }
            }

            // We finally project out the needed columns and remove all binding artifacts
            dataSource = ExecuteSelectClause(
                groupings,
                sqlQuery.SelectClause);

            // Offset limit just performs skip take
            if (sqlQuery.OffsetLimitClause != null)
            {
                dataSource = ExecuteOffsetLimitClause(dataSource, sqlQuery.OffsetLimitClause);
            }

            return(dataSource);
        }