// remainingViews may contain either unions only or intersections + differences
        private bool SimplifyRewritingOnce(T_Tile newRewriting, HashSet <T_Tile> remainingViews,
                                           out T_Tile simplifiedRewriting)
        {
            simplifiedRewriting = null;
            if (remainingViews.Count == 0)
            {
                return(false);
            }
            if (remainingViews.Count == 1)
            {
                // determine the remaining view
                T_Tile remainingView = remainingViews.First();

                // check whether rewriting obtained so far is good enough
                // try disposing of this remaining view
                bool isDisposable = false;
                switch (m_usedViews[remainingView])
                {
                case TileOpKind.Union:
                    // check whether rewriting still covers toFill
                    isDisposable = m_qp.IsContainedIn(m_originalRewriting, newRewriting);
                    break;

                default:     // intersection
                    isDisposable = m_qp.IsContainedIn(m_originalRewriting, newRewriting) &&
                                   m_qp.IsDisjointFrom(m_toAvoid, newRewriting);
                    break;
                }
                if (isDisposable)
                {
                    // yes, the remaining view is disposable
                    simplifiedRewriting = newRewriting;
                    m_usedViews.Remove(remainingView);
                    return(true);
                }
                return(false); // no, can't trash the remaining view
            }
            // split remainingViews into two halves
            // Compute rewriting for first half. Call recursively on second half.
            // Then, compute rewriting for second half. Call recursively on first half.
            int              halfCount           = remainingViews.Count / 2;
            int              count               = 0;
            T_Tile           firstHalfRewriting  = newRewriting;
            T_Tile           secondHalfRewriting = newRewriting;
            HashSet <T_Tile> firstHalf           = new HashSet <T_Tile>();
            HashSet <T_Tile> secondHalf          = new HashSet <T_Tile>();

            foreach (T_Tile remainingView in remainingViews)
            {
                TileOpKind viewKind = m_usedViews[remainingView];
                // add to first half
                if (count++ < halfCount)
                {
                    firstHalf.Add(remainingView);
                    firstHalfRewriting = GetRewritingHalf(firstHalfRewriting, remainingView, viewKind);
                }
                else // add to second half
                {
                    secondHalf.Add(remainingView);
                    secondHalfRewriting = GetRewritingHalf(secondHalfRewriting, remainingView, viewKind);
                }
            }
            // now, call recursively
            return(SimplifyRewritingOnce(firstHalfRewriting, secondHalf, out simplifiedRewriting) ||
                   SimplifyRewritingOnce(secondHalfRewriting, firstHalf, out simplifiedRewriting));
        }
Пример #2
0
        private bool RewriteQuery(out T_Tile rewriting)
        {
            rewriting = m_toFill;
            T_Tile rewritingSoFar;

            if (false == FindRewritingByIncludedAndDisjoint(out rewritingSoFar))
            {
                if (false == FindContributingView(out rewritingSoFar))
                {
                    return(false);
                }
            }

            bool hasExtraTuples = !m_qp.IsDisjointFrom(rewritingSoFar, m_toAvoid);

            // try to cut off extra tuples using joins
            if (hasExtraTuples)
            {
                foreach (T_Tile view in AvailableViews)
                {
                    if (TryJoin(view, ref rewritingSoFar))
                    {
                        hasExtraTuples = false;
                        break;
                    }
                }
            }

            // try to cut off extra tuples using anti-semijoins
            if (hasExtraTuples)
            {
                foreach (T_Tile view in AvailableViews)
                {
                    if (TryAntiSemiJoin(view, ref rewritingSoFar))
                    {
                        hasExtraTuples = false;
                        break;
                    }
                }
            }

            if (hasExtraTuples)
            {
                return(false); // won't be able to cut off extra tuples
            }

            // remove redundant joins and anti-semijoins
            RewritingSimplifier <T_Tile> .TrySimplifyJoinRewriting(ref rewritingSoFar, m_toAvoid, m_usedViews, m_qp);

            // find rewriting for missing tuples, if any
            T_Tile missingTuples = m_qp.AntiSemiJoin(m_toFill, rewritingSoFar);

            if (!m_qp.IsEmpty(missingTuples))
            {
                T_Tile rewritingForMissingTuples;
                if (false == RewritingPass <T_Tile> .RewriteQueryInternal(missingTuples, m_toAvoid, out rewritingForMissingTuples, m_views, new HashSet <T_Tile>(m_usedViews.Keys), m_qp))
                {
                    rewriting = rewritingForMissingTuples;
                    return(false); // failure
                }
                else
                {
                    // Although a more general optimization for UNIONs will handle this case,
                    // adding this check reduces the overall number of containment tests
                    if (m_qp.IsContainedIn(rewritingSoFar, rewritingForMissingTuples))
                    {
                        rewritingSoFar = rewritingForMissingTuples;
                    }
                    else
                    {
                        rewritingSoFar = m_qp.Union(rewritingSoFar, rewritingForMissingTuples);
                    }
                }
            }

            // if we reached this point, we have a successful rewriting
            rewriting = rewritingSoFar;
            return(true);
        }