internal CellQuery(
     List <ProjectedSlot> slots,
     BoolExpression whereClause,
     MemberPath rootMember,
     CellQuery.SelectDistinct eliminateDuplicates)
     : this(slots.ToArray(), whereClause, new List <BoolExpression>(), eliminateDuplicates, rootMember)
 {
 }
 internal CellQuery(CellQuery source)
 {
     this.m_basicCellRelation   = source.m_basicCellRelation;
     this.m_boolExprs           = source.m_boolExprs;
     this.m_selectDistinct      = source.m_selectDistinct;
     this.m_extentMemberPath    = source.m_extentMemberPath;
     this.m_originalWhereClause = source.m_originalWhereClause;
     this.m_projectedSlots      = source.m_projectedSlots;
     this.m_whereClause         = source.m_whereClause;
 }
 // effects: Given two duplicate eliination choices, returns an OR of them
 static private CellQuery.SelectDistinct MergeDupl(CellQuery.SelectDistinct d1, CellQuery.SelectDistinct d2)
 {
     if (d1 == CellQuery.SelectDistinct.Yes || d2 == CellQuery.SelectDistinct.Yes)
     {
         return(CellQuery.SelectDistinct.Yes);
     }
     else
     {
         return(CellQuery.SelectDistinct.No);
     }
 }
 /// <summary>
 /// Creates an cql block representing the <paramref name="extent"/> (the FROM part).
 /// SELECT is given by <paramref name="slots"/>, WHERE by <paramref name="whereClause"/> and AS by <paramref name="blockAliasNum"/>.
 /// </summary>
 internal ExtentCqlBlock(EntitySetBase extent,
                         CellQuery.SelectDistinct selectDistinct,
                         SlotInfo[] slots,
                         BoolExpression whereClause,
                         CqlIdentifiers identifiers,
                         int blockAliasNum)
     : base(slots, EmptyChildren, whereClause, identifiers, blockAliasNum)
 {
     m_extent         = extent;
     m_nodeTableAlias = identifiers.GetBlockAlias();
     m_selectDistinct = selectDistinct;
 }
 internal CellQuery(
     ProjectedSlot[] projectedSlots,
     BoolExpression whereClause,
     List <BoolExpression> boolExprs,
     CellQuery.SelectDistinct elimDupl,
     MemberPath rootMember)
 {
     this.m_boolExprs           = boolExprs;
     this.m_projectedSlots      = projectedSlots;
     this.m_whereClause         = whereClause;
     this.m_originalWhereClause = whereClause;
     this.m_selectDistinct      = elimDupl;
     this.m_extentMemberPath    = rootMember;
 }
        // effects: Merges query2 with this according to the TM/SP rules for opType and
        // returns the merged result. canBooleansOverlap indicates whether the bools in this and query2 can overlap, i.e.
        // the same cells may have contributed to query2 and this earlier in the merge process
        internal bool TryMergeTwoCellQueries(CellQuery query1, CellQuery query2, CellTreeOpType opType,
                                             MemberDomainMap memberDomainMap, out CellQuery mergedQuery)
        {
            mergedQuery = null;
            // Initialize g1 and g2 according to the TM/SP rules for IJ, LOJ, Union, FOJ cases
            BoolExpression g1 = null;
            BoolExpression g2 = null;

            switch (opType)
            {
            case CellTreeOpType.IJ:
                break;

            case CellTreeOpType.LOJ:
            case CellTreeOpType.LASJ:
                g2 = BoolExpression.True;
                break;

            case CellTreeOpType.FOJ:
            case CellTreeOpType.Union:
                g1 = BoolExpression.True;
                g2 = BoolExpression.True;
                break;

            default:
                Debug.Fail("Unsupported operator");
                break;
            }

            Dictionary <MemberPath, MemberPath> remap =
                new Dictionary <MemberPath, MemberPath>(MemberPath.EqualityComparer);

            //Continue merging only if both queries are over the same source
            MemberPath newRoot;

            if (!query1.Extent.Equals(query2.Extent))
            { // could not merge
                return(false);
            }
            else
            {
                newRoot = query1.SourceExtentMemberPath;
            }

            // Conjuncts for ANDing with the previous whereClauses
            BoolExpression conjunct1   = BoolExpression.True;
            BoolExpression conjunct2   = BoolExpression.True;
            BoolExpression whereClause = null;

            switch (opType)
            {
            case CellTreeOpType.IJ:
                // Project[D1, D2, A, B, C] Select[cond1 and cond2] (T)
                // We simply merge the two lists of booleans -- no conjuct is added
                // conjunct1 and conjunct2 don't change

                // query1.WhereCaluse AND query2.WhereCaluse
                Debug.Assert(g1 == null && g2 == null, "IJ does not affect g1 and g2");
                whereClause = BoolExpression.CreateAnd(query1.WhereClause, query2.WhereClause);
                break;

            case CellTreeOpType.LOJ:
                // conjunct1 does not change since D1 remains as is
                // Project[D1, (expr2 and cond2 and G2) as D2, A, B, C] Select[cond1] (T)
                // D1 does not change. New d2 is the list of booleans expressions
                // for query2 ANDed with g2 AND query2.WhereClause
                Debug.Assert(g1 == null, "LOJ does not affect g1");
                conjunct2 = BoolExpression.CreateAnd(query2.WhereClause, g2);
                // Just query1's whereclause
                whereClause = query1.WhereClause;
                break;

            case CellTreeOpType.FOJ:
            case CellTreeOpType.Union:
                // Project[(expr1 and cond1 and G1) as D1, (expr2 and cond2 and G2) as D2, A, B, C] Select[cond1] (T)
                // New D1 is a list -- newD1 = D1 AND query1.WhereClause AND g1
                // New D1 is a list -- newD2 = D2 AND query2.WhereClause AND g2
                conjunct1 = BoolExpression.CreateAnd(query1.WhereClause, g1);
                conjunct2 = BoolExpression.CreateAnd(query2.WhereClause, g2);

                // The new whereClause -- g1 AND query1.WhereCaluse OR g2 AND query2.WhereClause
                whereClause = BoolExpression.CreateOr(BoolExpression.CreateAnd(query1.WhereClause, g1),
                                                      BoolExpression.CreateAnd(query2.WhereClause, g2));
                break;

            case CellTreeOpType.LASJ:
                // conjunct1 does not change since D1 remains as is
                // Project[D1, (expr2 and cond2 and G2) as D2, A, B, C] Select[cond1] (T)
                // D1 does not change. New d2 is the list of booleans expressions
                // for query2 ANDed with g2 AND NOT query2.WhereClause
                Debug.Assert(g1 == null, "LASJ does not affect g1");
                conjunct2   = BoolExpression.CreateAnd(query2.WhereClause, g2);
                whereClause = BoolExpression.CreateAnd(query1.WhereClause, BoolExpression.CreateNot(conjunct2));
                break;

            default:
                Debug.Fail("Unsupported operator");
                break;
            }

            // Create the various remapped parts for the cell query --
            // boolean expressions, merged slots, whereclause, duplicate
            // elimination, join tree
            List <BoolExpression> boolExprs =
                MergeBoolExpressions(query1, query2, conjunct1, conjunct2, opType);

            //BoolExpression.RemapBools(boolExprs, remap);

            ProjectedSlot[] mergedSlots;
            if (false == ProjectedSlot.TryMergeRemapSlots(query1.ProjectedSlots, query2.ProjectedSlots, out mergedSlots))
            {
                // merging failed because two different right slots go to same left slot
                return(false);
            }

            whereClause = whereClause.RemapBool(remap);

            CellQuery.SelectDistinct elimDupl = MergeDupl(query1.SelectDistinctFlag, query2.SelectDistinctFlag);

            whereClause.ExpensiveSimplify();
            mergedQuery = new CellQuery(mergedSlots, whereClause,
                                        boolExprs, elimDupl, newRoot);
            return(true);
        }
 private static CellQuery.SelectDistinct MergeDupl(
     CellQuery.SelectDistinct d1,
     CellQuery.SelectDistinct d2)
 {
     return(d1 == CellQuery.SelectDistinct.Yes || d2 == CellQuery.SelectDistinct.Yes ? CellQuery.SelectDistinct.Yes : CellQuery.SelectDistinct.No);
 }
        internal static bool TryMergeTwoCellQueries(
            CellQuery query1,
            CellQuery query2,
            CellTreeOpType opType,
            out CellQuery mergedQuery)
        {
            mergedQuery = (CellQuery)null;
            BoolExpression boolExpression1 = (BoolExpression)null;
            BoolExpression boolExpression2 = (BoolExpression)null;

            switch (opType)
            {
            case CellTreeOpType.Union:
            case CellTreeOpType.FOJ:
                boolExpression1 = BoolExpression.True;
                boolExpression2 = BoolExpression.True;
                break;

            case CellTreeOpType.LOJ:
            case CellTreeOpType.LASJ:
                boolExpression2 = BoolExpression.True;
                break;
            }
            Dictionary <MemberPath, MemberPath> remap = new Dictionary <MemberPath, MemberPath>(MemberPath.EqualityComparer);

            if (!query1.Extent.Equals((object)query2.Extent))
            {
                return(false);
            }
            MemberPath     extentMemberPath = query1.SourceExtentMemberPath;
            BoolExpression and1             = BoolExpression.True;
            BoolExpression and2             = BoolExpression.True;
            BoolExpression boolExpression3  = (BoolExpression)null;

            switch (opType)
            {
            case CellTreeOpType.Union:
            case CellTreeOpType.FOJ:
                and1            = BoolExpression.CreateAnd(query1.WhereClause, boolExpression1);
                and2            = BoolExpression.CreateAnd(query2.WhereClause, boolExpression2);
                boolExpression3 = BoolExpression.CreateOr(BoolExpression.CreateAnd(query1.WhereClause, boolExpression1), BoolExpression.CreateAnd(query2.WhereClause, boolExpression2));
                break;

            case CellTreeOpType.LOJ:
                and2            = BoolExpression.CreateAnd(query2.WhereClause, boolExpression2);
                boolExpression3 = query1.WhereClause;
                break;

            case CellTreeOpType.IJ:
                boolExpression3 = BoolExpression.CreateAnd(query1.WhereClause, query2.WhereClause);
                break;

            case CellTreeOpType.LASJ:
                and2            = BoolExpression.CreateAnd(query2.WhereClause, boolExpression2);
                boolExpression3 = BoolExpression.CreateAnd(query1.WhereClause, BoolExpression.CreateNot(and2));
                break;
            }
            List <BoolExpression> boolExprs = CellTreeSimplifier.MergeBoolExpressions(query1, query2, and1, and2, opType);

            ProjectedSlot[] result;
            if (!ProjectedSlot.TryMergeRemapSlots(query1.ProjectedSlots, query2.ProjectedSlots, out result))
            {
                return(false);
            }
            BoolExpression whereClause = boolExpression3.RemapBool(remap);

            CellQuery.SelectDistinct elimDupl = CellTreeSimplifier.MergeDupl(query1.SelectDistinctFlag, query2.SelectDistinctFlag);
            whereClause.ExpensiveSimplify();
            mergedQuery = new CellQuery(result, whereClause, boolExprs, elimDupl, extentMemberPath);
            return(true);
        }