/// <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);
        }
Esempio n. 2
0
        private CqlBlock GenerateCqlBlockTree()
        {
            bool[] requiredSlots = this.GetRequiredSlots();
            List <WithRelationship> withRelationships = new List <WithRelationship>();
            CqlBlock cqlBlock = this.m_view.ToCqlBlock(requiredSlots, this.m_identifiers, ref this.m_currentBlockNum, ref withRelationships);

            foreach (CaseStatement caseStatement in this.m_caseStatements.Values)
            {
                caseStatement.Simplify();
            }
            return(this.ConstructCaseBlocks(cqlBlock, (IEnumerable <WithRelationship>)withRelationships));
        }
Esempio n. 3
0
        // effects: Modifies builder to contain a Cql query corresponding to
        // the tree rooted at this
        internal override void ToFullString(StringBuilder builder)
        {
            int blockAliasNum = 0;

            // Get the required slots, get the block and then get the string
            bool[] requiredSlots = GetProjectedSlots();
            // Using empty identifiers over here since we do not use this for the actual CqlGeneration
            CqlIdentifiers          identifiers       = new CqlIdentifiers();
            List <WithRelationship> withRelationships = new List <WithRelationship>();
            CqlBlock block = ToCqlBlock(requiredSlots, identifiers, ref blockAliasNum, ref withRelationships);

            block.AsEsql(builder, false, 1);
        }
Esempio n. 4
0
        /// <summary>
        /// Given the <paramref name="viewBlock"/> tree, generates the case statement blocks on top of it (using <see cref="m_caseStatements"/>) and returns the resulting tree.
        /// One block per case statement is generated. Generated blocks are nested, with the <paramref name="viewBlock"/> is the innermost input.
        /// </summary>
        private CqlBlock ConstructCaseBlocks(CqlBlock viewBlock, IEnumerable <WithRelationship> withRelationships)
        {
            // Get the 0th slot only, i.e., the extent
            bool[] topSlots = new bool[TotalSlots];
            topSlots[0] = true;

            // all booleans in the top-level WHERE clause are required and get bubbled up
            // this makes some _fromX booleans be marked as 'required by parent'
            m_topLevelWhereClause.GetRequiredSlots(m_projectedSlotMap, topSlots);
            CqlBlock result = ConstructCaseBlocks(viewBlock, 0, topSlots, withRelationships);

            return(result);
        }
        internal CaseStatement DeepQualify(CqlBlock block)
        {
            CaseStatement caseStatement = new CaseStatement(this.m_memberPath);

            foreach (CaseStatement.WhenThen clause in this.m_clauses)
            {
                CaseStatement.WhenThen whenThen = clause.ReplaceWithQualifiedSlot(block);
                caseStatement.m_clauses.Add(whenThen);
            }
            if (this.m_elseValue != null)
            {
                caseStatement.m_elseValue = this.m_elseValue.DeepQualify(block);
            }
            caseStatement.m_simplified = this.m_simplified;
            return(caseStatement);
        }
Esempio n. 6
0
        // <summary>
        // Recursively qualifies all <see cref="ProjectedSlot" />s and returns a new deeply qualified
        // <see
        //     cref="CaseStatement" />
        // .
        // </summary>
        internal CaseStatement DeepQualify(CqlBlock block)
        {
            // Go through the whenthens and else and make a new case statement with qualified slots as needed.
            var result = new CaseStatement(m_memberPath);

            foreach (var whenThen in m_clauses)
            {
                var newClause = whenThen.ReplaceWithQualifiedSlot(block);
                result.m_clauses.Add(newClause);
            }
            if (m_elseValue != null)
            {
                result.m_elseValue = m_elseValue.DeepQualify(block);
            }
            result.m_simplified = m_simplified;
            return(result);
        }
Esempio n. 7
0
        private CqlBlock ConstructCaseBlocks(
            CqlBlock viewBlock,
            int startSlotNum,
            bool[] parentRequiredSlots,
            IEnumerable <WithRelationship> withRelationships)
        {
            int count             = this.m_projectedSlotMap.Count;
            int caseStatementSlot = this.FindNextCaseStatementSlot(startSlotNum, parentRequiredSlots, count);

            if (caseStatementSlot == -1)
            {
                return(viewBlock);
            }
            MemberPath projectedSlot = this.m_projectedSlotMap[caseStatementSlot];

            bool[] flagArray = new bool[this.TotalSlots];
            this.GetRequiredSlotsForCaseMember(projectedSlot, flagArray);
            for (int index = 0; index < this.TotalSlots; ++index)
            {
                if (parentRequiredSlots[index])
                {
                    flagArray[index] = true;
                }
            }
            CaseStatement caseStatement = this.m_caseStatements[projectedSlot];

            flagArray[caseStatementSlot] = caseStatement.DependsOnMemberValue;
            CqlBlock cqlBlock = this.ConstructCaseBlocks(viewBlock, caseStatementSlot + 1, flagArray, (IEnumerable <WithRelationship>)null);

            SlotInfo[] forCaseStatement = this.CreateSlotInfosForCaseStatement(parentRequiredSlots, caseStatementSlot, cqlBlock, caseStatement, withRelationships);
            ++this.m_currentBlockNum;
            BoolExpression whereClause = startSlotNum == 0 ? this.m_topLevelWhereClause : BoolExpression.True;

            if (startSlotNum == 0)
            {
                for (int index = 1; index < forCaseStatement.Length; ++index)
                {
                    forCaseStatement[index].ResetIsRequiredByParent();
                }
            }
            return((CqlBlock) new CaseCqlBlock(forCaseStatement, caseStatementSlot, cqlBlock, whereClause, this.m_identifiers, this.m_currentBlockNum));
        }
Esempio n. 8
0
        /// <summary>
        /// Creates new <see cref="ProjectedSlot"/> that is qualified with <paramref name="block"/>.CqlAlias.
        /// If current slot is composite (such as <see cref="CaseStatementProjectedSlot"/>, then this method recursively qualifies all parts
        /// and returns a new deeply qualified slot (as opposed to <see cref="CqlBlock.QualifySlotWithBlockAlias"/>).
        /// </summary>
        internal virtual ProjectedSlot DeepQualify(CqlBlock block)
        {
            QualifiedSlot result = new QualifiedSlot(block, this);

            return(result);
        }
Esempio n. 9
0
        // effects: Generates a SlotInfo object for a slot of a join node. It
        // uses the type of the join operation (opType), whether the slot is
        // required by the parent or not (isRequiredSlot), the children of
        // this node (children) and the number of the slotNum
        private SlotInfo GetJoinSlotInfo(CellTreeOpType opType, bool isRequiredSlot,
                                         List <CqlBlock> children, int slotNum, CqlIdentifiers identifiers)
        {
            if (false == isRequiredSlot)
            {
                // The slot will not be used. So we can set the projected slot to be null
                SlotInfo unrequiredSlotInfo = new SlotInfo(false, false, null, GetMemberPath(slotNum));
                return(unrequiredSlotInfo);
            }

            // For a required slot, determine the child who is contributing to this value
            int           childDefiningSlot = -1;
            CaseStatement caseForOuterJoins = null;

            for (int childNum = 0; childNum < children.Count; childNum++)
            {
                CqlBlock child = children[childNum];
                if (false == child.IsProjected(slotNum))
                {
                    continue;
                }
                // For keys, we can pick any child block. So the first
                // one that we find is fine as well
                if (IsKeySlot(slotNum))
                {
                    childDefiningSlot = childNum;
                    break;
                }
                else if (opType == CellTreeOpType.IJ)
                {
                    // For Inner Joins, most of the time, the entries will be
                    // the same in all the children. However, in some cases,
                    // we will end up with NULL in one child and an actual
                    // value in another -- we should pick up the actual value in that case
                    childDefiningSlot = GetInnerJoinChildForSlot(children, slotNum);
                    break;
                }
                else
                {
                    // For LOJs, we generate a case statement if more than
                    // one child generates the value - until then we do not
                    // create the caseForOuterJoins object
                    if (childDefiningSlot != -1)
                    {
                        // We really need a case statement now
                        // We have the value being generated by another child
                        // We need to fetch the variable from the appropriate child
                        Debug.Assert(false == IsBoolSlot(slotNum), "Boolean slots cannot come from two children");
                        if (caseForOuterJoins == null)
                        {
                            MemberPath outputMember = GetMemberPath(slotNum);
                            caseForOuterJoins = new CaseStatement(outputMember);
                            // Add the child that we had not added in the first shot
                            AddCaseForOuterJoins(caseForOuterJoins, children[childDefiningSlot], slotNum, identifiers);
                        }
                        AddCaseForOuterJoins(caseForOuterJoins, child, slotNum, identifiers);
                    }
                    childDefiningSlot = childNum;
                }
            }

            MemberPath    memberPath = GetMemberPath(slotNum);
            ProjectedSlot slot       = null;

            // Generate the slot value -- case statement slot, or a qualified slot or null or false.
            // If case statement slot has nothing, treat it as null/empty.
            if (caseForOuterJoins != null && (caseForOuterJoins.Clauses.Count > 0 || caseForOuterJoins.ElseValue != null))
            {
                caseForOuterJoins.Simplify();
                slot = new CaseStatementProjectedSlot(caseForOuterJoins, null);
            }
            else if (childDefiningSlot >= 0)
            {
                slot = children[childDefiningSlot].QualifySlotWithBlockAlias(slotNum);
            }
            else
            {
                // need to produce output slot, but don't have a value
                // output NULL for fields or False for bools
                if (IsBoolSlot(slotNum))
                {
                    slot = new BooleanProjectedSlot(BoolExpression.False, identifiers, SlotToBoolIndex(slotNum));
                }
                else
                {
                    slot = new ConstantProjectedSlot(Domain.GetDefaultValueForMemberPath(memberPath, GetLeaves(), ViewgenContext.Config), memberPath);
                }
            }

            // We need to ensure that _from variables are never null since
            // view generation uses 2-valued boolean logic.
            // They can become null in outer joins. We compensate for it by
            // adding AND NOT NULL condition on boolean slots coming from outer joins.
            bool enforceNotNull = IsBoolSlot(slotNum) &&
                                  ((opType == CellTreeOpType.LOJ && childDefiningSlot > 0) ||
                                   opType == CellTreeOpType.FOJ);
            // We set isProjected to be true since we have come up with some value for it
            SlotInfo slotInfo = new SlotInfo(true, true, slot, memberPath, enforceNotNull);

            return(slotInfo);
        }
Esempio n. 10
0
        // requires: node corresponds to an IJ, LOJ, FOJ node
        // effects: Given a union node and the slots required by the parent,
        // generates a CqlBlock for the subtree rooted at node
        private CqlBlock JoinToCqlBlock(bool[] requiredSlots, CqlIdentifiers identifiers, ref int blockAliasNum, ref List <WithRelationship> withRelationships)
        {
            int totalSlots = requiredSlots.Length;

            Debug.Assert(OpType == CellTreeOpType.IJ ||
                         OpType == CellTreeOpType.LOJ ||
                         OpType == CellTreeOpType.FOJ, "Only these join operations handled");

            List <CqlBlock> children = new List <CqlBlock>();
            List <Tuple <QualifiedSlot, MemberPath> > additionalChildSlots = new List <Tuple <QualifiedSlot, MemberPath> >();

            // First get the children nodes (FROM part)
            foreach (CellTreeNode child in Children)
            {
                // Determine the slots that are projected by this child.
                // These are the required slots as well - unlike Union, we do not need the child to project any extra nulls.
                bool[] childProjectedSlots = child.GetProjectedSlots();
                AndWith(childProjectedSlots, requiredSlots);
                CqlBlock childBlock = child.ToCqlBlock(childProjectedSlots, identifiers, ref blockAliasNum, ref withRelationships);
                children.Add(childBlock);
                for (int qualifiedSlotNumber = childProjectedSlots.Length; qualifiedSlotNumber < childBlock.Slots.Count; qualifiedSlotNumber++)
                {
                    additionalChildSlots.Add(Tuple.Create(childBlock.QualifySlotWithBlockAlias(qualifiedSlotNumber), childBlock.MemberPath(qualifiedSlotNumber)));
                }
                Debug.Assert(totalSlots == child.NumBoolSlots + child.NumProjectedSlots,
                             "Number of required slots is different from what each node in the tree has?");
            }

            // Now get the slots that are projected out by this node (SELECT part)
            SlotInfo[] slotInfos = new SlotInfo[totalSlots + additionalChildSlots.Count];
            for (int slotNum = 0; slotNum < totalSlots; slotNum++)
            {
                // Note: this call could create a CaseStatementSlot (i.e., slotInfo.SlotValue is CaseStatementSlot)
                // which uses "from" booleans that need to be projected by children
                SlotInfo slotInfo = GetJoinSlotInfo(OpType, requiredSlots[slotNum], children, slotNum, identifiers);
                slotInfos[slotNum] = slotInfo;
            }

            for (int i = 0, slotNum = totalSlots; slotNum < totalSlots + additionalChildSlots.Count; slotNum++, i++)
            {
                slotInfos[slotNum] = new SlotInfo(true, true, additionalChildSlots[i].Item1, additionalChildSlots[i].Item2);
            }

            // Generate the ON conditions: For each child, generate an ON
            // clause with the 0th child on the key fields
            List <JoinCqlBlock.OnClause> onClauses = new List <JoinCqlBlock.OnClause>();

            for (int i = 1; i < children.Count; i++)
            {
                CqlBlock child = children[i];
                JoinCqlBlock.OnClause onClause = new JoinCqlBlock.OnClause();
                foreach (int keySlotNum in this.KeySlots)
                {
                    if (ViewgenContext.Config.IsValidationEnabled)
                    {
                        Debug.Assert(children[0].IsProjected(keySlotNum), "Key is not in 0th child");
                        Debug.Assert(child.IsProjected(keySlotNum), "Key is not in child");
                    }
                    else
                    {
                        if (!child.IsProjected(keySlotNum) || !children[0].IsProjected(keySlotNum))
                        {
                            ErrorLog errorLog = new ErrorLog();
                            errorLog.AddEntry(new ErrorLog.Record(true, ViewGenErrorCode.NoJoinKeyOrFKProvidedInMapping,
                                                                  Strings.Viewgen_NoJoinKeyOrFK, ViewgenContext.AllWrappersForExtent, String.Empty));
                            ExceptionHelpers.ThrowMappingException(errorLog, ViewgenContext.Config);
                        }
                    }
                    var firstSlot    = children[0].QualifySlotWithBlockAlias(keySlotNum);
                    var secondSlot   = child.QualifySlotWithBlockAlias(keySlotNum);
                    var outputMember = slotInfos[keySlotNum].OutputMember;
                    onClause.Add(firstSlot, outputMember, secondSlot, outputMember);
                }
                onClauses.Add(onClause);
            }

            CqlBlock result = new JoinCqlBlock(OpType, slotInfos, children, onClauses, identifiers, ++blockAliasNum);

            return(result);
        }
Esempio n. 11
0
        // requires: node corresponds to a Union node
        // effects: Given a union node and the slots required by the parent,
        // generates a CqlBlock for the subtree rooted at node
        private CqlBlock UnionToCqlBlock(bool[] requiredSlots, CqlIdentifiers identifiers, ref int blockAliasNum, ref List <WithRelationship> withRelationships)
        {
            Debug.Assert(OpType == CellTreeOpType.Union);

            List <CqlBlock> children = new List <CqlBlock>();
            List <Tuple <CqlBlock, SlotInfo> > additionalChildSlots = new List <Tuple <CqlBlock, SlotInfo> >();

            int totalSlots = requiredSlots.Length;

            foreach (CellTreeNode child in Children)
            {
                // Unlike Join, we pass the requiredSlots from the parent as the requirement.
                bool[] childProjectedSlots = child.GetProjectedSlots();
                AndWith(childProjectedSlots, requiredSlots);
                CqlBlock childBlock = child.ToCqlBlock(childProjectedSlots, identifiers, ref blockAliasNum, ref withRelationships);
                for (int qualifiedSlotNumber = childProjectedSlots.Length; qualifiedSlotNumber < childBlock.Slots.Count; qualifiedSlotNumber++)
                {
                    additionalChildSlots.Add(Tuple.Create(childBlock, childBlock.Slots[qualifiedSlotNumber]));
                }

                // if required, but not projected, add NULL
                SlotInfo[] paddedSlotInfo = new SlotInfo[childBlock.Slots.Count];
                for (int slotNum = 0; slotNum < totalSlots; slotNum++)
                {
                    if (requiredSlots[slotNum] && !childProjectedSlots[slotNum])
                    {
                        if (IsBoolSlot(slotNum))
                        {
                            paddedSlotInfo[slotNum] = new SlotInfo(true /* is required */, true /* is projected */,
                                                                   new BooleanProjectedSlot(BoolExpression.False, identifiers, SlotToBoolIndex(slotNum)), null /* member path*/);
                        }
                        else
                        {
                            // NULL as projected slot
                            MemberPath memberPath = childBlock.MemberPath(slotNum);
                            paddedSlotInfo[slotNum] = new SlotInfo(true /* is required */, true /* is projected */,
                                                                   new ConstantProjectedSlot(Constant.Null, memberPath), memberPath);
                        }
                    }
                    else
                    {
                        paddedSlotInfo[slotNum] = childBlock.Slots[slotNum];
                    }
                }
                childBlock.Slots = new ReadOnlyCollection <SlotInfo>(paddedSlotInfo);
                children.Add(childBlock);
                Debug.Assert(totalSlots == child.NumBoolSlots + child.NumProjectedSlots,
                             "Number of required slots is different from what each node in the tree has?");
            }

            // We need to add the slots added by each child uniformly for others (as nulls) since this is a union operation.
            if (additionalChildSlots.Count != 0)
            {
                foreach (CqlBlock childBlock in children)
                {
                    SlotInfo[] childSlots = new SlotInfo[totalSlots + additionalChildSlots.Count];
                    childBlock.Slots.CopyTo(childSlots, 0);
                    int index = totalSlots;
                    foreach (var addtionalChildSlotInfo in additionalChildSlots)
                    {
                        var slotInfo = addtionalChildSlotInfo.Item2;
                        if (addtionalChildSlotInfo.Item1.Equals(childBlock))
                        {
                            childSlots[index] = new SlotInfo(true /* is required */, true /* is projected */, slotInfo.SlotValue, slotInfo.OutputMember);
                        }
                        else
                        {
                            childSlots[index] = new SlotInfo(true /* is required */, true /* is projected */,
                                                             new ConstantProjectedSlot(Constant.Null, slotInfo.OutputMember), slotInfo.OutputMember);
                        }
                        //move on to the next slot added by children.
                        index++;
                    }
                    childBlock.Slots = new ReadOnlyCollection <SlotInfo>(childSlots);
                }
            }

            // Create the slotInfos and then Union CqlBlock
            SlotInfo[] slotInfos = new SlotInfo[totalSlots + additionalChildSlots.Count];

            // We pick the slot references from the first child, just as convention
            // In a union, values come from both sides
            CqlBlock firstChild = children[0];

            for (int slotNum = 0; slotNum < totalSlots; slotNum++)
            {
                SlotInfo slotInfo = firstChild.Slots[slotNum];
                // A required slot is somehow projected by a child in Union, so set isProjected to be the same as isRequired.
                bool isRequired = requiredSlots[slotNum];
                slotInfos[slotNum] = new SlotInfo(isRequired, isRequired, slotInfo.SlotValue, slotInfo.OutputMember);
            }

            for (int slotNum = totalSlots; slotNum < totalSlots + additionalChildSlots.Count; slotNum++)
            {
                var aslot = firstChild.Slots[slotNum];
                slotInfos[slotNum] = new SlotInfo(true, true, aslot.SlotValue, aslot.OutputMember);
            }

            CqlBlock block = new UnionCqlBlock(slotInfos, children, identifiers, ++blockAliasNum);

            return(block);
        }
Esempio n. 12
0
 internal override ProjectedSlot DeepQualify(CqlBlock block)
 {
     return(this); // Nothing to create
 }
 internal override ProjectedSlot DeepQualify(CqlBlock block)
 {
     return((ProjectedSlot) new CaseStatementProjectedSlot(this.m_caseStatement.DeepQualify(block), (IEnumerable <WithRelationship>)null));
 }
 /// <summary>
 ///     Creates a boolean of the form "<paramref name="block" />.<paramref name="originalCellNum" />".
 /// </summary>
 internal QualifiedCellIdBoolean(CqlBlock block, CqlIdentifiers identifiers, int originalCellNum)
     : base(identifiers, originalCellNum)
 {
     m_block = block;
 }
Esempio n. 15
0
        // <summary>
        // Given the <paramref name="viewBlock" /> tree generated by the cell merging process and the
        // <paramref
        //     name="parentRequiredSlots" />
        // ,
        // generates the block tree for the case statement at or past the startSlotNum, i.e., only for case statements that are beyond startSlotNum.
        // </summary>
        private CqlBlock ConstructCaseBlocks(
            CqlBlock viewBlock, int startSlotNum, bool[] parentRequiredSlots, IEnumerable <WithRelationship> withRelationships)
        {
            var numMembers = m_projectedSlotMap.Count;
            // Find the next slot for which we have a case statement, i.e.,
            // which was in the multiconstants
            var foundSlot = FindNextCaseStatementSlot(startSlotNum, parentRequiredSlots, numMembers);

            if (foundSlot == -1)
            {
                // We have bottomed out - no more slots to generate cases for
                // Just get the base view block
                return(viewBlock);
            }

            // Compute the requiredSlots for this member, i.e., what slots are needed to produce this member.
            var thisMember        = m_projectedSlotMap[foundSlot];
            var thisRequiredSlots = new bool[TotalSlots];

            GetRequiredSlotsForCaseMember(thisMember, thisRequiredSlots);
            Debug.Assert(
                thisRequiredSlots.Length == parentRequiredSlots.Length &&
                thisRequiredSlots.Length == TotalSlots,
                "Number of slots in array should not vary across blocks");

            // Merge parent's requirements with this requirements
            for (var i = 0; i < TotalSlots; i++)
            {
                // We do ask the children to generate the slot that we are
                // producing if it is available
                if (parentRequiredSlots[i])
                {
                    thisRequiredSlots[i] = true;
                }
            }

            // If current case statement depends on its slot value, then make sure the value is produced by the child block.
            var thisCaseStatement = m_caseStatements[thisMember];

            thisRequiredSlots[foundSlot] = thisCaseStatement.DependsOnMemberValue;

            // Recursively, determine the block tree for slots beyond foundSlot.
            var childBlock = ConstructCaseBlocks(viewBlock, foundSlot + 1, thisRequiredSlots, null);

            // For each slot, create a SlotInfo object
            var slotInfos = CreateSlotInfosForCaseStatement(
                parentRequiredSlots, foundSlot, childBlock, thisCaseStatement, withRelationships);

            m_currentBlockNum++;

            // We have a where clause only at the top level
            var whereClause = startSlotNum == 0 ? m_topLevelWhereClause : BoolExpression.True;

            if (startSlotNum == 0)
            {
                // only slot #0 is required by parent; reset all 'required by parent' booleans introduced above
                for (var i = 1; i < slotInfos.Length; i++)
                {
                    slotInfos[i].ResetIsRequiredByParent();
                }
            }

            var result = new CaseCqlBlock(slotInfos, foundSlot, childBlock, whereClause, m_identifiers, m_currentBlockNum);

            return(result);
        }
Esempio n. 16
0
 internal override ProjectedSlot DeepQualify(CqlBlock block)
 {
     return((ProjectedSlot)this);
 }
 internal CaseStatement.WhenThen ReplaceWithQualifiedSlot(CqlBlock block)
 {
     return(new CaseStatement.WhenThen(this.m_condition, this.m_value.DeepQualify(block)));
 }
 internal virtual ProjectedSlot DeepQualify(CqlBlock block)
 {
     return((ProjectedSlot) new QualifiedSlot(block, this));
 }
Esempio n. 19
0
        /// <summary>
        ///     Creates new <see cref="ProjectedSlot" /> that is qualified with <paramref name="block" />.CqlAlias.
        ///     If current slot is composite (such as <see cref="CaseStatementProjectedSlot" />, then this method recursively qualifies all parts
        ///     and returns a new deeply qualified slot (as opposed to <see cref="CqlBlock.QualifySlotWithBlockAlias" />).
        /// </summary>
        internal override ProjectedSlot DeepQualify(CqlBlock block)
        {
            var newStatement = m_caseStatement.DeepQualify(block);

            return(new CaseStatementProjectedSlot(newStatement, null));
        }
        private CqlBlock UnionToCqlBlock(
            bool[] requiredSlots,
            CqlIdentifiers identifiers,
            ref int blockAliasNum,
            ref List <WithRelationship> withRelationships)
        {
            List <CqlBlock> children = new List <CqlBlock>();
            List <Tuple <CqlBlock, SlotInfo> > tupleList = new List <Tuple <CqlBlock, SlotInfo> >();
            int length1 = requiredSlots.Length;

            foreach (CellTreeNode child in this.Children)
            {
                bool[] projectedSlots = child.GetProjectedSlots();
                OpCellTreeNode.AndWith(projectedSlots, requiredSlots);
                CqlBlock cqlBlock = child.ToCqlBlock(projectedSlots, identifiers, ref blockAliasNum, ref withRelationships);
                for (int length2 = projectedSlots.Length; length2 < cqlBlock.Slots.Count; ++length2)
                {
                    tupleList.Add(Tuple.Create <CqlBlock, SlotInfo>(cqlBlock, cqlBlock.Slots[length2]));
                }
                SlotInfo[] slotInfoArray = new SlotInfo[cqlBlock.Slots.Count];
                for (int slotNum = 0; slotNum < length1; ++slotNum)
                {
                    if (requiredSlots[slotNum] && !projectedSlots[slotNum])
                    {
                        if (this.IsBoolSlot(slotNum))
                        {
                            slotInfoArray[slotNum] = new SlotInfo(true, true, (ProjectedSlot) new BooleanProjectedSlot(BoolExpression.False, identifiers, this.SlotToBoolIndex(slotNum)), (MemberPath)null);
                        }
                        else
                        {
                            MemberPath outputMember = cqlBlock.MemberPath(slotNum);
                            slotInfoArray[slotNum] = new SlotInfo(true, true, (ProjectedSlot) new ConstantProjectedSlot(Constant.Null), outputMember);
                        }
                    }
                    else
                    {
                        slotInfoArray[slotNum] = cqlBlock.Slots[slotNum];
                    }
                }
                cqlBlock.Slots = new ReadOnlyCollection <SlotInfo>((IList <SlotInfo>)slotInfoArray);
                children.Add(cqlBlock);
            }
            if (tupleList.Count != 0)
            {
                foreach (CqlBlock cqlBlock in children)
                {
                    SlotInfo[] array = new SlotInfo[length1 + tupleList.Count];
                    cqlBlock.Slots.CopyTo(array, 0);
                    int index = length1;
                    foreach (Tuple <CqlBlock, SlotInfo> tuple in tupleList)
                    {
                        SlotInfo slotInfo = tuple.Item2;
                        array[index] = !tuple.Item1.Equals((object)cqlBlock) ? new SlotInfo(true, true, (ProjectedSlot) new ConstantProjectedSlot(Constant.Null), slotInfo.OutputMember) : new SlotInfo(true, true, slotInfo.SlotValue, slotInfo.OutputMember);
                        ++index;
                    }
                    cqlBlock.Slots = new ReadOnlyCollection <SlotInfo>((IList <SlotInfo>)array);
                }
            }
            SlotInfo[] slotInfos = new SlotInfo[length1 + tupleList.Count];
            CqlBlock   cqlBlock1 = children[0];

            for (int index = 0; index < length1; ++index)
            {
                SlotInfo slot         = cqlBlock1.Slots[index];
                bool     requiredSlot = requiredSlots[index];
                slotInfos[index] = new SlotInfo(requiredSlot, requiredSlot, slot.SlotValue, slot.OutputMember);
            }
            for (int index = length1; index < length1 + tupleList.Count; ++index)
            {
                SlotInfo slot = cqlBlock1.Slots[index];
                slotInfos[index] = new SlotInfo(true, true, slot.SlotValue, slot.OutputMember);
            }
            return((CqlBlock) new UnionCqlBlock(slotInfos, children, identifiers, ++blockAliasNum));
        }