예제 #1
0
        public override ulong LogicAggCE(LogicAgg node)
        {
            ulong card = 1;

            if (node.groupby_ is null)
            {
                card = 1;
            }
            else
            {
                ulong distinct = 1;
                foreach (var v in node.groupby_)
                {
                    ulong ndistinct = 1;
                    if (v is ColExpr vc && vc.tabRef_ is BaseTableRef bvc)
                    {
                        var stat = Catalog.sysstat_.GetColumnStat(bvc.relname_, vc.colName_);
                        ndistinct = stat.n_distinct_;
                    }

                    // stop accumulating in case of overflow
                    if (distinct * ndistinct > distinct)
                    {
                        distinct *= ndistinct;
                    }
                }

                card = (ulong)distinct;
            }

            // it won't go beyond the number of output rows
            return(Math.Min(card, node.child_().Card()));
        }
예제 #2
0
        public override CGroupMember Apply(CGroupMember expr)
        {
            // for manually binding the expression
            void manualbindexpr(Expr e)
            {
                e.bounded_ = true;
                e.type_    = new BoolType();
            }

            // for transformaing original having according to the new agg func
            BinExpr processhaving(Expr e, Dictionary <Expr, Expr> dict)
            {
                var be = e as BinExpr;

                Debug.Assert(be != null);
                bool        isreplace = false;
                List <Expr> children  = new List <Expr>();

                foreach (var child in be.children_)
                {
                    if (dict.ContainsKey(child))
                    {
                        children.Add(dict[child]);
                        isreplace = true;
                    }
                    else
                    {
                        children.Add(child);
                    }
                }
                Debug.Assert(isreplace);
                return(new BinExpr(children[0], children[1], be.op_));
            }

            LogicAgg origAggNode = (expr.logic_ as LogicAgg);
            var      childNode   = (origAggNode.child_() as LogicMemoRef).Deref <LogicNode>();

            var groupby = origAggNode.groupby_?.CloneList();
            var having  = origAggNode.having_?.Clone();

            // process the aggregation functions
            origAggNode.GenerateAggrFns(false);

            List <AggFunc> aggfns = new List <AggFunc>();

            origAggNode.aggrFns_.ForEach(x => aggfns.Add(x.Clone() as AggFunc));
            // need to make aggrFns_ back to null list
            origAggNode.aggrFns_ = new List <AggFunc>();

            var globalfns = new List <Expr>();
            var localfns  = new List <Expr>();

            // record the processed aggregate functions
            var derivedAggFuncDict = new Dictionary <Expr, Expr>();

            foreach (var func in aggfns)
            {
                Expr processed = func.SplitAgg();
                // if splitagg is returning null, end the transformation process
                if (processed is null)
                {
                    return(expr);
                }

                // force the id to be equal.
                processed._ = func._;

                globalfns.Add(processed);
                derivedAggFuncDict.Add(func, processed);
            }

            var local = new LogicAgg(childNode, groupby, localfns, null);

            local.isLocal_ = true;

            // having is placed on the global agg and the agg func need to be processed
            var newhaving = having;

            if (having != null)
            {
                newhaving = processhaving(having, derivedAggFuncDict);
                manualbindexpr(newhaving);
            }

            // assuming having is an expression involving agg func,
            // it is only placed on the global agg
            var global = new LogicAgg(local, groupby, globalfns, newhaving);

            global.isDerived_ = true;
            global.Overridesign(origAggNode);
            global.deriveddict_ = derivedAggFuncDict;

            return(new CGroupMember(global, expr.group_));
        }