コード例 #1
0
 // <summary>
 // Registers the group aggregate var with the group aggregate var info manager
 // </summary>
 public override void Visit(GroupByIntoOp op, Node n)
 {
     VisitGroupByOp(op, n);
     foreach (var child in n.Child3.Children)
     {
         var groupAggregateVar = ((VarDefOp)child.Op).Var;
         GroupAggregateVarRefInfo groupAggregateVarRefInfo;
         // If the group by is over a group, it may be already tracked as referencing a group var
         // An optimization would be to separately track this groupAggregateVar too, for the cases when the aggregate can
         // not be pushed to the group by node over which this one is defined but can be propagated to this group by node.
         if (!_groupAggregateVarInfoManager.TryGetReferencedGroupAggregateVarInfo(groupAggregateVar, out groupAggregateVarRefInfo))
         {
             _groupAggregateVarInfoManager.Add(
                 groupAggregateVar, new GroupAggregateVarInfo(n, groupAggregateVar),
                 _command.CreateNode(_command.CreateVarRefOp(groupAggregateVar)), false);
         }
     }
 }
        private Node VisitCollect(Node n)
        {
            //Make sure the only children are projects over unnest
            var currentNode         = n.Child0;
            var constantDefinitions = new Dictionary <Var, Node>();

            while (currentNode.Child0.Op.OpType
                   == OpType.Project)
            {
                currentNode = currentNode.Child0;
                //Visit the VarDefListOp child
                if (VisitDefault(currentNode.Child1) == null)
                {
                    return(null);
                }
                foreach (var definitionNode in currentNode.Child1.Children)
                {
                    if (IsConstant(definitionNode.Child0))
                    {
                        constantDefinitions.Add(((VarDefOp)definitionNode.Op).Var, definitionNode.Child0);
                    }
                }
            }

            if (currentNode.Child0.Op.OpType
                != OpType.Unnest)
            {
                return(null);
            }

            // Handle the unnest
            var unnestOp = (UnnestOp)currentNode.Child0.Op;
            GroupAggregateVarRefInfo groupAggregateVarRefInfo;

            if (_groupAggregateVarInfoManager.TryGetReferencedGroupAggregateVarInfo(unnestOp.Var, out groupAggregateVarRefInfo))
            {
                if (_targetGroupAggregateVarInfo == null)
                {
                    _targetGroupAggregateVarInfo = groupAggregateVarRefInfo.GroupAggregateVarInfo;
                }
                else if (_targetGroupAggregateVarInfo != groupAggregateVarRefInfo.GroupAggregateVarInfo)
                {
                    return(null);
                }
                if (!_isUnnested)
                {
                    return(null);
                }
            }
            else
            {
                return(null);
            }

            var physicalProjectOp = (PhysicalProjectOp)n.Child0.Op;

            PlanCompiler.Assert(physicalProjectOp.Outputs.Count == 1, "Physical project should only have one output at this stage");
            var outputVar = physicalProjectOp.Outputs[0];

            var computationTemplate = TranslateOverGroupAggregateVar(outputVar, null);

            if (computationTemplate != null)
            {
                _isUnnested = true;
                return(computationTemplate);
            }

            Node constantDefinitionNode;

            if (constantDefinitions.TryGetValue(outputVar, out constantDefinitionNode))
            {
                _isUnnested = true;
                return(constantDefinitionNode);
            }
            return(null);
        }