Ejemplo n.º 1
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)
        {
            var numSlotsAddedByChildBlock = childBlock.Slots.Count - TotalSlots;
            var slotInfos = new SlotInfo[TotalSlots + numSlotsAddedByChildBlock];
            for (var slotNum = 0; slotNum < TotalSlots; slotNum++)
            {
                var isProjected = childBlock.IsProjected(slotNum);
                var isRequiredByParent = parentRequiredSlots[slotNum];
                var slot = childBlock.SlotValue(slotNum);
                var 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
                    var 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"
                var slotInfo = new SlotInfo(isRequiredByParent && isProjected, isProjected, slot, outputMember);
                slotInfos[slotNum] = slotInfo;
            }
            for (var i = TotalSlots; i < TotalSlots + numSlotsAddedByChildBlock; i++)
            {
                var childAddedSlot = childBlock.QualifySlotWithBlockAlias(i);
                slotInfos[i] = new SlotInfo(true, true, childAddedSlot, childBlock.MemberPath(i));
            }
            return slotInfos;
        }