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); }
// <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); }