Beispiel #1
0
        LogicNode FilterPushDown(LogicNode plan, bool pushJoinFilter)
        {
            // locate the all filters ingoring any within FromQuery as it will
            // be optimized by subquery optimization and this will cause double
            // predicate push down (e.g., a1>1 && a1>1)
            //
            var parents   = new List <LogicNode>();
            var indexes   = new List <int>();
            var filters   = new List <LogicFilter>();
            var cntFilter = plan.FindNodeTypeMatch(parents,
                                                   indexes, filters, skipParentType: typeof(LogicFromQuery));

            for (int i = 0; i < cntFilter; i++)
            {
                var parent = parents[i];
                var filter = filters[i];
                var index  = indexes[i];

                Debug.Assert(!(parent is LogicFromQuery));
                if (filter?.filter_ != null && filter?.movable_ is true)
                {
                    List <Expr> andlist    = new List <Expr>();
                    var         filterexpr = filter.filter_;

                    // if it is a constant true filer, remove it. If a false filter, we leave
                    // it there - shall we try hard to stop query early? Nope, it is no deserved
                    // to poke around for this corner case.
                    //
                    var isConst = filterexpr.FilterIsConst(out bool trueOrFalse);
                    if (isConst)
                    {
                        if (!trueOrFalse)
                        {
                            andlist.Add(LiteralExpr.MakeLiteral("false", new BoolType()));
                        }
                        else
                        {
                            Debug.Assert(andlist.Count == 0);
                        }
                    }
                    else
                    {
                        // filter push down
                        andlist = filterexpr.FilterToAndList();
                        andlist.RemoveAll(e =>
                        {
                            var isConst = e.FilterIsConst(out bool trueOrFalse);
                            if (isConst)
                            {
                                Debug.Assert(trueOrFalse);
                                return(true);
                            }
                            return(pushdownFilter(plan, e, pushJoinFilter));
                        });
                    }

                    // stich the new plan
                    if (andlist.Count == 0)
                    {
                        if (parent is null)
                        {
                            // take it out from the tree
                            plan = plan.child_();
                        }
                        else
                        {
                            parent.children_[index] = filter.child_();
                        }
                    }
                    else
                    {
                        filter.filter_ = andlist.AndListToExpr();
                    }
                }
            }

            return(plan);
        }