// <summary> // Takes in a JoinTreeNode and a Contition Property Map and creates an BoolExpression // for the Condition Map. // </summary> private static BoolExpression GetConditionExpression(MemberPath member, ConditionPropertyMapping conditionMap) { //Get the member for which the condition is being specified EdmMember conditionMember = (conditionMap.Column != null) ? conditionMap.Column : conditionMap.Property; var conditionMemberNode = new MemberPath(member, conditionMember); //Check if this is a IsNull condition MemberRestriction conditionExpression = null; if (conditionMap.IsNull.HasValue) { // for conditions on scalars, create NodeValue nodes, otherwise NodeType var conditionConstant = conditionMap.IsNull.Value ? Constant.Null : Constant.NotNull; if (MetadataHelper.IsNonRefSimpleMember(conditionMember)) { conditionExpression = new ScalarRestriction(conditionMemberNode, conditionConstant); } else { conditionExpression = new TypeRestriction(conditionMemberNode, conditionConstant); } } else { conditionExpression = new ScalarRestriction(conditionMemberNode, new ScalarConstant(conditionMap.Value)); } Debug.Assert(conditionExpression != null); return(BoolExpression.CreateLiteral(conditionExpression, null)); }
// effects: Given a sequence of constants that need to be propagated // to the C-side and the current boolean expression, generates a new // expression of the form "expression AND C-side Member in constants" // expression" and returns it. Each constant is propagated only if member // is projected -- if member is not projected, returns "expression" internal static BoolExpression PropagateCellConstantsToWhereClause( LeftCellWrapper wrapper, BoolExpression expression, Constant constant, MemberPath member, MemberMaps memberMaps) { var joinSlot = wrapper.GetCSideMappedSlotForSMember(member); if (joinSlot == null) { return(expression); } var negatedConstant = constant as NegatedConstant; // Look at the constants and determine if they correspond to // typeConstants or scalarConstants // This slot is being projected. We need to add a where clause element Debug.Assert(constant is ScalarConstant || constant.IsNull() || negatedConstant != null, "Invalid type of constant"); // We want the possible values for joinSlot.MemberPath which is a // C-side element -- so we use the queryDomainMap var possibleValues = memberMaps.QueryDomainMap.GetDomain(joinSlot.MemberPath); // Note: the values in constaints can be null or not null as // well (i.e., just not scalarConstants) var allowedValues = new Set <Constant>(Constant.EqualityComparer); if (negatedConstant != null) { // select all values from the c-side domain that are not in the negated set allowedValues.Unite(possibleValues); allowedValues.Difference(negatedConstant.Elements); } else { allowedValues.Add(constant); } MemberRestriction restriction = new ScalarRestriction(joinSlot.MemberPath, allowedValues, possibleValues); var result = BoolExpression.CreateAnd(expression, BoolExpression.CreateLiteral(restriction, memberMaps.QueryDomainMap)); return(result); }
/// <summary> /// Given a LeftCellWrapper for the S-side fragment and a non-nullable colum m, return a CQuery with nullability condition /// appended to Cquery of c-side member that column m is mapped to /// </summary> private static FragmentQuery AddNullConditionOnCSideFragment(LeftCellWrapper wrapper, MemberPath member, MemberMaps memberMaps) { MemberProjectedSlot projectedSlot = wrapper.GetCSideMappedSlotForSMember(member); if (projectedSlot == null || !projectedSlot.MemberPath.IsNullable) //don't bother checking further fore non nullable C-side member { return(null); } BoolExpression expression = wrapper.RightCellQuery.WhereClause; IEnumerable <Constant> possibleValues = memberMaps.QueryDomainMap.GetDomain(projectedSlot.MemberPath); Set <Constant> allowedValues = new Set <Constant>(Constant.EqualityComparer); allowedValues.Add(Constant.Null); //Create a condition as conjunction of originalCondition and slot IS NULL MemberRestriction restriction = new ScalarRestriction(projectedSlot.MemberPath, allowedValues, possibleValues); BoolExpression resultingExpr = BoolExpression.CreateAnd(expression, BoolExpression.CreateLiteral(restriction, memberMaps.QueryDomainMap)); return(FragmentQuery.Create(resultingExpr)); }
/// <summary> /// Finds errors related to splitting Conditions /// 1. Condition value is repeated across multiple types /// 2. A Column/attribute is mapped but also used as a condition /// </summary> private void MatchConditionErrors() { List <LeftCellWrapper> leftCellWrappers = m_viewgenContext.AllWrappersForExtent; //Stores violating Discriminator (condition member) so that we dont repeat the same error Set <MemberPath> mappedConditionMembers = new Set <MemberPath>(); //Both of these data-structs help in finding duplicate conditions Set <CompositeCondition> setOfconditions = new Set <CompositeCondition>(new ConditionComparer()); Dictionary <CompositeCondition, LeftCellWrapper> firstLCWForCondition = new Dictionary <CompositeCondition, LeftCellWrapper>(new ConditionComparer()); foreach (var leftCellWrapper in leftCellWrappers) { CompositeCondition condMembersValues = new CompositeCondition(); CellQuery cellQuery = leftCellWrapper.OnlyInputCell.GetLeftQuery(m_viewgenContext.ViewTarget); foreach (MemberRestriction condition in cellQuery.GetConjunctsFromWhereClause()) { MemberPath memberPath = condition.RestrictedMemberSlot.MemberPath; if (!m_domainMap.IsConditionMember(memberPath)) { continue; } ScalarRestriction scalarCond = condition as ScalarRestriction; //Check for mapping of Scalar member condition, ignore type conditions if (scalarCond != null && !mappedConditionMembers.Contains(memberPath) && /* prevents duplicate errors */ !leftCellWrapper.OnlyInputCell.CQuery.WhereClause.Equals(leftCellWrapper.OnlyInputCell.SQuery.WhereClause) && /* projection allowed when both conditions are equal */ !IsMemberPartOfNotNullCondition(leftCellWrappers, memberPath, m_viewgenContext.ViewTarget)) { //This member should not be mapped CheckThatConditionMemberIsNotMapped(memberPath, leftCellWrappers, mappedConditionMembers); } //If a not-null condition is specified on a nullable column, //check that the property it is mapped to in the fragment is non-nullable, //unless there is a not null condition on the property that is being mapped it self. //Otherwise return an error. if (m_viewgenContext.ViewTarget == ViewTarget.UpdateView) { if (scalarCond != null && memberPath.IsNullable && IsMemberPartOfNotNullCondition(new LeftCellWrapper[] { leftCellWrapper }, memberPath, m_viewgenContext.ViewTarget)) { MemberPath rightMemberPath = GetRightMemberPath(memberPath, leftCellWrapper); if (rightMemberPath != null && rightMemberPath.IsNullable && !IsMemberPartOfNotNullCondition(new LeftCellWrapper[] { leftCellWrapper }, rightMemberPath, m_viewgenContext.ViewTarget)) { m_errorLog.AddEntry(new ErrorLog.Record(true, ViewGenErrorCode.ErrorPatternConditionError, Strings.Viewgen_ErrorPattern_NotNullConditionMappedToNullableMember( memberPath, rightMemberPath ), leftCellWrapper.OnlyInputCell, "")); } } } //CheckForDuplicateConditionValue //discover a composite condition of the form {path1=x, path2=y, ...} foreach (var element in condition.Domain.Values) { Set <Constant> values; //if not in the dict, add it if (!condMembersValues.TryGetValue(memberPath, out values)) { values = new Set <Constant>(Constant.EqualityComparer); condMembersValues.Add(memberPath, values); } values.Add(element); } } //foreach condition if (condMembersValues.Count > 0) //it is possible that there are no condition members { //Check if the composite condition has been encountered before if (setOfconditions.Contains(condMembersValues)) { //Extents may be Equal on right side (e.g: by some form of Refconstraint) if (!RightSideEqual(firstLCWForCondition[condMembersValues], leftCellWrapper)) { //error duplicate conditions m_errorLog.AddEntry(new ErrorLog.Record(true, ViewGenErrorCode.ErrorPatternConditionError, Strings.Viewgen_ErrorPattern_DuplicateConditionValue( BuildCommaSeparatedErrorString <MemberPath>(condMembersValues.Keys) ), ToIEnum(firstLCWForCondition[condMembersValues].OnlyInputCell, leftCellWrapper.OnlyInputCell), "")); } } else { setOfconditions.Add(condMembersValues); //Remember which cell the condition came from.. used for error reporting firstLCWForCondition.Add(condMembersValues, leftCellWrapper); } } } //foreach fragment related to the Extent we are working on }
private void MatchConditionErrors() { List <LeftCellWrapper> wrappersForExtent = this.m_viewgenContext.AllWrappersForExtent; Set <MemberPath> mappedConditionMembers = new Set <MemberPath>(); Set <Dictionary <MemberPath, Set <Constant> > > set1 = new Set <Dictionary <MemberPath, Set <Constant> > >((IEqualityComparer <Dictionary <MemberPath, Set <Constant> > >) new ConditionComparer()); Dictionary <Dictionary <MemberPath, Set <Constant> >, LeftCellWrapper> dictionary = new Dictionary <Dictionary <MemberPath, Set <Constant> >, LeftCellWrapper>((IEqualityComparer <Dictionary <MemberPath, Set <Constant> > >) new ConditionComparer()); foreach (LeftCellWrapper leftCellWrapper in wrappersForExtent) { Dictionary <MemberPath, Set <Constant> > index = new Dictionary <MemberPath, Set <Constant> >(); foreach (MemberRestriction memberRestriction in leftCellWrapper.OnlyInputCell.GetLeftQuery(this.m_viewgenContext.ViewTarget).GetConjunctsFromWhereClause()) { MemberPath memberPath = memberRestriction.RestrictedMemberSlot.MemberPath; if (this.m_domainMap.IsConditionMember(memberPath)) { ScalarRestriction scalarRestriction = memberRestriction as ScalarRestriction; if (scalarRestriction != null && !mappedConditionMembers.Contains(memberPath) && (!leftCellWrapper.OnlyInputCell.CQuery.WhereClause.Equals((object)leftCellWrapper.OnlyInputCell.SQuery.WhereClause) && !ErrorPatternMatcher.IsMemberPartOfNotNullCondition((IEnumerable <LeftCellWrapper>)wrappersForExtent, memberPath, this.m_viewgenContext.ViewTarget))) { this.CheckThatConditionMemberIsNotMapped(memberPath, wrappersForExtent, mappedConditionMembers); } if (this.m_viewgenContext.ViewTarget == ViewTarget.UpdateView && scalarRestriction != null && memberPath.IsNullable) { if (ErrorPatternMatcher.IsMemberPartOfNotNullCondition((IEnumerable <LeftCellWrapper>) new LeftCellWrapper[1] { leftCellWrapper }, memberPath, this.m_viewgenContext.ViewTarget)) { MemberPath rightMemberPath = ErrorPatternMatcher.GetRightMemberPath(memberPath, leftCellWrapper); if (rightMemberPath != null && rightMemberPath.IsNullable) { if (!ErrorPatternMatcher.IsMemberPartOfNotNullCondition((IEnumerable <LeftCellWrapper>) new LeftCellWrapper[1] { leftCellWrapper }, rightMemberPath, this.m_viewgenContext.ViewTarget)) { this.m_errorLog.AddEntry(new ErrorLog.Record(ViewGenErrorCode.ErrorPatternConditionError, Strings.Viewgen_ErrorPattern_NotNullConditionMappedToNullableMember((object)memberPath, (object)rightMemberPath), leftCellWrapper.OnlyInputCell, "")); } } } } foreach (Constant element in memberRestriction.Domain.Values) { Set <Constant> set2; if (!index.TryGetValue(memberPath, out set2)) { set2 = new Set <Constant>(Constant.EqualityComparer); index.Add(memberPath, set2); } set2.Add(element); } } } if (index.Count > 0) { if (set1.Contains(index)) { if (!this.RightSideEqual(dictionary[index], leftCellWrapper)) { this.m_errorLog.AddEntry(new ErrorLog.Record(ViewGenErrorCode.ErrorPatternConditionError, Strings.Viewgen_ErrorPattern_DuplicateConditionValue((object)ErrorPatternMatcher.BuildCommaSeparatedErrorString <MemberPath>((IEnumerable <MemberPath>)index.Keys)), ErrorPatternMatcher.ToIEnum(dictionary[index].OnlyInputCell, leftCellWrapper.OnlyInputCell), "")); } } else { set1.Add(index); dictionary.Add(index, leftCellWrapper); } } } }