Beispiel #1
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:
                    from = new LogicScanTable(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 =>
            {
                if (x is BaseTableRef bx)
                {
                    var method = bx.Table().distMethod_;
                    if (bx.IsDistributed())
                    {
                        hasdtable = true;
                        if (method != TableDef.DistributionMethod.Replicated)
                        {
                            onlyreplicated = false;
                        }
                    }
                }
            });
            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);
        }
Beispiel #2
0
 public LogicMarkJoin(LogicNode l, LogicNode r, Expr f) : base(l, r, f)
 {
     type_ = JoinType.Left;
 }
Beispiel #3
0
        // If there is OR in the predicate, can't turn into a filter
        //
        LogicNode existsToMarkJoin(LogicNode nodeA, ExistSubqueryExpr existExpr, ref bool canReplace)
        {
            bool exprIsNotORExprAndEqualsToExistExpr(Expr x, Expr existExpr)
            {
                return((!(x is LogicOrExpr)) && x.Equals(existExpr));
            }

            // nodeB contains the join filter
            var nodeB       = existExpr.query_.logicPlan_;
            var nodeBFilter = nodeB.filter_;

            nodeB.NullifyFilter();

            // nullify nodeA's filter: the rest is push to top filter. However,
            // if nodeA is a Filter|MarkJoin, keep its mark filter.
            var markerFilter = new ExprRef(new MarkerExpr(nodeBFilter.tableRefs_, existExpr.subqueryid_), 0);
            var nodeAFilter  = nodeA.filter_;

            Debug.Assert(!(nodeA is null));

            // a1 > @1 and a2 > @2 and a3 > 2, existExpr = @1
            //   keeplist: a1 > @1 and a3 > 2
            //   andlist after removal: a2 > @2
            //   nodeAFilter = a1 > @1 and a3 > 2
            //   consider a1>0 and (@1 or @2)
            //   a1>0 and (@1 or (@2 and @3))

            //(@1 or marker@2) and marker@3 existExpr = @1
            //   keep list (@1 or marker@2)
            //   andlist after remove @3
            //   nodeAFilter = (@1 or marker@2)
            var andlist  = nodeAFilter.FilterToAndList();
            var keeplist = andlist.Where(x => x.VisitEachExists(e => e.Equals(existExpr))).ToList();

            andlist.RemoveAll(x => exprIsNotORExprAndEqualsToExistExpr(x, existExpr) ||
                              ((x is LogicOrExpr) && !hasAnyExtraSubqueryExprInOR(x, existExpr)));

            // if there is any (#marker@1 or @2), the root should be replace,
            // i.e. the (#marker@1 or @2)  keeps at the top for farther unnesting
            canReplace = andlist.Find(x => (x is LogicOrExpr) && hasAnyExtraSubqueryExprInOR(x, existExpr)) == null ? false : true;

            if (andlist.Count == 0 || canReplace)
            {
                // nodeA is root, a ref parameter. (why it is a ref parameter without "ref" or "out" )
                nodeA.NullifyFilter();
            }
            else
            {
                nodeA.filter_ = andlist.AndListToExpr();
                nodeAFilter   = keeplist.Count > 0 ? keeplist.AndListToExpr() : markerFilter;
            }

            // make a mark join
            LogicMarkJoin markjoin;

            if (existExpr.hasNot_)
            {
                markjoin = new LogicMarkAntiSemiJoin(nodeA, nodeB, existExpr.subqueryid_);
            }
            else
            {
                markjoin = new LogicMarkSemiJoin(nodeA, nodeB, existExpr.subqueryid_);
            }

            // make a filter on top of the mark join collecting all filters
            Expr topfilter;

            topfilter = nodeAFilter.SearchAndReplace(existExpr, markerFilter);
            nodeBFilter.DeParameter(nodeA.InclusiveTableRefs());

            // find all expr contains Parameter col and move it to the toper
            var TableRefs = nodeA.InclusiveTableRefs();

            topfilter = topfilter.AddAndFilter(nodeBFilter);
            LogicFilter Filter             = new LogicFilter(markjoin, topfilter);
            var         notDeparameterExpr = findAndfetchParameterExpr(ref nodeA);

            if (notDeparameterExpr.Count > 0)
            {
                topfilter = notDeparameterExpr.AndListToExpr();
                Filter    = new LogicFilter(Filter, topfilter);
            }
            return(Filter);
        }
Beispiel #4
0
 public LogicMarkJoin(LogicNode l, LogicNode r, int subquery_id) : base(l, r)
 {
     type_ = JoinType.Left; subquery_id_ = subquery_id;
 }
Beispiel #5
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);
        }