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));
        }
Пример #2
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);
        }