Esempio n. 1
0
        public override bool Appliable(CGroupMember expr)
        {
            LogicJoin a_bc = expr.logic_ as LogicJoin;

            if (a_bc is null || !a_bc.IsInnerJoin())
            {
                return(false);
            }

            var bc       = (a_bc.rchild_() as LogicMemoRef).Deref();
            var bcfilter = bc.filter_;

            if (bc is LogicJoin bcj)
            {
                if (!bcj.IsInnerJoin())
                {
                    return(false);
                }

                // we only reject cases that logically impossible to apply
                // association rule, but leave anything may generate worse
                // plan (say catersisan joins) to apply stage.
                return(true);
            }
            return(false);
        }
Esempio n. 2
0
        // classic formula is:
        //   A X B => |A|*|B|/max(dA, dB) where dA,dB are distinct values of joining columns
        // This however does not consider join key distribution. In SQL Server 2014, it introduced
        // histogram join to better the estimation.
        //
        public override ulong LogicJoinCE(LogicJoin node)
        {
            ulong getDistinct(Expr key)
            {
                if (key is ColExpr col)
                {
                    var tr = col.tabRef_;

                    if (tr is FromQueryRef fqr && fqr.MapOutputName(col.colName_) != null)
                    {
                        if (fqr.MapOutputName(col.colName_) is ColExpr ce)
                        {
                            tr = ce.tabRef_;
                        }
                    }

                    if (tr is BaseTableRef btr)
                    {
                        var stats = Catalog.sysstat_.GetColumnStat(btr.relname_, col.colName_);
                        return(stats?.EstDistinct() ?? 0);
                    }
                }
                return(0);
            }

            ulong card;

            node.CreateKeyList();
            var cardl = node.lchild_().Card();
            var cardr = node.rchild_().Card();

            ulong dl = 0, dr = 0, mindlr = 1;

            for (int i = 0; i < node.leftKeys_.Count; i++)
            {
                var lv = node.leftKeys_[i];
                dl = getDistinct(lv);
                var rv = node.rightKeys_[i];
                dr = getDistinct(rv);

                if (node.ops_[i] != "=")
                {
                    mindlr = 0;
                    break;
                }
                mindlr = mindlr * Math.Min(dl, dr);
            }

            if (mindlr != 0)
            {
                card = Math.Max(1, (cardl * cardr) / mindlr);
            }
            else
            {
                // fall back to the old estimator
                card = DefaultEstimate(node);
            }
            return(card);
        }
Esempio n. 3
0
        public override CGroupMember Apply(CGroupMember expr)
        {
            LogicJoin  log = expr.logic_ as LogicJoin;
            var        l   = new PhysicMemoRef(log.l_());
            var        r   = new PhysicMemoRef(log.r_());
            PhysicNode phy = new PhysicNLJoin(log, l, r);

            return(new CGroupMember(phy, expr.group_));
        }
Esempio n. 4
0
        public override CGroupMember Apply(CGroupMember expr)
        {
            LogicJoin log      = expr.logic_ as LogicJoin;
            var       l        = new PhysicMemoRef(log.l_());
            var       r        = new PhysicMemoRef(log.r_());
            var       hashjoin = new PhysicHashJoin(log, l, r);

            return(new CGroupMember(hashjoin, expr.group_));
        }
Esempio n. 5
0
        public override bool Appliable(CGroupMember expr)
        {
            LogicJoin log = expr.logic_ as LogicJoin;

            if (log is null || log is LogicMarkJoin || log is LogicSingleJoin)
            {
                return(false);
            }
            return(true);
        }
Esempio n. 6
0
        // A Xs B => A LOJ B if max1row is assured
        LogicJoin singleJoin2OuterJoin(LogicSingleJoin singJoinNode)
        {
            LogicJoin newjoin = singJoinNode;

            if (!singJoinNode.max1rowCheck_)
            {
                newjoin       = new LogicJoin(singJoinNode.l_(), singJoinNode.r_(), singJoinNode.filter_);
                newjoin.type_ = JoinType.Left;
            }

            return(newjoin);
        }
Esempio n. 7
0
        public override CGroupMember Apply(CGroupMember expr)
        {
            LogicJoin a_bc     = expr.logic_ as LogicJoin;
            LogicNode a        = (a_bc.l_() as LogicMemoRef).Deref <LogicNode>();
            LogicJoin bc       = (a_bc.r_() as LogicMemoRef).Deref <LogicJoin>();
            Expr      bcfilter = bc.filter_;
            var       ab       = new LogicJoin(a_bc.l_(), bc.l_());
            var       c        = bc.r_();
            var       ab_c     = new LogicJoin(ab, c);

            Debug.Assert(!a.LeftReferencesRight(bc));
            if (ab.LeftReferencesRight(c))
            {
                return(expr);
            }

            // pull up all join filters and re-push them back
            Expr allfilters = bcfilter;

            if (a_bc.filter_ != null)
            {
                allfilters = allfilters.AddAndFilter(a_bc.filter_);
            }
            if (allfilters != null)
            {
                var andlist = allfilters.FilterToAndList();
                andlist.RemoveAll(e => ab_c.PushJoinFilter(e));
                if (andlist.Count > 0)
                {
                    ab_c.filter_ = andlist.AndListToExpr();
                }
            }

            // Ideally if there is no cross join in the given plan but cross join
            // in the new plan, we shall return the original plan. However, stop
            // exploration now will prevent generating other promising plans. So
            // we have to return the new plan.
            //
            if (expr.QueryOption().optimize_.memo_disable_crossjoin_)
            {
                if (a_bc.filter_ != null && bcfilter != null)
                {
                    if (ab_c.filter_ is null || ab.filter_ is null)
                    {
                        return(expr);
                    }
                }
            }


            return(new CGroupMember(ab_c, expr.group_));
        }
Esempio n. 8
0
        public override CGroupMember Apply(CGroupMember expr)
        {
            LogicJoin join = expr.logic_ as LogicJoin;
            var       l = join.lchild_(); var r = join.rchild_(); var f = join.filter_;

            Debug.Assert(!l.LeftReferencesRight(r));
            if (r.LeftReferencesRight(l))
            {
                return(expr);
            }

            LogicJoin newjoin = new LogicJoin(r, l, f);

            return(new CGroupMember(newjoin, expr.group_));
        }
Esempio n. 9
0
        // classic formula is:
        //   A X B => |A|*|B|/max(dA, dB) where dA,dB are distinct values of joining columns
        // This however does not consider join key distribution. In SQL Server 2014, it introduced
        // histogram join to better the estimation.
        //
        public override long LogicJoinCE(LogicJoin node)
        {
            long card;

            node.CreateKeyList();
            var cardl = node.l_().Card();
            var cardr = node.r_().Card();

            long dl = 0, dr = 0, mindlr = 1;

            for (int i = 0; i < node.leftKeys_.Count; i++)
            {
                var lv = node.leftKeys_[i];
                if (lv is ColExpr vl && vl.tabRef_ is BaseTableRef bvl)
                {
                    var stat = Catalog.sysstat_.GetColumnStat(bvl.relname_, vl.colName_);
                    dl = stat.EstDistinct();
                }
                var rv = node.rightKeys_[i];
                if (rv is ColExpr vr && vr.tabRef_ is BaseTableRef bvr)
                {
                    var stat = Catalog.sysstat_.GetColumnStat(bvr.relname_, vr.colName_);
                    dr = stat.EstDistinct();
                }

                if (node.ops_[i] != "=")
                {
                    mindlr = 0;
                    break;
                }
                mindlr = mindlr * Math.Min(dl, dr);
            }

            if (mindlr != 0)
            {
                card = Math.Max(1, (cardl * cardr) / mindlr);
            }
            else
            {
                // fall back to the old estimator
                card = DefaultEstimate(node);
            }
            return(card);
        }
Esempio n. 10
0
        // an outer join can be converted to inner join if join condition is null-rejected.
        // Null-rejected condition meaning it evalues to not true (i.e., false or null) for
        // any null completed row generated by outer join.
        //
        // a join condition is null if
        //  https://dev.mysql.com/doc/refman/8.0/en/outer-join-simplification.html
        //  - It is of the form A IS NOT NULL, where A is an attribute of any of the inner tables
        //  - It is a predicate containing a reference to an inner table that evaluates to UNKNOWN
        //    when one of its arguments is NULL
        //  - It is a conjunction containing a null-rejected condition as a conjunct
        //  - It is a disjunction of null-rejected conditions
        //
        LogicJoin trySimplifyOuterJoin(LogicJoin join, Expr extraFilter)
        {
            bool nullRejectingSingleCondition(Expr condition)
            {
                // FIXME: for now, assuming any predicate is null-rejecting unless it is IS NULL
                Debug.Assert(condition.IsBoolean());
                var bcond = condition as BinExpr;

                if (bcond?.op_ == "is")
                {
                    return(false);
                }
                return(false);
            }

            // if no extra filters, can't convert
            if (extraFilter is null)
            {
                return(join);
            }
            if (join.type_ != JoinType.Left)
            {
                return(join);
            }

            // It is a conjunction containing a null-rejected condition as a conjunct
            var  andlist    = extraFilter.FilterToAndList();
            bool nullreject = andlist.Where(x => nullRejectingSingleCondition(x)).Count() > 0;

            if (nullreject)
            {
                goto convert_inner;
            }

            // It is a conjunction containing a null-rejected condition as a conjunct
            return(join);

convert_inner:
            join.type_ = JoinType.Inner;
            return(join);
        }
Esempio n. 11
0
        public override bool Appliable(CGroupMember expr)
        {
            LogicJoin join = expr.logic_ as LogicJoin;

            if (join is null || join is LogicMarkJoin || join is LogicSingleJoin)
            {
                return(false);
            }

            if (join.filter_.FilterHashable())
            {
                var  stmt        = expr.Stmt() as SelectStmt;
                bool lhasSubqCol = stmt.PlanContainsCorrelatedSubquery() &&
                                   TableRef.HasColsUsedBySubquries(join.l_().InclusiveTableRefs());
                if (!lhasSubqCol)
                {
                    return(true);
                }
            }
            return(false);
        }
Esempio n. 12
0
 public abstract ulong LogicJoinCE(LogicJoin node);
Esempio n. 13
0
    public static void Run(SQLStatement stmt, ExecContext context)
    {
        PhysicCollect   PhysicCollect108   = stmt.physicPlan_.LocateNode("108") as PhysicCollect;
        PhysicProfiling PhysicProfiling109 = stmt.physicPlan_.LocateNode("109") as PhysicProfiling;
        LogicLimit      LogicLimit109      = PhysicProfiling109.logic_ as LogicLimit;
        var             filter109          = LogicLimit109.filter_;
        var             output109          = LogicLimit109.output_;
        PhysicLimit     PhysicLimit110     = stmt.physicPlan_.LocateNode("110") as PhysicLimit;
        LogicLimit      LogicLimit110      = PhysicLimit110.logic_ as LogicLimit;
        var             filter110          = LogicLimit110.filter_;
        var             output110          = LogicLimit110.output_;
        PhysicProfiling PhysicProfiling111 = stmt.physicPlan_.LocateNode("111") as PhysicProfiling;
        LogicAgg        LogicAgg111        = PhysicProfiling111.logic_ as LogicAgg;
        var             filter111          = LogicAgg111.filter_;
        var             output111          = LogicAgg111.output_;
        PhysicHashAgg   PhysicHashAgg112   = stmt.physicPlan_.LocateNode("112") as PhysicHashAgg;
        LogicAgg        LogicAgg112        = PhysicHashAgg112.logic_ as LogicAgg;
        var             filter112          = LogicAgg112.filter_;
        var             output112          = LogicAgg112.output_;
        PhysicProfiling PhysicProfiling113 = stmt.physicPlan_.LocateNode("113") as PhysicProfiling;
        LogicJoin       LogicJoin113       = PhysicProfiling113.logic_ as LogicJoin;
        var             filter113          = LogicJoin113.filter_;
        var             output113          = LogicJoin113.output_;
        PhysicHashJoin  PhysicHashJoin114  = stmt.physicPlan_.LocateNode("114") as PhysicHashJoin;
        LogicJoin       LogicJoin114       = PhysicHashJoin114.logic_ as LogicJoin;
        var             filter114          = LogicJoin114.filter_;
        var             output114          = LogicJoin114.output_;
        PhysicProfiling PhysicProfiling115 = stmt.physicPlan_.LocateNode("115") as PhysicProfiling;
        LogicJoin       LogicJoin115       = PhysicProfiling115.logic_ as LogicJoin;
        var             filter115          = LogicJoin115.filter_;
        var             output115          = LogicJoin115.output_;
        PhysicHashJoin  PhysicHashJoin116  = stmt.physicPlan_.LocateNode("116") as PhysicHashJoin;
        LogicJoin       LogicJoin116       = PhysicHashJoin116.logic_ as LogicJoin;
        var             filter116          = LogicJoin116.filter_;
        var             output116          = LogicJoin116.output_;
        PhysicProfiling PhysicProfiling117 = stmt.physicPlan_.LocateNode("117") as PhysicProfiling;
        LogicScanTable  LogicScanTable117  = PhysicProfiling117.logic_ as LogicScanTable;
        var             filter117          = LogicScanTable117.filter_;
        var             output117          = LogicScanTable117.output_;
        PhysicScanTable PhysicScanTablea   = stmt.physicPlan_.LocateNode("a") as PhysicScanTable;
        LogicScanTable  LogicScanTablea    = PhysicScanTablea.logic_ as LogicScanTable;
        var             filtera            = LogicScanTablea.filter_;
        var             outputa            = LogicScanTablea.output_;
        PhysicProfiling PhysicProfiling118 = stmt.physicPlan_.LocateNode("118") as PhysicProfiling;
        LogicScanTable  LogicScanTable118  = PhysicProfiling118.logic_ as LogicScanTable;
        var             filter118          = LogicScanTable118.filter_;
        var             output118          = LogicScanTable118.output_;
        PhysicScanTable PhysicScanTablec   = stmt.physicPlan_.LocateNode("c") as PhysicScanTable;
        LogicScanTable  LogicScanTablec    = PhysicScanTablec.logic_ as LogicScanTable;
        var             filterc            = LogicScanTablec.filter_;
        var             outputc            = LogicScanTablec.output_;
        var             hm116 = new Dictionary <KeyList, List <TaggedRow> >();
        PhysicProfiling PhysicProfiling119 = stmt.physicPlan_.LocateNode("119") as PhysicProfiling;
        LogicScanTable  LogicScanTable119  = PhysicProfiling119.logic_ as LogicScanTable;
        var             filter119          = LogicScanTable119.filter_;
        var             output119          = LogicScanTable119.output_;
        PhysicScanTable PhysicScanTableb   = stmt.physicPlan_.LocateNode("b") as PhysicScanTable;
        LogicScanTable  LogicScanTableb    = PhysicScanTableb.logic_ as LogicScanTable;
        var             filterb            = LogicScanTableb.filter_;
        var             outputb            = LogicScanTableb.output_;
        var             hm114       = new Dictionary <KeyList, List <TaggedRow> >();
        var             aggrcore112 = LogicAgg112.aggrFns_;
        var             hm112       = new Dictionary <KeyList, Row>();
        var             nrows110    = 0;

        PhysicProfiling109.nloops_++;
        PhysicProfiling111.nloops_++;
        PhysicProfiling113.nloops_++;
        PhysicProfiling115.nloops_++;
        PhysicProfiling117.nloops_++;
        var heapa = (LogicScanTablea.tabref_).Table().heap_.GetEnumerator();

        for (;;)
        {
            Row ra = null;
            if (context.stop_)
            {
                break;
            }
            if (heapa.MoveNext())
            {
                ra = heapa.Current;
            }
            else
            {
                break;
            }
            {
                {
                    // projection on PhysicScanTablea: Output: a.a1[0],a.a2[1]
                    Row rproj = new Row(2);
                    rproj[0] = ra[0];
                    rproj[1] = ra[1];
                    ra       = rproj;
                }

                PhysicProfiling117.nrows_++;
                var r117    = ra;
                var keys116 = KeyList.ComputeKeys(context, LogicJoin116.leftKeys_, r117);
                if (hm116.TryGetValue(keys116, out List <TaggedRow> exist))
                {
                    exist.Add(new TaggedRow(r117));
                }
                else
                {
                    var rows = new List <TaggedRow>();
                    rows.Add(new TaggedRow(r117));
                    hm116.Add(keys116, rows);
                }
            }
        }

        if (hm116.Count == 0)
        {
            return;
        }
        PhysicProfiling118.nloops_++;
        var heapc = (LogicScanTablec.tabref_).Table().heap_.GetEnumerator();

        for (;;)
        {
            Row rc = null;
            if (context.stop_)
            {
                break;
            }
            if (heapc.MoveNext())
            {
                rc = heapc.Current;
            }
            else
            {
                break;
            }
            {
                {
                    // projection on PhysicScanTablec: Output: c.c2[1]
                    Row rproj = new Row(1);
                    rproj[0] = rc[1];
                    rc       = rproj;
                }

                PhysicProfiling118.nrows_++;
                var r118 = rc;
                if (context.stop_)
                {
                    return;
                }
                Row  fakel116         = new Row(2);
                Row  r116             = new Row(fakel116, r118);
                var  keys116          = KeyList.ComputeKeys(context, LogicJoin116.rightKeys_, r116);
                bool foundOneMatch116 = false;
                if (hm116.TryGetValue(keys116, out List <TaggedRow> exist116))
                {
                    foundOneMatch116 = true;
                    foreach (var v116 in exist116)
                    {
                        r116 = new Row(v116.row_, r118);
                        {
                            // projection on PhysicHashJoin116: Output: a.a1[0],a.a2[1]
                            Row rproj = new Row(2);
                            rproj[0] = r116[0];
                            rproj[1] = r116[1];
                            r116     = rproj;
                        }

                        PhysicProfiling115.nrows_++;
                        var r115    = r116;
                        var keys114 = KeyList.ComputeKeys(context, LogicJoin114.leftKeys_, r115);
                        if (hm114.TryGetValue(keys114, out List <TaggedRow> exist))
                        {
                            exist.Add(new TaggedRow(r115));
                        }
                        else
                        {
                            var rows = new List <TaggedRow>();
                            rows.Add(new TaggedRow(r115));
                            hm114.Add(keys114, rows);
                        }
                    }
                }
                else
                {
                    // no match for antisemi
                }
            }
        }

        if (hm114.Count == 0)
        {
            return;
        }
        PhysicProfiling119.nloops_++;
        var heapb = (LogicScanTableb.tabref_).Table().heap_.GetEnumerator();

        for (;;)
        {
            Row rb = null;
            if (context.stop_)
            {
                break;
            }
            if (heapb.MoveNext())
            {
                rb = heapb.Current;
            }
            else
            {
                break;
            }
            {
                {
                    // projection on PhysicScanTableb: Output: b.b1[0]
                    Row rproj = new Row(1);
                    rproj[0] = rb[0];
                    rb       = rproj;
                }

                PhysicProfiling119.nrows_++;
                var r119 = rb;
                if (context.stop_)
                {
                    return;
                }
                Row  fakel114         = new Row(2);
                Row  r114             = new Row(fakel114, r119);
                var  keys114          = KeyList.ComputeKeys(context, LogicJoin114.rightKeys_, r114);
                bool foundOneMatch114 = false;
                if (hm114.TryGetValue(keys114, out List <TaggedRow> exist114))
                {
                    foundOneMatch114 = true;
                    foreach (var v114 in exist114)
                    {
                        r114 = new Row(v114.row_, r119);
                        {
                            // projection on PhysicHashJoin114: Output: a.a1[0],a.a2[1]
                            Row rproj = new Row(2);
                            rproj[0] = r114[0];
                            rproj[1] = r114[1];
                            r114     = rproj;
                        }

                        PhysicProfiling113.nrows_++;
                        var r113 = r114;
                        var keys = KeyList.ComputeKeys(context, LogicAgg112.keys_, r113);
                        if (hm112.TryGetValue(keys, out Row exist))
                        {
                            for (int i = 0; i < 1; i++)
                            {
                                var old = exist[i];
                                exist[i] = aggrcore112[i].Accum(context, old, r113);
                            }
                        }
                        else
                        {
                            hm112.Add(keys, PhysicHashAgg112.AggrCoreToRow(r113));
                            exist = hm112[keys];
                            for (int i = 0; i < 1; i++)
                            {
                                exist[i] = aggrcore112[i].Init(context, r113);
                            }
                        }
                    }
                }
                else
                {
                    // no match for antisemi
                }
            }
        }

        foreach (var v112 in hm112)
        {
            if (context.stop_)
            {
                break;
            }
            var keys112    = v112.Key;
            Row aggvals112 = v112.Value;
            for (int i = 0; i < 1; i++)
            {
                aggvals112[i] = aggrcore112[i].Finalize(context, aggvals112[i]);
            }
            var r112 = new Row(keys112, aggvals112);
            if (true || LogicAgg112.having_.Exec(context, r112) is true)
            {
                {
                    // projection on PhysicHashAgg112: Output: {a.a2}[0]*2,{count(a.a1)}[1],repeat('a',{a.a2}[0])
                    Row rproj = new Row(3);
                    rproj[0] = ((dynamic)r112[0] * (dynamic)2);
                    rproj[1] = r112[1];
                    rproj[2] = ExprSearch.Locate("74").Exec(context, r112) /*repeat('a',{a.a2}[0])*/;
                    r112     = rproj;
                }

                PhysicProfiling111.nrows_++;
                var r111 = r112;
                nrows110++;
                Debug.Assert(nrows110 <= 2);
                if (nrows110 == 2)
                {
                    context.stop_ = true;
                }
                var r110 = r111;
                PhysicProfiling109.nrows_++;
                var r109 = r110;
                Row newr = new Row(3);
                newr[0] = r109[0];
                newr[1] = r109[1];
                newr[2] = r109[2];
                PhysicCollect108.rows_.Add(newr);
                Console.WriteLine(newr);
            }
        }
    }
Esempio n. 14
0
        public LogicNode CreateSetOpPlan(bool top = true)
        {
            if (top)
            {
                // traversal on top node is the time to examine the setop tree
                Debug.Assert(!IsLeaf());
                VerifySelection();
            }

            if (IsLeaf())
            {
                return(stmt_.CreatePlan());
            }
            else
            {
                LogicNode plan  = null;
                var       lplan = left_.CreateSetOpPlan(false);
                var       rplan = right_.CreateSetOpPlan(false);

                // try to reuse existing operators to implment because users may write
                // SQL code like this and this helps reduce optimizer search space
                //
                switch (op_)
                {
                case "unionall":
                    // union all keeps all rows, including duplicates
                    plan = new LogicAppend(lplan, rplan);
                    break;

                case "union":
                    // union collect rows from both sides, and remove duplicates
                    plan = new LogicAppend(lplan, rplan);
                    var groupby = new List <Expr>(first_.selection_.CloneList());
                    plan = new LogicAgg(plan, groupby, null, null);
                    break;

                case "except":
                // except keeps left rows not found in right
                case "intersect":
                    // intersect keeps rows found in both sides
                    var filter = FilterHelper.MakeFullComparator(
                        left_.first_.selection_, right_.first_.selection_);
                    var join = new LogicJoin(lplan, rplan);
                    if (op_.Contains("except"))
                    {
                        join.type_ = JoinType.AntiSemi;
                    }
                    if (op_.Contains("intersect"))
                    {
                        join.type_ = JoinType.Semi;
                    }
                    var logfilter = new LogicFilter(join, filter);
                    groupby = new List <Expr>(first_.selection_.CloneList());
                    plan    = new LogicAgg(logfilter, groupby, null, null);
                    break;

                case "exceptall":
                case "intersectall":
                    // the 'all' semantics is a bit confusing than intuition:
                    //  {1,1,1} exceptall {1,1} => {1}
                    //  {1,1,1} intersectall {1,1} => {1,1}
                    //
                    throw new NotImplementedException();

                default:
                    throw new InvalidProgramException();
                }

                return(plan);
            }
        }
Esempio n. 15
0
 public LogicJoinBlock(LogicJoin join, JoinGraph graph)
 {
     graph_ = graph;
     join_  = join;
     children_.AddRange(graph.vertices_);
 }
Esempio n. 16
0
        // from clause -
        //  pair each from item with cross join, their join conditions will be handled
        //  with where clause processing.
        //
        LogicNode transformFromClause()
        {
            LogicNode transformOneFrom(TableRef tab)
            {
                LogicNode from;

                switch (tab)
                {
                case BaseTableRef bref:
                    if (bref.Table().source_ == TableDef.TableSource.Table)
                    {
                        from = new LogicScanTable(bref);
                    }
                    else
                    {
                        from = new LogicScanStream(bref);
                    }
                    if (bref.tableSample_ != null)
                    {
                        from = new LogicSampleScan(from, bref.tableSample_);
                    }
                    break;

                case ExternalTableRef eref:
                    from = new LogicScanFile(eref);
                    break;

                case QueryRef qref:
                    var plan = qref.query_.CreatePlan();
                    if (qref is FromQueryRef && queryOpt_.optimize_.remove_from_)
                    {
                        from = plan;
                    }
                    else
                    {
                        string alias = null;
                        if (qref is CTEQueryRef cq)
                        {
                            alias = cq.alias_;
                        }
                        else if (qref is FromQueryRef fq)
                        {
                            alias = fq.alias_;
                        }
                        var key = new NamedQuery(qref.query_, alias);
                        from = new LogicFromQuery(qref, plan);
                        subQueries_.Add(key);

                        // if from CTE, then it could be duplicates
                        if (!fromQueries_.ContainsKey(key))
                        {
                            fromQueries_.Add(key, from as LogicFromQuery);
                        }
                    }
                    break;

                case JoinQueryRef jref:
                    // We will form join group on all tables and put a filter on top
                    // of the joins as a normalized form for later processing.
                    //
                    //      from a join b on a1=b1 or a3=b3 join c on a2=c2;
                    //   => from a , b, c where  (a1=b1 or a3=b3) and a2=c2;
                    //
                    LogicJoin subjoin    = new LogicJoin(null, null);
                    Expr      filterexpr = null;
                    for (int i = 0; i < jref.tables_.Count; i++)
                    {
                        LogicNode t        = transformOneFrom(jref.tables_[i]);
                        var       children = subjoin.children_;
                        if (children[0] is null)
                        {
                            children[0] = t;
                        }
                        else
                        {
                            if (children[1] is null)
                            {
                                children[1] = t;
                            }
                            else
                            {
                                subjoin = new LogicJoin(t, subjoin);
                            }
                            subjoin.type_ = jref.joinops_[i - 1];
                            filterexpr    = filterexpr.AddAndFilter(jref.constraints_[i - 1]);
                        }
                    }
                    Debug.Assert(filterexpr != null);
                    from = new LogicFilter(subjoin, filterexpr);
                    break;

                default:
                    throw new InvalidProgramException();
                }

                return(from);
            }

            LogicNode root;

            if (from_.Count >= 2)
            {
                var join     = new LogicJoin(null, null);
                var children = join.children_;
                from_.ForEach(x =>
                {
                    LogicNode from = transformOneFrom(x);
                    if (children[0] is null)
                    {
                        children[0] = from;
                    }
                    else
                    {
                        children[1] = (children[1] is null) ? from :
                                      new LogicJoin(from, children[1]);
                    }
                });
                root = join;
            }
            else if (from_.Count == 1)
            {
                root = transformOneFrom(from_[0]);
            }
            else
            {
                root = new LogicResult(selection_);
            }

            // distributed plan is required if any table is distributed, subquery
            // referenced tables are not counted here. So we may have the query
            // shape with main queyr not distributed but subquery is.
            //
            bool hasdtable      = false;
            bool onlyreplicated = true;

            from_.ForEach(x => checkifHasdtableAndifOnlyReplicated(x, ref hasdtable, ref onlyreplicated));
            if (hasdtable)
            {
                Debug.Assert(!distributed_);
                distributed_ = true;

                // distributed table query can also use memo
                // remote exchange is considered in memo optimization
                queryOpt_.optimize_.memo_use_remoteexchange_ = true;

                if (onlyreplicated)
                {
                    root = new LogicGather(root, new List <int> {
                        0
                    });
                }
                else
                {
                    root = new LogicGather(root);
                }
            }

            return(root);
        }
Esempio n. 17
0
        // from clause -
        //  pair each from item with cross join, their join conditions will be handled
        //  with where clauss processing.
        //
        LogicNode transformFromClause()
        {
            LogicNode transformOneFrom(TableRef tab)
            {
                LogicNode from;

                switch (tab)
                {
                case BaseTableRef bref:
                    from = new LogicScanTable(bref);
                    break;

                case ExternalTableRef eref:
                    from = new LogicScanFile(eref);
                    break;

                case QueryRef qref:
                    var plan = qref.query_.CreatePlan();
                    if (qref is FromQueryRef && queryOpt_.optimize_.remove_from_)
                    {
                        from = plan;
                    }
                    else
                    {
                        string alias = null;
                        if (qref is CTEQueryRef cq)
                        {
                            alias = cq.alias_;
                        }
                        else if (qref is FromQueryRef fq)
                        {
                            alias = fq.alias_;
                        }
                        var key = new NamedQuery(qref.query_, alias);
                        from = new LogicFromQuery(qref, plan);
                        subQueries_.Add(key);

                        // if from CTE, then it could be duplicates
                        if (!fromQueries_.ContainsKey(key))
                        {
                            fromQueries_.Add(key, from as LogicFromQuery);
                        }
                    }
                    break;

                case JoinQueryRef jref:
                    // We will form join group on all tables and put a filter on top
                    // of the joins as a normalized form for later processing.
                    //
                    //      from a join b on a1=b1 or a3=b3 join c on a2=c2;
                    //   => from a , b, c where  (a1=b1 or a3=b3) and a2=c2;
                    //
                    LogicJoin subjoin    = new LogicJoin(null, null);
                    Expr      filterexpr = null;
                    for (int i = 0; i < jref.tables_.Count; i++)
                    {
                        LogicNode t        = transformOneFrom(jref.tables_[i]);
                        var       children = subjoin.children_;
                        if (children[0] is null)
                        {
                            children[0] = t;
                        }
                        else
                        {
                            if (children[1] is null)
                            {
                                children[1] = t;
                            }
                            else
                            {
                                subjoin = new LogicJoin(t, subjoin);
                            }
                            subjoin.type_ = jref.joinops_[i - 1];
                            filterexpr    = filterexpr.AddAndFilter(jref.constraints_[i - 1]);
                        }
                    }
                    Debug.Assert(filterexpr != null);
                    from = new LogicFilter(subjoin, filterexpr);
                    break;

                default:
                    throw new Exception();
                }

                return(from);
            }

            LogicNode root;

            if (from_.Count >= 2)
            {
                var join     = new LogicJoin(null, null);
                var children = join.children_;
                from_.ForEach(x =>
                {
                    LogicNode from = transformOneFrom(x);
                    if (children[0] is null)
                    {
                        children[0] = from;
                    }
                    else
                    {
                        children[1] = (children[1] is null) ? from :
                                      new LogicJoin(from, children[1]);
                    }
                });
                root = join;
            }
            else if (from_.Count == 1)
            {
                root = transformOneFrom(from_[0]);
            }
            else
            {
                root = new LogicResult(selection_);
            }

            return(root);
        }