Esempio n. 1
0
        protected override BoundRelation RewriteGroupByAndAggregationRelation(BoundGroupByAndAggregationRelation node)
        {
            var aggregates = RemoveUnusedSlots(node.Aggregates, a => a.Output);

            node = node.Update(node.Input, node.Groups, aggregates);

            _recorder.Record(node.Aggregates);
            _recorder.Record(node.Groups);

            return(base.RewriteGroupByAndAggregationRelation(node));
        }
Esempio n. 2
0
        protected override BoundRelation RewriteGroupByAndAggregationRelation(BoundGroupByAndAggregationRelation node)
        {
            var input = RewriteRelation(node.Input);

            if (node.Aggregates.IsEmpty)
            {
                return(new BoundSortRelation(true, input, node.Groups));
            }

            var sortedInput = node.Groups.Any()
                ? new BoundSortRelation(false, input, node.Groups)
                : input;

            return(new BoundStreamAggregatesRelation(sortedInput, node.Groups, node.Aggregates));
        }
Esempio n. 3
0
        protected override BoundExpression RewriteSingleRowSubselect(BoundSingleRowSubselect node)
        {
            var relation = RewriteRelation(node.Relation);

            var factory = node.Value.Factory;

            // TODO: If the query is guranteed to return a single, e.g. if it is a aggregated but not grouped,
            //       we should not emit the additional aggregation and assertion.

            // 1. We need to know whether it returns more then one row.

            var valueSlot   = node.Value;
            var anyOutput   = factory.CreateTemporary(valueSlot.Type);
            var countOutput = factory.CreateTemporary(typeof(int));

            var anyAggregateSymbol = BuiltInAggregates.Any;
            var anyAggregatable    = anyAggregateSymbol.Definition.CreateAggregatable(valueSlot.Type);

            var countAggregatedSymbol = BuiltInAggregates.Count;
            var countAggregatable     = countAggregatedSymbol.Definition.CreateAggregatable(typeof(int));

            var aggregates = new[]
            {
                new BoundAggregatedValue(anyOutput, anyAggregateSymbol, anyAggregatable, Expression.Value(valueSlot)),
                new BoundAggregatedValue(countOutput, countAggregatedSymbol, countAggregatable, Expression.Literal(0))
            };

            var aggregation = new BoundGroupByAndAggregationRelation(relation, Enumerable.Empty <BoundComparedValue>(), aggregates);

            // 2. Now we can assert that the number of rows returned is at most one.

            var condition = Expression.LessThan(Expression.Value(countOutput), Expression.Literal(1));

            var message        = Resources.SubqueryReturnedMoreThanRow;
            var assertRelation = new BoundAssertRelation(aggregation, condition, message);

            var subquery   = new Subquery(SubqueryKind.Subselect, anyOutput, assertRelation, CurrentPassthru);
            var subqueries = _subqueryStack.Peek();

            subqueries.Add(subquery);

            return(Expression.Value(anyOutput));
        }
 private static CardinalityEstimate EstimateGroupByAndAggregationRelation(BoundGroupByAndAggregationRelation relation)
 {
     return(CardinalityEstimate.Unknown);
 }
Esempio n. 5
0
        private BoundRelation PushOverGroupByAndAggregation(BoundFilterRelation node, BoundGroupByAndAggregationRelation input)
        {
            // TODO: This may not be that easy.
            //
            // For example this condition can be pushed:
            //
            //      GroupCol = Value
            //
            //  while this can't:
            //
            //      GroupCol = Value OR Func(const) = const
            //
            // Formally, a predicate can be pushed over an aggregate if and only if all disjuncts of the predicate's
            // CNF do reference at least one grouping column.

            BoundExpression remainder = null;
            BoundExpression pushed    = null;

            foreach (var conjunction in Expression.SplitConjunctions(node.Condition))
            {
                if (conjunction.DependsOnAny(input.GetDefinedValues()))
                {
                    remainder = Expression.And(remainder, conjunction);
                }
                else
                {
                    pushed = Expression.And(pushed, conjunction);
                }
            }

            var newInputInput = pushed == null
                ? input.Input
                : new BoundFilterRelation(input.Input, pushed);

            var newInput = RewriteRelation(input.Update(newInputInput, input.Groups, input.Aggregates));

            var newNode = remainder == null
                ? newInput
                : new BoundFilterRelation(newInput, remainder);

            return(newNode);
        }