// effects: Given a set of values in domain1 and domain2, // Returns all possible positive values that are present in domain1 and domain2 private static CellConstantSet DeterminePossibleValues(IEnumerable <Constant> domain1, IEnumerable <Constant> domain2) { CellConstantSet union = new CellConstantSet(domain1, Constant.EqualityComparer).Union(domain2); CellConstantSet result = DeterminePossibleValues(union); return(result); }
//True = domain is restricted, False = domain is not restricted (because there is no condition) private static bool GetRestrictedOrUnrestrictedDomain(MemberProjectedSlot slot, CellQuery cellQuery, EdmItemCollection edmItemCollection, out CellConstantSet domain) { CellConstantSet domainValues = DeriveDomainFromMemberPath(slot.MemberPath, edmItemCollection, true /* leaveDomainUnbounded */); //Note, out domain is set even in the case where method call returns false return(TryGetDomainRestrictedByWhereClause(domainValues, slot, cellQuery, out domain)); }
// 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: Given a set of values in domain // Returns all possible values that are present in domain. static CellConstantSet DeterminePossibleValues(IEnumerable <Constant> domain) { // E.g., if we have 1, 2, NOT(1) --> Result = 1, 2 // 1, NOT(1, 2) --> Result = 1, 2 // 1, 2, NOT(NULL) --> Result = 1, 2, NULL // 1, 2, NOT(2), NOT(3, 4) --> Result = 1, 2, 3, 4 CellConstantSet result = new CellConstantSet(Constant.EqualityComparer); foreach (Constant constant in domain) { NegatedConstant negated = constant as NegatedConstant; if (negated != null) { // Go through all the constants in negated and add them to domain // We add them to possible values also even if (say) Null is not allowed because we want the complete // partitioning of the space, e.g., if the values specified by the caller are 1, NotNull -> we want 1, Null foreach (Constant constElement in negated.Elements) { Debug.Assert(constElement as NegatedConstant == null, "Negated cell constant inside NegatedCellConstant"); result.Add(constElement); } } else { result.Add(constant); } } return(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); }
// effects: Given a set of values in domain, "normalizes" it, i.e., // all positive constants are seperated out and any negative constant // is changed s.t. it is the negative of all positive values // extraValues indicates more constants that domain could take, e.g., // domain could be "1, 2, NOT(1, 2)", extraValues could be "3". In // this case, we return "1, 2, 3, NOT(1, 2, 3)" internal static CellConstantSet ExpandNegationsInDomain(IEnumerable <Constant> domain, IEnumerable <Constant> otherPossibleValues) { //Finds all constants referenced in (domain UNION extraValues) e.g: 1, NOT(2) => 1, 2 CellConstantSet possibleValues = DeterminePossibleValues(domain, otherPossibleValues); // For NOT --> Add all constants into d that are present in p but // not in the NOT // v = 1, NOT(1, 2); p = 1, 2, 3 => d = 1, NOT(1, 2, 3), 3 // v = 1, 2, NOT(1); p = 1, 2, 4 => d = 1, 2, 4, NOT(1, 2, 4) // v = 1, 2, NOT(1, 2, 4), NOT(1, 2, 4, 5); p = 1, 2, 4, 5, 6 => d = 1, 2, 5, 6, NOT(1, 2, 4, 5, 6) // NotNull works naturally now. If possibleValues has (1, 2, NULL) // and values has NOT(NULL), add 1, 2 to m_domain CellConstantSet result = new Set <Constant>(Constant.EqualityComparer); foreach (Constant constant in domain) { NegatedConstant negated = constant as NegatedConstant; if (negated != null) { result.Add(new NegatedConstant(possibleValues)); // Compute all elements in possibleValues that are not present in negated. E.g., if // negated is NOT(1, 2, 3) and possibleValues is 1, 2, 3, // 4, we need to add 4 to result CellConstantSet remainingElements = possibleValues.Difference(negated.Elements); result.AddRange(remainingElements); } else { result.Add(constant); } } return(result); }
// effects: Given a member, determines all possible values that can be created from Metadata internal static CellConstantSet DeriveDomainFromMemberPath(MemberPath memberPath, EdmItemCollection edmItemCollection, bool leaveDomainUnbounded) { CellConstantSet domain = DeriveDomainFromType(memberPath.EdmType, edmItemCollection, leaveDomainUnbounded); if (memberPath.IsNullable) { domain.Add(Constant.Null); } return(domain); }
// effects: Given a type, determines all possible values that can be created from Metadata private static CellConstantSet DeriveDomainFromType(EdmType type, EdmItemCollection edmItemCollection, bool leaveDomainUnbounded) { CellConstantSet domain = null; if (Helper.IsScalarType(type)) { // Get the domain for scalars -- for booleans, we special case. if (MetadataHelper.HasDiscreteDomain(type)) { Debug.Assert(Helper.AsPrimitive(type).PrimitiveTypeKind == PrimitiveTypeKind.Boolean, "Only boolean type has discrete domain."); // Closed domain domain = new Set <Constant>(CreateList(true, false), Constant.EqualityComparer); } else { // Unbounded domain domain = new Set <Constant>(Constant.EqualityComparer); if (leaveDomainUnbounded) { domain.Add(Constant.NotNull); } } } else //Type Constants - Domain is all possible concrete subtypes { Debug.Assert(Helper.IsEntityType(type) || Helper.IsComplexType(type) || Helper.IsRefType(type) || Helper.IsAssociationType(type)); // Treat ref types as their referenced entity types if (Helper.IsRefType(type)) { type = ((RefType)type).ElementType; } List <Constant> types = new List <Constant>(); foreach (EdmType derivedType in MetadataHelper.GetTypeAndSubtypesOf(type, edmItemCollection, false /*includeAbstractTypes*/)) { TypeConstant derivedTypeConstant = new TypeConstant(derivedType); types.Add(derivedTypeConstant); } domain = new Set <Constant>(types, Constant.EqualityComparer); } Debug.Assert(domain != null, "Domain not set up for some type"); return(domain); }
// effects: Given a set of values in domain1 and domain2, // Returns all possible positive values that are present in domain1 and domain2 private static CellConstantSet DeterminePossibleValues(IEnumerable<Constant> domain1, IEnumerable<Constant> domain2) { CellConstantSet union = new CellConstantSet(domain1, Constant.EqualityComparer).Union(domain2); CellConstantSet result = DeterminePossibleValues(union); return result; }
// 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); }
//True = domain is restricted, False = domain is not restricted (because there is no condition) private static bool GetRestrictedOrUnrestrictedDomain(MemberProjectedSlot slot, CellQuery cellQuery, EdmItemCollection edmItemCollection, out CellConstantSet domain) { CellConstantSet domainValues = DeriveDomainFromMemberPath(slot.MemberPath, edmItemCollection, true /* leaveDomainUnbounded */); //Note, out domain is set even in the case where method call returns false return TryGetDomainRestrictedByWhereClause(domainValues, slot, cellQuery, out domain); }
// effects: Given a set of values in domain // Returns all possible values that are present in domain. static CellConstantSet DeterminePossibleValues(IEnumerable<Constant> domain) { // E.g., if we have 1, 2, NOT(1) --> Result = 1, 2 // 1, NOT(1, 2) --> Result = 1, 2 // 1, 2, NOT(NULL) --> Result = 1, 2, NULL // 1, 2, NOT(2), NOT(3, 4) --> Result = 1, 2, 3, 4 CellConstantSet result = new CellConstantSet(Constant.EqualityComparer); foreach (Constant constant in domain) { NegatedConstant negated = constant as NegatedConstant; if (negated != null) { // Go through all the constants in negated and add them to domain // We add them to possible values also even if (say) Null is not allowed because we want the complete // partitioning of the space, e.g., if the values specified by the caller are 1, NotNull -> we want 1, Null foreach (Constant constElement in negated.Elements) { Debug.Assert(constElement as NegatedConstant == null, "Negated cell constant inside NegatedCellConstant"); result.Add(constElement); } } else { result.Add(constant); } } return result; }