// requires: domain not have any Negated constants other than NotNull // Also, cellQuery contains all final oneOfConsts or all partial oneOfConsts // cellquery must contain a whereclause of the form "True", "OneOfConst" or " // "OneOfConst AND ... AND OneOfConst" // slot must present in cellQuery and incomingDomain is the domain for it // effects: Returns the set of values that slot can take as restricted by cellQuery's whereClause private static bool TryGetDomainRestrictedByWhereClause(IEnumerable <Constant> domain, MemberProjectedSlot slot, CellQuery cellQuery, out CellConstantSet result) { var conditionsForSlot = cellQuery.GetConjunctsFromWhereClause() .Where(restriction => MemberPath.EqualityComparer.Equals(restriction.RestrictedMemberSlot.MemberPath, slot.MemberPath)) .Select(restriction => new CellConstantSet(restriction.Domain.Values, Constant.EqualityComparer)); //Debug.Assert(!conditionsForSlot.Skip(1).Any(), "More than one Clause with the same path"); if (!conditionsForSlot.Any()) { // If the slot was not mentioned in the query return the domain without restricting it result = new CellConstantSet(domain); return(false); } // Now get all the possible values from domain and conditionValues CellConstantSet possibleValues = DeterminePossibleValues(conditionsForSlot.SelectMany(m => m.Select(c => c)), domain); Domain restrictedDomain = new Domain(domain, possibleValues); foreach (var conditionValues in conditionsForSlot) { // Domain derived from Edm-Type INTERSECTED with Conditions restrictedDomain = restrictedDomain.Intersect(new Domain(conditionValues, possibleValues)); } result = new CellConstantSet(restrictedDomain.Values, Constant.EqualityComparer); return(!domain.SequenceEqual(result)); }
ComputeConstantDomainSetsForSlotsInQueryViews(IEnumerable <Cell> cells, EdmItemCollection edmItemCollection, bool isValidationEnabled) { Dictionary <MemberPath, CellConstantSet> cDomainMap = new Dictionary <MemberPath, CellConstantSet>(MemberPath.EqualityComparer); foreach (Cell cell in cells) { CellQuery cQuery = cell.CQuery; // Go through the conjuncts to get the constants (e.g., we // just don't want to NULL, NOT(NULL). We want to say that // the possible values are NULL, 4, NOT(NULL, 4) foreach (MemberRestriction restriction in cQuery.GetConjunctsFromWhereClause()) { MemberProjectedSlot slot = restriction.RestrictedMemberSlot; CellConstantSet cDomain = DeriveDomainFromMemberPath(slot.MemberPath, edmItemCollection, isValidationEnabled); // Now we add the domain of oneConst into this //Isnull=true and Isnull=false conditions should not contribute to a member's domain cDomain.AddRange(restriction.Domain.Values.Where(c => !(c.Equals(Constant.Null) || c.Equals(Constant.NotNull)))); CellConstantSet values; bool found = cDomainMap.TryGetValue(slot.MemberPath, out values); if (!found) { cDomainMap[slot.MemberPath] = cDomain; } else { values.AddRange(cDomain); } } } return(cDomainMap); }
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); }
// requires: domain not have any Negated constants other than NotNull // Also, cellQuery contains all final oneOfConsts or all partial oneOfConsts // cellquery must contain a whereclause of the form "True", "OneOfConst" or " // "OneOfConst AND ... AND OneOfConst" // slot must present in cellQuery and incomingDomain is the domain for it // effects: Returns the set of values that slot can take as restricted by cellQuery's whereClause private static bool TryGetDomainRestrictedByWhereClause(IEnumerable<Constant> domain, MemberProjectedSlot slot, CellQuery cellQuery, out CellConstantSet result) { var conditionsForSlot = cellQuery.GetConjunctsFromWhereClause() .Where(restriction => MemberPath.EqualityComparer.Equals(restriction.RestrictedMemberSlot.MemberPath, slot.MemberPath)) .Select(restriction => new CellConstantSet(restriction.Domain.Values, Constant.EqualityComparer)); //Debug.Assert(!conditionsForSlot.Skip(1).Any(), "More than one Clause with the same path"); if (!conditionsForSlot.Any()) { // If the slot was not mentioned in the query return the domain without restricting it result = new CellConstantSet(domain); return false; } // Now get all the possible values from domain and conditionValues CellConstantSet possibleValues = DeterminePossibleValues(conditionsForSlot.SelectMany(m => m.Select(c => c)), domain); Domain restrictedDomain = new Domain(domain, possibleValues); foreach (var conditionValues in conditionsForSlot) { // Domain derived from Edm-Type INTERSECTED with Conditions restrictedDomain = restrictedDomain.Intersect(new Domain(conditionValues, possibleValues)); } result = new CellConstantSet(restrictedDomain.Values, Constant.EqualityComparer); return !domain.SequenceEqual(result); }
// effects: Creates a map with all the condition member constants // from extentCells. viewtarget determines whether the view is an // update or query view internal MemberDomainMap(ViewTarget viewTarget, bool isValidationEnabled, IEnumerable <Cell> extentCells, EdmItemCollection edmItemCollection, ConfigViewGenerator config, Dictionary <EntityType, Set <EntityType> > inheritanceGraph) { m_conditionDomainMap = new Dictionary <MemberPath, CellConstantSet>(MemberPath.EqualityComparer); m_edmItemCollection = edmItemCollection; Dictionary <MemberPath, CellConstantSet> domainMap = null; if (viewTarget == ViewTarget.UpdateView) { domainMap = Domain.ComputeConstantDomainSetsForSlotsInUpdateViews(extentCells, m_edmItemCollection); } else { domainMap = Domain.ComputeConstantDomainSetsForSlotsInQueryViews(extentCells, m_edmItemCollection, isValidationEnabled); } foreach (Cell cell in extentCells) { CellQuery cellQuery = cell.GetLeftQuery(viewTarget); // Get the atoms from cellQuery and only keep the ones that // are condition members foreach (MemberRestriction condition in cellQuery.GetConjunctsFromWhereClause()) { // Note: TypeConditions are created using OneOfTypeConst and // scalars are created using OneOfScalarConst MemberPath memberPath = condition.RestrictedMemberSlot.MemberPath; Debug.Assert(condition is ScalarRestriction || condition is TypeRestriction, "Unexpected restriction"); // Take the narrowed domain from domainMap, if any CellConstantSet domainValues; if (!domainMap.TryGetValue(memberPath, out domainValues)) { domainValues = Domain.DeriveDomainFromMemberPath(memberPath, edmItemCollection, isValidationEnabled); } //Don't count conditions that are satisfied through IsNull=false if (!domainValues.Contains(Constant.Null)) { //multiple values of condition represent disjunction in conditions (not currently supported) // if there is any condition constant that is NotNull if (condition.Domain.Values.All(conditionConstant => (conditionConstant.Equals(Constant.NotNull)))) { continue; } //else there is atleast one condition value that is allowed, continue view generation } //------------------------------------------ //| Nullable | IsNull | Test case | //| T | T | T | //| T | F | T | //| F | T | F | //| F | F | T | //------------------------------------------ //IsNull condition on a member that is non nullable is an invalid condition if (domainValues.Count <= 0 || (!domainValues.Contains(Constant.Null) && condition.Domain.Values.Contains(Constant.Null))) { string message = System.Data.Entity.Strings.ViewGen_InvalidCondition(memberPath.PathToString(false)); ErrorLog.Record record = new ErrorLog.Record(true, ViewGenErrorCode.InvalidCondition, message, cell, String.Empty); ExceptionHelpers.ThrowMappingException(record, config); } if (memberPath.IsAlwaysDefined(inheritanceGraph) == false) { domainValues.Add(Constant.Undefined); } AddToDomainMap(memberPath, domainValues); } } // Fill up the domains for the remaining slots as well m_nonConditionDomainMap = new Dictionary <MemberPath, CellConstantSet>(MemberPath.EqualityComparer); foreach (Cell cell in extentCells) { CellQuery cellQuery = cell.GetLeftQuery(viewTarget); // Get the atoms from cellQuery and only keep the ones that // are condition members foreach (MemberProjectedSlot slot in cellQuery.GetAllQuerySlots()) { MemberPath member = slot.MemberPath; if (m_conditionDomainMap.ContainsKey(member) == false && m_nonConditionDomainMap.ContainsKey(member) == false) { CellConstantSet memberSet = Domain.DeriveDomainFromMemberPath(member, m_edmItemCollection, true /* Regardless of validation, leave the domain unbounded because this is not a condition member */); if (member.IsAlwaysDefined(inheritanceGraph) == false) { // nonConditionMember may belong to subclass memberSet.Add(Constant.Undefined); } memberSet = Domain.ExpandNegationsInDomain(memberSet, memberSet); m_nonConditionDomainMap.Add(member, new CellConstantSetInfo(memberSet, slot)); } } } }