Example #1
0
        private SlotInfo[] CreateSlotInfosForCaseStatement(
            bool[] parentRequiredSlots,
            int foundSlot,
            CqlBlock childBlock,
            CaseStatement thisCaseStatement,
            IEnumerable <WithRelationship> withRelationships)
        {
            int num = childBlock.Slots.Count - this.TotalSlots;

            SlotInfo[] slotInfoArray = new SlotInfo[this.TotalSlots + num];
            for (int slotNum = 0; slotNum < this.TotalSlots; ++slotNum)
            {
                bool          isProjected        = childBlock.IsProjected(slotNum);
                bool          parentRequiredSlot = parentRequiredSlots[slotNum];
                ProjectedSlot slotValue          = childBlock.SlotValue(slotNum);
                MemberPath    outputMemberPath   = this.GetOutputMemberPath(slotNum);
                if (slotNum == foundSlot)
                {
                    slotValue   = (ProjectedSlot) new CaseStatementProjectedSlot(thisCaseStatement.DeepQualify(childBlock), withRelationships);
                    isProjected = true;
                }
                else if (isProjected && parentRequiredSlot)
                {
                    slotValue = (ProjectedSlot)childBlock.QualifySlotWithBlockAlias(slotNum);
                }
                SlotInfo slotInfo = new SlotInfo(parentRequiredSlot && isProjected, isProjected, slotValue, outputMemberPath);
                slotInfoArray[slotNum] = slotInfo;
            }
            for (int totalSlots = this.TotalSlots; totalSlots < this.TotalSlots + num; ++totalSlots)
            {
                QualifiedSlot qualifiedSlot = childBlock.QualifySlotWithBlockAlias(totalSlots);
                slotInfoArray[totalSlots] = new SlotInfo(true, true, (ProjectedSlot)qualifiedSlot, childBlock.MemberPath(totalSlots));
            }
            return(slotInfoArray);
        }
Example #2
0
        // <summary>
        // Creates a qualified slot "block_alias.slot_alias"
        // </summary>
        internal QualifiedSlot(CqlBlock block, ProjectedSlot slot)
        {
            DebugCheck.NotNull(block);
            DebugCheck.NotNull(slot);

            m_block = block;
            m_slot = slot; // Note: slot can be another qualified slot.
        }
Example #3
0
 internal SlotInfo(
     bool isRequiredByParent,
     bool isProjected,
     ProjectedSlot slotValue,
     MemberPath outputMember)
     : this(isRequiredByParent, isProjected, slotValue, outputMember, false)
 {
 }
Example #4
0
        // <summary>
        // Creates a qualified slot "block_alias.slot_alias"
        // </summary>
        internal QualifiedSlot(CqlBlock block, ProjectedSlot slot)
        {
            DebugCheck.NotNull(block);
            DebugCheck.NotNull(slot);

            m_block = block;
            m_slot  = slot; // Note: slot can be another qualified slot.
        }
 protected override bool IsEqualTo(ProjectedSlot right)
 {
     ConstantProjectedSlot rightSlot = right as ConstantProjectedSlot;
     if (rightSlot == null)
     {
         return false;
     }
     return Constant.EqualityComparer.Equals(m_constant, rightSlot.m_constant);
 }
        protected override bool IsEqualTo(ProjectedSlot right)
        {
            ViewCellSlot viewCellSlot = right as ViewCellSlot;

            if (viewCellSlot == null || this.m_slotNum != viewCellSlot.m_slotNum || !ProjectedSlot.EqualityComparer.Equals((ProjectedSlot)this.m_cSlot, (ProjectedSlot)viewCellSlot.m_cSlot))
            {
                return(false);
            }
            return(ProjectedSlot.EqualityComparer.Equals((ProjectedSlot)this.m_sSlot, (ProjectedSlot)viewCellSlot.m_sSlot));
        }
        protected override bool IsEqualTo(ProjectedSlot right)
        {
            ViewCellSlot rightSlot = right as ViewCellSlot;
            if (rightSlot == null)
            {
                return false;
            }

            return m_slotNum == rightSlot.m_slotNum &&
                MemberProjectedSlot.EqualityComparer.Equals(m_cSlot, rightSlot.m_cSlot) &&
                MemberProjectedSlot.EqualityComparer.Equals(m_sSlot, rightSlot.m_sSlot);
        }
Example #8
0
        /// <summary>
        /// Given the slot (<paramref name="foundSlot"/>) and its corresponding case statement (<paramref name="thisCaseStatement"/>),
        /// generates the slotinfos for the cql block producing the case statement.
        /// </summary>
        private SlotInfo[] CreateSlotInfosForCaseStatement(bool[] parentRequiredSlots,
                                                           int foundSlot,
                                                           CqlBlock childBlock,
                                                           CaseStatement thisCaseStatement,
                                                           IEnumerable <WithRelationship> withRelationships)
        {
            int numSlotsAddedByChildBlock = childBlock.Slots.Count - TotalSlots;

            SlotInfo[] slotInfos = new SlotInfo[TotalSlots + numSlotsAddedByChildBlock];
            for (int slotNum = 0; slotNum < TotalSlots; slotNum++)
            {
                bool          isProjected        = childBlock.IsProjected(slotNum);
                bool          isRequiredByParent = parentRequiredSlots[slotNum];
                ProjectedSlot slot         = childBlock.SlotValue(slotNum);
                MemberPath    outputMember = GetOutputMemberPath(slotNum);
                if (slotNum == foundSlot)
                {
                    // We need a case statement instead for this slot that we
                    // are handling right now
                    Debug.Assert(isRequiredByParent, "Case result not needed by parent");

                    // Get a case statement with all slots replaced by aliases slots
                    CaseStatement newCaseStatement = thisCaseStatement.DeepQualify(childBlock);
                    slot        = new CaseStatementProjectedSlot(newCaseStatement, withRelationships);
                    isProjected = true; // We are projecting this slot now
                }
                else if (isProjected && isRequiredByParent)
                {
                    // We only alias something that is needed and is being projected by the child.
                    // It is a qualified slot into the child block.
                    slot = childBlock.QualifySlotWithBlockAlias(slotNum);
                }
                // For slots, if it is not required by the parent, we want to
                // set the isRequiredByParent for this slot to be
                // false. Furthermore, we do not want to introduce any "NULL
                // AS something" at this stage for slots not being
                // projected. So if the child does not project that slot, we
                // declare it as not being required by the parent (if such a
                // NULL was needed, it would have been pushed all the way
                // down to a non-case block.
                // Essentially, from a Case statement's parent perspective,
                // it is saying "If you can produce a slot either by yourself
                // or your children, please do. Otherwise, do not concoct anything"
                SlotInfo slotInfo = new SlotInfo(isRequiredByParent && isProjected, isProjected, slot, outputMember);
                slotInfos[slotNum] = slotInfo;
            }
            for (int i = TotalSlots; i < TotalSlots + numSlotsAddedByChildBlock; i++)
            {
                QualifiedSlot childAddedSlot = childBlock.QualifySlotWithBlockAlias(i);
                slotInfos[i] = new SlotInfo(true, true, childAddedSlot, childBlock.MemberPath(i));
            }
            return(slotInfos);
        }
Example #9
0
        protected override bool IsEqualTo(ProjectedSlot right)
        {
            ViewCellSlot rightSlot = right as ViewCellSlot;

            if (rightSlot == null)
            {
                return(false);
            }

            return(m_slotNum == rightSlot.m_slotNum &&
                   MemberProjectedSlot.EqualityComparer.Equals(m_cSlot, rightSlot.m_cSlot) &&
                   MemberProjectedSlot.EqualityComparer.Equals(m_sSlot, rightSlot.m_sSlot));
        }
Example #10
0
 // effects: Given all the fields, just sets them. 
 internal CellQuery(
     ProjectedSlot[] projectedSlots,
     BoolExpression whereClause,
     List<BoolExpression> boolExprs,
     SelectDistinct elimDupl, MemberPath rootMember)
 {
     m_boolExprs = boolExprs;
     m_projectedSlots = projectedSlots;
     m_whereClause = whereClause;
     m_originalWhereClause = whereClause;
     m_selectDistinct = elimDupl;
     m_extentMemberPath = rootMember;
 }
Example #11
0
 internal SlotInfo(
     bool isRequiredByParent,
     bool isProjected,
     ProjectedSlot slotValue,
     MemberPath outputMember,
     bool enforceNotNull)
 {
     this.m_isRequiredByParent = isRequiredByParent;
     this.m_isProjected        = isProjected;
     this.m_slotValue          = slotValue;
     this.m_outputMember       = outputMember;
     this.m_enforceNotNull     = enforceNotNull;
 }
Example #12
0
 /// <summary>
 /// Creates a <see cref="SlotInfo"/> for a <see cref="CqlBlock"/> X with information about whether this slot is needed by X's parent
 /// (<paramref name="isRequiredByParent"/>), whether X projects it (<paramref name="isProjected"/>) along with the slot value (<paramref name="slotValue"/>) and
 /// the output member path (<paramref name="outputMember"/> (for regular/non-boolean slots) for the slot.
 /// </summary>
 /// <param name="enforceNotNull">We need to ensure that _from variables are never null since view generation uses 2-valued boolean logic.
 /// If <paramref name="enforceNotNull"/>=true, the generated Cql adds a condition (AND <paramref name="slotValue"/> NOT NULL).
 /// This flag is used only for boolean slots.</param>
 internal SlotInfo(bool isRequiredByParent, bool isProjected, ProjectedSlot slotValue, MemberPath outputMember, bool enforceNotNull)
 {
     m_isRequiredByParent = isRequiredByParent;
     m_isProjected        = isProjected;
     m_slotValue          = slotValue;
     m_outputMember       = outputMember;
     m_enforceNotNull     = enforceNotNull;
     Debug.Assert(false == m_isRequiredByParent || m_slotValue != null, "Required slots cannot be null");
     Debug.Assert(m_slotValue is QualifiedSlot ||
                  (m_slotValue == null && m_outputMember == null) || // unused boolean slot
                  (m_slotValue is BooleanProjectedSlot) == (m_outputMember == null),
                  "If slot is boolean slot, there is no member path for it and vice-versa");
 }
Example #13
0
 /// <summary>
 /// Creates a <see cref="SlotInfo"/> for a <see cref="CqlBlock"/> X with information about whether this slot is needed by X's parent
 /// (<paramref name="isRequiredByParent"/>), whether X projects it (<paramref name="isProjected"/>) along with the slot value (<paramref name="slotValue"/>) and 
 /// the output member path (<paramref name="outputMember"/> (for regular/non-boolean slots) for the slot.
 /// </summary>
 /// <param name="enforceNotNull">We need to ensure that _from variables are never null since view generation uses 2-valued boolean logic.
 /// If <paramref name="enforceNotNull"/>=true, the generated Cql adds a condition (AND <paramref name="slotValue"/> NOT NULL).
 /// This flag is used only for boolean slots.</param>
 internal SlotInfo(bool isRequiredByParent, bool isProjected, ProjectedSlot slotValue, MemberPath outputMember, bool enforceNotNull)
 {
     m_isRequiredByParent = isRequiredByParent;
     m_isProjected = isProjected;
     m_slotValue = slotValue;
     m_outputMember = outputMember;
     m_enforceNotNull = enforceNotNull;
     Debug.Assert(false == m_isRequiredByParent || m_slotValue != null, "Required slots cannot be null");
     Debug.Assert(m_slotValue is QualifiedSlot ||
                  (m_slotValue == null && m_outputMember == null) || // unused boolean slot
                  (m_slotValue is BooleanProjectedSlot) == (m_outputMember == null),
                  "If slot is boolean slot, there is no member path for it and vice-versa");
 }
Example #14
0
        /// <summary>
        /// Walks the chain of <see cref="QualifiedSlot"/>s starting from the current one and returns the original slot.
        /// </summary>
        internal ProjectedSlot GetOriginalSlot()
        {
            ProjectedSlot slot = m_slot;

            while (true)
            {
                QualifiedSlot qualifiedSlot = slot as QualifiedSlot;
                if (qualifiedSlot == null)
                {
                    break;
                }
                slot = qualifiedSlot.m_slot;
            }
            return(slot);
        }
Example #15
0
        internal ProjectedSlot GetOriginalSlot()
        {
            ProjectedSlot slot = this.m_slot;

            while (true)
            {
                QualifiedSlot qualifiedSlot = slot as QualifiedSlot;
                if (qualifiedSlot != null)
                {
                    slot = qualifiedSlot.m_slot;
                }
                else
                {
                    break;
                }
            }
            return(slot);
        }
        private bool AddRewritingToCaseStatement(
            Tile <FragmentQuery> rewriting,
            CaseStatement caseStatement,
            MemberPath currentPath,
            Constant domainValue)
        {
            BoolExpression boolExpression = BoolExpression.True;
            bool           flag           = this._qp.IsContainedIn((Tile <FragmentQuery>)QueryRewriter.CreateTile(this._domainQuery), rewriting);

            if (this._qp.IsDisjointFrom((Tile <FragmentQuery>)QueryRewriter.CreateTile(this._domainQuery), rewriting))
            {
                return(false);
            }
            int            num           = flag ? 1 : 0;
            ProjectedSlot  projectedSlot = !domainValue.HasNotNull() ? (ProjectedSlot) new ConstantProjectedSlot(domainValue) : (ProjectedSlot) new MemberProjectedSlot(currentPath);
            BoolExpression condition     = flag ? BoolExpression.True : QueryRewriter.TileToBoolExpr(rewriting);

            caseStatement.AddWhenThen(condition, projectedSlot);
            return(flag);
        }
Example #17
0
        /// <summary>
        /// Returns an array of size <see cref="TotalSlots"/> which indicates the slots that are needed to constuct value at <paramref name="caseMemberPath"/>,
        /// e.g., CPerson may need pid and name (say slots 2 and 5 - then bools[2] and bools[5] will be true.
        /// </summary>
        /// <param name="caseMemberPath">must be part of <see cref="m_caseStatements"/></param>
        private void GetRequiredSlotsForCaseMember(MemberPath caseMemberPath, bool[] requiredSlots)
        {
            Debug.Assert(true == m_caseStatements.ContainsKey(caseMemberPath), "Constructing case for regular field?");
            Debug.Assert(requiredSlots.Length == TotalSlots, "Invalid array size for populating required slots");

            CaseStatement statement = m_caseStatements[caseMemberPath];

            // Find the required slots from the when then clause conditions
            // and values
            bool requireThisSlot = false;

            foreach (CaseStatement.WhenThen clause in statement.Clauses)
            {
                clause.Condition.GetRequiredSlots(m_projectedSlotMap, requiredSlots);
                ProjectedSlot slot = clause.Value;
                if (!(slot is ConstantProjectedSlot))
                {
                    // If this slot is a scalar and a non-constant,
                    // we need the lower down blocks to generate it for us
                    requireThisSlot = true;
                }
            }

            EdmType edmType = caseMemberPath.EdmType;

            if (Helper.IsEntityType(edmType) || Helper.IsComplexType(edmType))
            {
                foreach (EdmType instantiatedType in statement.InstantiatedTypes)
                {
                    foreach (EdmMember childMember in Helper.GetAllStructuralMembers(instantiatedType))
                    {
                        int slotNum = GetSlotIndex(caseMemberPath, childMember);
                        requiredSlots[slotNum] = true;
                    }
                }
            }
            else if (caseMemberPath.IsScalarType())
            {
                // A scalar does not need anything per se to be constructed
                // unless it is referring to a field in the tree below, i.e., the THEN
                // slot is not a constant slot
                if (requireThisSlot)
                {
                    int caseMemberSlotNum = m_projectedSlotMap.IndexOf(caseMemberPath);
                    requiredSlots[caseMemberSlotNum] = true;
                }
            }
            else if (Helper.IsAssociationType(edmType))
            {
                // For an association, get the indices of the ends, e.g.,
                // CProduct and CCategory in CProductCategory1
                // Need just it's ends
                AssociationSet  associationSet  = (AssociationSet)caseMemberPath.Extent;
                AssociationType associationType = associationSet.ElementType;
                foreach (AssociationEndMember endMember in associationType.AssociationEndMembers)
                {
                    int slotNum = GetSlotIndex(caseMemberPath, endMember);
                    requiredSlots[slotNum] = true;
                }
            }
            else
            {
                // For a reference, all we need are the keys
                RefType refType = edmType as RefType;
                Debug.Assert(refType != null, "What other non scalars do we have? Relation end must be a reference type");

                EntityTypeBase refElementType = refType.ElementType;
                // Go through all the members of elementType and get the key properties

                EntitySet entitySet = MetadataHelper.GetEntitySetAtEnd((AssociationSet)caseMemberPath.Extent,
                                                                       (AssociationEndMember)caseMemberPath.LeafEdmMember);
                foreach (EdmMember entityMember in refElementType.KeyMembers)
                {
                    int slotNum = GetSlotIndex(caseMemberPath, entityMember);
                    requiredSlots[slotNum] = true;
                }
            }
        }
Example #18
0
 // <summary>
 // Creates a <see cref="SlotInfo" /> for a <see cref="CqlBlock" /> X with information about whether this slot is needed by X's parent
 // (<paramref name="isRequiredByParent" />), whether X projects it (<paramref name="isProjected" />) along with the slot value (
 // <paramref
 //     name="slotValue" />
 // ) and
 // the output member path (<paramref name="outputMember" /> (for regular/non-boolean slots) for the slot.
 // </summary>
 internal SlotInfo(bool isRequiredByParent, bool isProjected, ProjectedSlot slotValue, MemberPath outputMember)
     : this(isRequiredByParent, isProjected, slotValue, outputMember, false /* enforceNotNull */)
 {
 }
 private static bool TryGetInstantiatedType(ProjectedSlot slot, out EdmType type)
 {
     type = null;
     var constantSlot = slot as ConstantProjectedSlot;
     if (constantSlot != null)
     {
         var typeConstant = constantSlot.CellConstant as TypeConstant;
         if (typeConstant != null)
         {
             type = typeConstant.EdmType;
             return true;
         }
     }
     return false;
 }
Example #20
0
        // 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 static bool TryMergeTwoCellQueries(
            CellQuery query1, CellQuery query2, CellTreeOpType opType,
            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;
            }

            var 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
            var            conjunct1   = BoolExpression.True;
            var            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
            var 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);

            var elimDupl = MergeDupl(query1.SelectDistinctFlag, query2.SelectDistinctFlag);

            whereClause.ExpensiveSimplify();
            mergedQuery = new CellQuery(
                mergedSlots, whereClause,
                boolExprs, elimDupl, newRoot);
            return(true);
        }
        private static void WithRelationshipsClauseAsCql(
            Action<WithRelationship> emitWithRelationship, IEnumerable<WithRelationship> withRelationships, ProjectedSlot slot)
        {
            if (withRelationships != null
                && withRelationships.Count() > 0)
            {
                var constantSlot = slot as ConstantProjectedSlot;
                Debug.Assert(constantSlot != null, "WITH RELATIONSHIP clauses should be specified for type constant slots only.");
                var typeConstant = constantSlot.CellConstant as TypeConstant;
                Debug.Assert(typeConstant != null, "WITH RELATIONSHIP clauses should be there for type constants only.");
                var fromType = typeConstant.EdmType;

                foreach (var withRelationship in withRelationships)
                {
                    // Add With statement for the types that participate in the association.
                    if (withRelationship.FromEndEntityType.IsAssignableFrom(fromType))
                    {
                        emitWithRelationship(withRelationship);
                    }
                }
            }
        }
        /// <summary>
        ///     Simplifies the <see cref="CaseStatement" /> so that unnecessary WHEN/THENs for nulls/undefined values are eliminated.
        ///     Also, adds an ELSE clause if possible.
        /// </summary>
        internal void Simplify()
        {
            if (m_simplified)
            {
                return;
            }

            var clauses = new List<WhenThen>();
            // remove all WHEN clauses where the value gets set to "undefined"
            // We eliminate the last clause for now - we could determine the
            // "most complicated" WHEN clause and eliminate it
            var eliminatedNullClauses = false;
            foreach (var clause in m_clauses)
            {
                var constantSlot = clause.Value as ConstantProjectedSlot;
                // If null or undefined, remove it
                if (constantSlot != null
                    && (constantSlot.CellConstant.IsNull() || constantSlot.CellConstant.IsUndefined()))
                {
                    eliminatedNullClauses = true;
                }
                else
                {
                    clauses.Add(clause);
                    if (clause.Condition.IsTrue)
                    {
                        // none of subsequent case statements will be evaluated - ignore them
                        break;
                    }
                }
            }

            if (eliminatedNullClauses && clauses.Count == 0)
            {
                // There is nothing left -- we should add a null as the value
                m_elseValue = new ConstantProjectedSlot(Constant.Null);
            }

            // If we eliminated some undefined or null clauses, we do not want an else clause
            if (clauses.Count > 0
                && false == eliminatedNullClauses)
            {
                // turn the last WHEN clause into an ELSE
                var lastIndex = clauses.Count - 1;
                m_elseValue = clauses[lastIndex].Value;
                clauses.RemoveAt(lastIndex);
            }
            m_clauses = clauses;

            m_simplified = true;
        }
Example #23
0
        // requires: projectedSlotMap which contains a mapping of the fields
        // for "this" to integers 
        // effects: Align the fields of this cell query using the
        // projectedSlotMap and generates a new query into newMainQuery
        // Based on the re-aligned fields in this, re-aligns the
        // corresponding fields in otherQuery as well and modifies
        // newOtherQuery to contain it
        // Example:
        //    input:  Proj[A,B,"5"] = Proj[F,"7",G]
        //            Proj[C,B]     = Proj[H,I]
        //            projectedSlotMap: A -> 0, B -> 1, C -> 2
        //   output:  Proj[A,B,null] = Proj[F,"7",null]
        //            Proj[null,B,C] = Proj[null,I,H]
        internal void CreateFieldAlignedCellQueries(
            CellQuery otherQuery, MemberProjectionIndex projectedSlotMap,
            out CellQuery newMainQuery, out CellQuery newOtherQuery)
        {
            // mainSlots and otherSlots hold the new slots for two queries
            var numAlignedSlots = projectedSlotMap.Count;
            var mainSlots = new ProjectedSlot[numAlignedSlots];
            var otherSlots = new ProjectedSlot[numAlignedSlots];

            // Go through the slots for this query and find the new slot for them
            for (var i = 0; i < m_projectedSlots.Length; i++)
            {
                var slot = m_projectedSlots[i] as MemberProjectedSlot;
                Debug.Assert(slot != null, "All slots during cell normalization must field slots");
                // Get the the ith slot's variable and then get the
                // new slot number from the field map
                var newSlotNum = projectedSlotMap.IndexOf(slot.MemberPath);
                Debug.Assert(newSlotNum >= 0, "Field projected but not in projectedSlotMap");
                mainSlots[newSlotNum] = m_projectedSlots[i];
                otherSlots[newSlotNum] = otherQuery.m_projectedSlots[i];

                // We ignore constants -- note that this is not the
                // isHighpriority or discriminator case.  An example of this
                // is when (say) Address does not have zip but USAddress
                // does.  Then the constraint looks like Pi_NULL, A, B(E) =
                // Pi_x, y, z(S)

                // We don't care about this null in the view generation of
                // the left side. Note that this could happen in inheritance
                // or in cases when say the S side has 20 fields but the C
                // side has only 3 - the other 17 are null or default.

                // NOTE: We allow such constants only on the C side and not
                // ont the S side. Otherwise, we can have a situation Pi_A,
                // B, C(E) = Pi_5, y, z(S) Then someone can set A to 7 and we
                // will not roundtrip. We check for this in validation
            }

            // Make the new cell queries with the new slots
            newMainQuery = new CellQuery(this, mainSlots);
            newOtherQuery = new CellQuery(otherQuery, otherSlots);
        }
        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);
        }
 private static DbExpression CaseSlotValueAsCqt(
     DbExpression row, ProjectedSlot slot, MemberPath outputMember, IEnumerable<WithRelationship> withRelationships)
 {
     // We should never have THEN as a BooleanProjectedSlot.
     Debug.Assert(
         slot is MemberProjectedSlot || slot is QualifiedSlot || slot is ConstantProjectedSlot,
         "Case statement THEN can only have constants or members.");
     var cqt = slot.AsCqt(row, outputMember);
     cqt = WithRelationshipsClauseAsCqt(row, cqt, withRelationships, slot);
     return cqt;
 }
 private static void WithRelationshipsClauseAsEsql(
     StringBuilder builder, IEnumerable<WithRelationship> withRelationships, string blockAlias, int indentLevel, ProjectedSlot slot)
 {
     var first = true;
     WithRelationshipsClauseAsCql(
         // emitWithRelationship action
         (withRelationship) =>
             {
                 if (first)
                 {
                     builder.Append(" WITH ");
                     first = false;
                 }
                 withRelationship.AsEsql(builder, blockAlias, indentLevel);
             },
         withRelationships,
         slot);
 }
Example #27
0
 /// <summary>
 /// Creates a qualified slot "block_alias.slot_alias"
 /// </summary>
 internal QualifiedSlot(CqlBlock block, ProjectedSlot slot)
 {
     Debug.Assert(block != null && slot != null, "Null input to QualifiedSlot constructor");
     m_block = block;
     m_slot  = slot; // Note: slot can be another qualified slot.
 }
        private static DbExpression WithRelationshipsClauseAsCqt(
            DbExpression row, DbExpression slotValueExpr, IEnumerable<WithRelationship> withRelationships, ProjectedSlot slot)
        {
            var relatedEntityRefs = new List<DbRelatedEntityRef>();
            WithRelationshipsClauseAsCql(
                // emitWithRelationship action
                (withRelationship) => { relatedEntityRefs.Add(withRelationship.AsCqt(row)); },
                withRelationships,
                slot);

            if (relatedEntityRefs.Count > 0)
            {
                var typeConstructor = slotValueExpr as DbNewInstanceExpression;
                Debug.Assert(
                    typeConstructor != null && typeConstructor.ResultType.EdmType.BuiltInTypeKind == BuiltInTypeKind.EntityType,
                    "WITH RELATIONSHIP clauses should be specified for entity type constructors only.");
                return DbExpressionBuilder.CreateNewEntityWithRelationshipsExpression(
                    (EntityType)typeConstructor.ResultType.EdmType,
                    typeConstructor.Arguments,
                    relatedEntityRefs);
            }
            else
            {
                return slotValueExpr;
            }
        }
 protected override bool IsEqualTo(ProjectedSlot right)
 {
     var rightSlot = right as MemberProjectedSlot;
     if (rightSlot == null)
     {
         return false;
     }
     // We want equality of the paths
     return MemberPath.EqualityComparer.Equals(m_memberPath, rightSlot.m_memberPath);
 }
 /// <summary>
 /// Creates a qualified slot "block_alias.slot_alias"
 /// </summary>
 internal QualifiedSlot(CqlBlock block, ProjectedSlot slot)
 {
     Debug.Assert(block != null && slot != null, "Null input to QualifiedSlot constructor");
     m_block = block;
     m_slot = slot; // Note: slot can be another qualified slot.
 }
 private static StringBuilder CaseSlotValueAsEsql(
     StringBuilder builder, ProjectedSlot slot, MemberPath outputMember, string blockAlias,
     IEnumerable<WithRelationship> withRelationships, int indentLevel)
 {
     // We should never have THEN as a BooleanProjectedSlot.
     Debug.Assert(
         slot is MemberProjectedSlot || slot is QualifiedSlot || slot is ConstantProjectedSlot,
         "Case statement THEN can only have constants or members.");
     slot.AsEsql(builder, outputMember, blockAlias, 1);
     WithRelationshipsClauseAsEsql(builder, withRelationships, blockAlias, indentLevel, slot);
     return builder;
 }
Example #32
0
 internal QualifiedSlot(CqlBlock block, ProjectedSlot slot)
 {
     this.m_block = block;
     this.m_slot  = slot;
 }
Example #33
0
 // effects: Given an existing cellquery, makes a new one based on it
 // but uses the slots as specified with newSlots
 private CellQuery(CellQuery existing, ProjectedSlot[] newSlots)
     :
         this(newSlots, existing.m_whereClause, existing.m_boolExprs,
             existing.m_selectDistinct, existing.m_extentMemberPath)
 {
 }
        /// <summary>
        ///     Adds an expression of the form "WHEN <paramref name="condition" /> THEN <paramref name="value" />".
        ///     This operation is not allowed after the <see cref="Simplify" /> call.
        /// </summary>
        internal void AddWhenThen(BoolExpression condition, ProjectedSlot value)
        {
            Debug.Assert(!m_simplified, "Attempt to modify a simplified case statement");
            DebugCheck.NotNull(value);

            condition.ExpensiveSimplify();
            m_clauses.Add(new WhenThen(condition, value));
        }
 /// <summary>
 ///     Creates WHEN condition THEN value.
 /// </summary>
 internal WhenThen(BoolExpression condition, ProjectedSlot value)
 {
     m_condition = condition;
     m_value = value;
 }