// requires: caseForOuterJoins corresponds the slot "slotNum" // effects: Adds a WhenThen corresponding to child to caseForOuterJoins. private void AddCaseForOuterJoins(CaseStatement caseForOuterJoins, CqlBlock child, int slotNum, CqlIdentifiers identifiers) { // Determine the cells that the slot comes from // and make an OR expression, e.g., WHEN _from0 or _from2 or ... THEN child[slotNum] ProjectedSlot childSlot = child.SlotValue(slotNum); ConstantProjectedSlot constantSlot = childSlot as ConstantProjectedSlot; if (constantSlot != null && constantSlot.CellConstant.IsNull()) { // NULL being generated by a child - don't need to project return; } BoolExpression originBool = BoolExpression.False; for (int i = 0; i < NumBoolSlots; i++) { int boolSlotNum = BoolIndexToSlot(i); if (child.IsProjected(boolSlotNum)) { // OR it to the expression QualifiedCellIdBoolean boolExpr = new QualifiedCellIdBoolean(child, identifiers, i); originBool = BoolExpression.CreateOr(originBool, BoolExpression.CreateLiteral(boolExpr, RightDomainMap)); } } // Qualify the slotNum with the child.CqlAlias for the THEN QualifiedSlot slot = child.QualifySlotWithBlockAlias(slotNum); caseForOuterJoins.AddWhenThen(originBool, slot); }
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); }
private void AddCaseForOuterJoins( CaseStatement caseForOuterJoins, CqlBlock child, int slotNum, CqlIdentifiers identifiers) { ConstantProjectedSlot constantProjectedSlot = child.SlotValue(slotNum) as ConstantProjectedSlot; if (constantProjectedSlot != null && constantProjectedSlot.CellConstant.IsNull()) { return; } BoolExpression or = BoolExpression.False; for (int index = 0; index < this.NumBoolSlots; ++index) { int slot = this.BoolIndexToSlot(index); if (child.IsProjected(slot)) { QualifiedCellIdBoolean qualifiedCellIdBoolean = new QualifiedCellIdBoolean(child, identifiers, index); or = BoolExpression.CreateOr(or, BoolExpression.CreateLiteral((BoolLiteral)qualifiedCellIdBoolean, this.RightDomainMap)); } } QualifiedSlot qualifiedSlot = child.QualifySlotWithBlockAlias(slotNum); caseForOuterJoins.AddWhenThen(or, (ProjectedSlot)qualifiedSlot); }
private CqlBlock JoinToCqlBlock( bool[] requiredSlots, CqlIdentifiers identifiers, ref int blockAliasNum, ref List <WithRelationship> withRelationships) { int length1 = requiredSlots.Length; List <CqlBlock> children = new List <CqlBlock>(); List <Tuple <QualifiedSlot, MemberPath> > tupleList = new List <Tuple <QualifiedSlot, MemberPath> >(); foreach (CellTreeNode child in this.Children) { bool[] projectedSlots = child.GetProjectedSlots(); OpCellTreeNode.AndWith(projectedSlots, requiredSlots); CqlBlock cqlBlock = child.ToCqlBlock(projectedSlots, identifiers, ref blockAliasNum, ref withRelationships); children.Add(cqlBlock); for (int length2 = projectedSlots.Length; length2 < cqlBlock.Slots.Count; ++length2) { tupleList.Add(Tuple.Create <QualifiedSlot, MemberPath>(cqlBlock.QualifySlotWithBlockAlias(length2), cqlBlock.MemberPath(length2))); } } SlotInfo[] slotInfos = new SlotInfo[length1 + tupleList.Count]; for (int slotNum = 0; slotNum < length1; ++slotNum) { SlotInfo joinSlotInfo = this.GetJoinSlotInfo(this.OpType, requiredSlots[slotNum], children, slotNum, identifiers); slotInfos[slotNum] = joinSlotInfo; } int index1 = 0; int index2 = length1; while (index2 < length1 + tupleList.Count) { slotInfos[index2] = new SlotInfo(true, true, (ProjectedSlot)tupleList[index1].Item1, tupleList[index1].Item2); ++index2; ++index1; } List <JoinCqlBlock.OnClause> onClauses = new List <JoinCqlBlock.OnClause>(); for (int index3 = 1; index3 < children.Count; ++index3) { CqlBlock cqlBlock = children[index3]; JoinCqlBlock.OnClause onClause = new JoinCqlBlock.OnClause(); foreach (int keySlot in this.KeySlots) { if (!this.ViewgenContext.Config.IsValidationEnabled && (!cqlBlock.IsProjected(keySlot) || !children[0].IsProjected(keySlot))) { ErrorLog errorLog = new ErrorLog(); errorLog.AddEntry(new ErrorLog.Record(ViewGenErrorCode.NoJoinKeyOrFKProvidedInMapping, Strings.Viewgen_NoJoinKeyOrFK, (IEnumerable <LeftCellWrapper>) this.ViewgenContext.AllWrappersForExtent, string.Empty)); ExceptionHelpers.ThrowMappingException(errorLog, this.ViewgenContext.Config); } QualifiedSlot leftSlot = children[0].QualifySlotWithBlockAlias(keySlot); QualifiedSlot rightSlot = cqlBlock.QualifySlotWithBlockAlias(keySlot); MemberPath outputMember = slotInfos[keySlot].OutputMember; onClause.Add(leftSlot, outputMember, rightSlot, outputMember); } onClauses.Add(onClause); } return((CqlBlock) new JoinCqlBlock(this.OpType, slotInfos, children, onClauses, identifiers, ++blockAliasNum)); }
/// <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); }
/// <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); }