internal static void CheckConstraints(CellTreeNode node, LeftCellWrapper wrapper, ViewgenContext context, ErrorLog errorLog) { DomainConstraintVisitor visitor = new DomainConstraintVisitor(wrapper, context, errorLog); node.Accept <bool, bool>(visitor, true); }
internal void Validate() { // turn rewritings into cell trees // plain: according to rewritings for case statements var plainMemberValueTrees = CreateMemberValueTrees(false); // complement: uses complement rewriting for the last WHEN ... THEN // This is how the final case statement will be generated in update views var complementMemberValueTrees = CreateMemberValueTrees(true); var plainWhereClauseVisitor = new WhereClauseVisitor(_basicView, plainMemberValueTrees); var complementWhereClauseVisitor = new WhereClauseVisitor(_basicView, complementMemberValueTrees); // produce CellTree for each SQuery foreach (var wrapper in _viewgenContext.AllWrappersForExtent) { var cell = wrapper.OnlyInputCell; // construct cell tree for CQuery CellTreeNode cQueryTree = new LeafCellTreeNode(_viewgenContext, wrapper); // sQueryTree: unfolded update view inside S-side of the cell CellTreeNode sQueryTree; // construct cell tree for SQuery (will be used for domain constraint checking) var complementSQueryTreeForCondition = complementWhereClauseVisitor.GetCellTreeNode(cell.SQuery.WhereClause); Debug.Assert(complementSQueryTreeForCondition != null, "Rewriting for S-side query is unsatisfiable"); if (complementSQueryTreeForCondition == null) { continue; // situation should never happen } if (complementSQueryTreeForCondition != _basicView) { // intersect with basic expression sQueryTree = new OpCellTreeNode(_viewgenContext, CellTreeOpType.IJ, complementSQueryTreeForCondition, _basicView); } else { sQueryTree = _basicView; } // Append in-set or in-end condition to both queries to produce more concise errors // Otherwise, the errors are of the form "if there exists an entity in extent, then violation". We don't care about empty extents var inExtentCondition = BoolExpression.CreateLiteral(wrapper.CreateRoleBoolean(), _viewgenContext.MemberMaps.QueryDomainMap); BoolExpression unsatisfiedConstraint; if (!CheckEquivalence( cQueryTree.RightFragmentQuery, sQueryTree.RightFragmentQuery, inExtentCondition, out unsatisfiedConstraint)) { var extentName = StringUtil.FormatInvariant("{0}", _viewgenContext.Extent); // Simplify to produce more readable error messages cQueryTree.RightFragmentQuery.Condition.ExpensiveSimplify(); sQueryTree.RightFragmentQuery.Condition.ExpensiveSimplify(); var message = Strings.ViewGen_CQ_PartitionConstraint(extentName); ReportConstraintViolation( message, unsatisfiedConstraint, ViewGenErrorCode.PartitionConstraintViolation, cQueryTree.GetLeaves().Concat(sQueryTree.GetLeaves())); } var plainSQueryTreeForCondition = plainWhereClauseVisitor.GetCellTreeNode(cell.SQuery.WhereClause); Debug.Assert(plainSQueryTreeForCondition != null, "Rewriting for S-side query is unsatisfiable"); if (plainSQueryTreeForCondition != null) { // Query is non-empty. Check domain constraints on: // (a) swapped members DomainConstraintVisitor.CheckConstraints(plainSQueryTreeForCondition, wrapper, _viewgenContext, _errorLog); //If you have already found errors, just continue on to the next wrapper instead of //collecting more errors for the same if (_errorLog.Count > 0) { continue; } // (b) projected members CheckConstraintsOnProjectedConditionMembers(plainMemberValueTrees, wrapper, sQueryTree, inExtentCondition); if (_errorLog.Count > 0) { continue; } } CheckConstraintsOnNonNullableMembers(wrapper); } if (_errorLog.Count > 0) { ExceptionHelpers.ThrowMappingException(_errorLog, _viewgenContext.Config); } }