internal override bool IsProjectedSlot(int slot) { CellQuery cellQuery = LeftCellWrapper.RightCellQuery; if (IsBoolSlot(slot)) { return(cellQuery.GetBoolVar(SlotToBoolIndex(slot)) != null); } else { return(cellQuery.ProjectedSlotAt(slot) != null); } }
// requires: RightCellQuery.Extent corresponds to a relationship set // effects: Returns the ends to which the key of the corresponding // table (i.e., the left query) maps to in the relationship set. For // example, if RightCellQuery.Extent is OrderOrders and it maps to // <oid, otherOid> of table SOrders with key oid, this returns the // end to which oid is mapped. Similarly, if we have a link table // with the whole key mapped to two ends of the association set, it // returns both ends private Set <AssociationEndMember> GetEndsForTablePrimaryKey() { CellQuery rightQuery = RightCellQuery; Set <AssociationEndMember> result = new Set <AssociationEndMember>(EqualityComparer <AssociationEndMember> .Default); // Get the key slots for the table (they are in the slotMap) and // check for that slot on the C-side foreach (int keySlot in m_memberMaps.ProjectedSlotMap.KeySlots) { MemberProjectedSlot slot = (MemberProjectedSlot)rightQuery.ProjectedSlotAt(keySlot); MemberPath path = slot.MemberPath; // See what end it maps to in the relationSet AssociationEndMember endMember = (AssociationEndMember)path.RootEdmMember; Debug.Assert(endMember != null, "Element in path before scalar path is not end property?"); result.Add(endMember); } Debug.Assert(result != null, "No end found for keyslots of table?"); return(result); }
// requires: this domainMap has been created for the C-side // effects: Fixes the mergedDomain map in this by merging entries // available in updateDomainMap internal static void PropagateUpdateDomainToQueryDomain(IEnumerable <Cell> cells, MemberDomainMap queryDomainMap, MemberDomainMap updateDomainMap) { foreach (Cell cell in cells) { CellQuery cQuery = cell.CQuery; CellQuery sQuery = cell.SQuery; for (int i = 0; i < cQuery.NumProjectedSlots; i++) { MemberProjectedSlot cSlot = cQuery.ProjectedSlotAt(i) as MemberProjectedSlot; MemberProjectedSlot sSlot = sQuery.ProjectedSlotAt(i) as MemberProjectedSlot; if (cSlot == null || sSlot == null) { continue; } // Get the domain for sSlot and merge with cSlot's MemberPath cPath = cSlot.MemberPath; MemberPath sPath = sSlot.MemberPath; CellConstantSet cDomain = queryDomainMap.GetDomainInternal(cPath); CellConstantSet sDomain = updateDomainMap.GetDomainInternal(sPath); // skip NULL because if c-side member is nullable, it's already there, and otherwise can't be taken // skip negated because negated values are translated in a special way cDomain.Unite(sDomain.Where(constant => !constant.IsNull() && !(constant is NegatedConstant))); if (updateDomainMap.IsConditionMember(sPath) && !queryDomainMap.IsConditionMember(cPath)) { // record this member so KB knows we have to generate constraints for it queryDomainMap.m_projectedConditionMembers.Add(cPath); } } } ExpandNegationsInDomainMap(queryDomainMap.m_conditionDomainMap); ExpandNegationsInDomainMap(queryDomainMap.m_nonConditionDomainMap); }
ComputeConstantDomainSetsForSlotsInUpdateViews(IEnumerable <Cell> cells, EdmItemCollection edmItemCollection) { Dictionary <MemberPath, CellConstantSet> updateDomainMap = new Dictionary <MemberPath, CellConstantSet>(MemberPath.EqualityComparer); foreach (Cell cell in cells) { CellQuery cQuery = cell.CQuery; CellQuery sQuery = cell.SQuery; foreach (MemberProjectedSlot sSlot in sQuery.GetConjunctsFromWhereClause().Select(oneOfConst => oneOfConst.RestrictedMemberSlot)) { // obtain initial slot domain and restrict it if the slot has conditions CellConstantSet restrictedDomain; bool wasDomainRestricted = GetRestrictedOrUnrestrictedDomain(sSlot, sQuery, edmItemCollection, out restrictedDomain); // Suppose that we have a cell: // Proj(ID, A) WHERE(A=5) FROM E = Proj(ID, B) FROM T // In the above cell, B on the S-side is 5 and we add that to its range. But if B had a restriction, // we do not add 5. Note that do we not have a problem w.r.t. possibleValues since if A=5 and B=1, we have an // empty cell -- we should catch that as an error. If A = 5 and B = 5 is present then restrictedDomain // and domainValues are the same // if no restriction on the S-side and the slot is projected then take the domain from the C-side if (!wasDomainRestricted) { int projectedPosition = sQuery.GetProjectedPosition(sSlot); if (projectedPosition >= 0) { // get the domain of the respective C-side slot MemberProjectedSlot cSlot = cQuery.ProjectedSlotAt(projectedPosition) as MemberProjectedSlot; Debug.Assert(cSlot != null, "Assuming constants are not projected"); wasDomainRestricted = GetRestrictedOrUnrestrictedDomain(cSlot, cQuery, edmItemCollection, out restrictedDomain); if (!wasDomainRestricted) { continue; } } } // Add the default value to the domain MemberPath sSlotMemberPath = sSlot.MemberPath; Constant defaultValue; if (TryGetDefaultValueForMemberPath(sSlotMemberPath, out defaultValue)) { restrictedDomain.Add(defaultValue); } // add all constants appearing in the domain to sDomainMap CellConstantSet sSlotDomain; if (!updateDomainMap.TryGetValue(sSlotMemberPath, out sSlotDomain)) { updateDomainMap[sSlotMemberPath] = restrictedDomain; } else { sSlotDomain.AddRange(restrictedDomain); } } } return(updateDomainMap); }
internal override CqlBlock ToCqlBlock(bool[] requiredSlots, CqlIdentifiers identifiers, ref int blockAliasNum, ref List <WithRelationship> withRelationships) { // Get the projected slots and the boolean expressions int totalSlots = requiredSlots.Length; CellQuery cellQuery = LeftCellWrapper.RightCellQuery; SlotInfo[] projectedSlots = new SlotInfo[totalSlots]; Debug.Assert(cellQuery.NumProjectedSlots + cellQuery.NumBoolVars == totalSlots, "Wrong number of projected slots in node"); Debug.Assert(cellQuery.NumProjectedSlots == ProjectedSlotMap.Count, "Different number of slots in cell query and what we have mappings for"); // Add the regular fields for (int i = 0; i < cellQuery.NumProjectedSlots; i++) { ProjectedSlot slot = cellQuery.ProjectedSlotAt(i); // If the slot is not null, we will project it // For extents, we say that all requiredlots are the only the // ones that are CLR non-null. Recall that "real" nulls are // handled by having a CellConstant.Null in ConstantSlot if (requiredSlots[i] && slot == null) { MemberPath memberPath = ProjectedSlotMap[i]; ConstantProjectedSlot defaultValue = new ConstantProjectedSlot(Domain.GetDefaultValueForMemberPath(memberPath, GetLeaves(), ViewgenContext.Config), memberPath); cellQuery.FixMissingSlotAsDefaultConstant(i, defaultValue); slot = defaultValue; } SlotInfo slotInfo = new SlotInfo(requiredSlots[i], slot != null, slot, ProjectedSlotMap[i]); projectedSlots[i] = slotInfo; } // Add the boolean fields for (int boolNum = 0; boolNum < cellQuery.NumBoolVars; boolNum++) { BoolExpression expr = cellQuery.GetBoolVar(boolNum); BooleanProjectedSlot boolSlot; if (expr != null) { boolSlot = new BooleanProjectedSlot(expr, identifiers, boolNum); } else { boolSlot = new BooleanProjectedSlot(BoolExpression.False, identifiers, boolNum); } int slotIndex = BoolIndexToSlot(boolNum); SlotInfo slotInfo = new SlotInfo(requiredSlots[slotIndex], expr != null, boolSlot, null); projectedSlots[slotIndex] = slotInfo; } // See if we are generating a query view and whether there are any colocated foreign keys for which // we have to add With statements. IEnumerable <SlotInfo> totalProjectedSlots = projectedSlots; if ((cellQuery.Extent.EntityContainer.DataSpace == DataSpace.SSpace) && (this.m_cellWrapper.LeftExtent.BuiltInTypeKind == BuiltInTypeKind.EntitySet)) { IEnumerable <StorageAssociationSetMapping> associationSetMaps = this.ViewgenContext.EntityContainerMapping.GetRelationshipSetMappingsFor(this.m_cellWrapper.LeftExtent, cellQuery.Extent); List <SlotInfo> foreignKeySlots = new List <SlotInfo>(); foreach (StorageAssociationSetMapping colocatedAssociationSetMap in associationSetMaps) { WithRelationship withRelationship; if (TryGetWithRelationship(colocatedAssociationSetMap, this.m_cellWrapper.LeftExtent, cellQuery.SourceExtentMemberPath, ref foreignKeySlots, out withRelationship)) { withRelationships.Add(withRelationship); totalProjectedSlots = projectedSlots.Concat(foreignKeySlots); } } } ExtentCqlBlock result = new ExtentCqlBlock(cellQuery.Extent, cellQuery.SelectDistinctFlag, totalProjectedSlots.ToArray(), cellQuery.WhereClause, identifiers, ++blockAliasNum); return(result); }