コード例 #1
0
ファイル: OpCellTreeNode.cs プロジェクト: yz1988computer/ef6
        // requires: caseForOuterJoins corresponds the slot "slotNum"
        // effects: Adds a WhenThen corresponding to child to caseForOuterJoins.
        private void AddCaseForOuterJoins(CaseStatement caseForOuterJoins, CqlBlock child, int slotNum, CqlIdentifiers identifiers)
        {
            // Determine the cells that the slot comes from
            // and make an OR expression, e.g., WHEN _from0 or _from2 or ... THEN child[slotNum]

            var childSlot    = child.SlotValue(slotNum);
            var constantSlot = childSlot as ConstantProjectedSlot;

            if (constantSlot != null &&
                constantSlot.CellConstant.IsNull())
            {
                // NULL being generated by a child - don't need to project
                return;
            }

            var originBool = BoolExpression.False;

            for (var i = 0; i < NumBoolSlots; i++)
            {
                var boolSlotNum = BoolIndexToSlot(i);
                if (child.IsProjected(boolSlotNum))
                {
                    // OR it to the expression
                    var boolExpr = new QualifiedCellIdBoolean(child, identifiers, i);
                    originBool = BoolExpression.CreateOr(originBool, BoolExpression.CreateLiteral(boolExpr, RightDomainMap));
                }
            }
            // Qualify the slotNum with the child.CqlAlias for the THEN
            var slot = child.QualifySlotWithBlockAlias(slotNum);

            caseForOuterJoins.AddWhenThen(originBool, slot);
        }
コード例 #2
0
        private void AddCaseForOuterJoins(
            CaseStatement caseForOuterJoins,
            CqlBlock child,
            int slotNum,
            CqlIdentifiers identifiers)
        {
            ConstantProjectedSlot constantProjectedSlot = child.SlotValue(slotNum) as ConstantProjectedSlot;

            if (constantProjectedSlot != null && constantProjectedSlot.CellConstant.IsNull())
            {
                return;
            }
            BoolExpression or = BoolExpression.False;

            for (int index = 0; index < this.NumBoolSlots; ++index)
            {
                int slot = this.BoolIndexToSlot(index);
                if (child.IsProjected(slot))
                {
                    QualifiedCellIdBoolean qualifiedCellIdBoolean = new QualifiedCellIdBoolean(child, identifiers, index);
                    or = BoolExpression.CreateOr(or, BoolExpression.CreateLiteral((BoolLiteral)qualifiedCellIdBoolean, this.RightDomainMap));
                }
            }
            QualifiedSlot qualifiedSlot = child.QualifySlotWithBlockAlias(slotNum);

            caseForOuterJoins.AddWhenThen(or, (ProjectedSlot)qualifiedSlot);
        }
コード例 #3
0
 // for backward compatibility: add (WHEN True THEN Type) for non-scalar types
 internal void AddTrivialCaseStatementsForConditionMembers()
 {
     for (var memberNum = 0; memberNum < _context.MemberMaps.ProjectedSlotMap.Count; memberNum++)
     {
         var memberPath = _context.MemberMaps.ProjectedSlotMap[memberNum];
         if (!memberPath.IsScalarType()
             && !_caseStatements.ContainsKey(memberPath))
         {
             Constant typeConstant = new TypeConstant(memberPath.EdmType);
             {
                 var caseStmt = new CaseStatement(memberPath);
                 caseStmt.AddWhenThen(BoolExpression.True, new ConstantProjectedSlot(typeConstant));
                 _caseStatements[memberPath] = caseStmt;
             }
         }
     }
 }
コード例 #4
0
        // Modifies _caseStatements and _topLevelWhereClause
        private List<LeftCellWrapper> RemapFromVariables()
        {
            var usedCells = new List<LeftCellWrapper>();
            // remap CellIdBooleans appearing in WHEN clauses and in topLevelWhereClause so the first used cell = 0, second = 1, etc.
            // This ordering is exploited in CQL generation
            var newNumber = 0;
            var literalRemap = new Dictionary<BoolLiteral, BoolLiteral>(BoolLiteral.EqualityIdentifierComparer);
            foreach (var leftCellWrapper in _context.AllWrappersForExtent)
            {
                if (_usedViews.Contains(leftCellWrapper.FragmentQuery))
                {
                    usedCells.Add(leftCellWrapper);
                    var oldNumber = leftCellWrapper.OnlyInputCell.CellNumber;
                    if (newNumber != oldNumber)
                    {
                        literalRemap[new CellIdBoolean(_identifiers, oldNumber)] = new CellIdBoolean(_identifiers, newNumber);
                    }
                    newNumber++;
                }
            }

            if (literalRemap.Count > 0)
            {
                // Remap _from literals in WHERE clause
                _topLevelWhereClause = _topLevelWhereClause.RemapLiterals(literalRemap);

                // Remap _from literals in case statements
                var newCaseStatements = new Dictionary<MemberPath, CaseStatement>();
                foreach (var entry in _caseStatements)
                {
                    var newCaseStatement = new CaseStatement(entry.Key);
                    Debug.Assert(entry.Value.ElseValue == null);
                    foreach (var clause in entry.Value.Clauses)
                    {
                        newCaseStatement.AddWhenThen(clause.Condition.RemapLiterals(literalRemap), clause.Value);
                    }
                    newCaseStatements[entry.Key] = newCaseStatement;
                }
                _caseStatements = newCaseStatements;
            }
            return usedCells;
        }
コード例 #5
0
        private void AddElseDefaultToCaseStatement(
            MemberPath currentPath, CaseStatement caseStatement, List<Constant> domain,
            CellTreeNode rightDomainQuery, Tile<FragmentQuery> unionCaseRewriting)
        {
            Debug.Assert(_context.ViewTarget == ViewTarget.UpdateView, "Used for update views only");

            Constant defaultValue;
            var hasDefaultValue = Domain.TryGetDefaultValueForMemberPath(currentPath, out defaultValue);

            if (false == hasDefaultValue
                || false == domain.Contains(defaultValue))
            {
                Debug.Assert(unionCaseRewriting != null, "No union of rewritings for case statements");
                var unionTree = TileToCellTree(unionCaseRewriting, _context);
                var configurationNeedsDefault = _context.RightFragmentQP.Difference(
                    rightDomainQuery.RightFragmentQuery, unionTree.RightFragmentQuery);

                if (_context.RightFragmentQP.IsSatisfiable(configurationNeedsDefault))
                {
                    if (hasDefaultValue)
                    {
                        caseStatement.AddWhenThen(BoolExpression.True, new ConstantProjectedSlot(defaultValue));
                    }
                    else
                    {
                        configurationNeedsDefault.Condition.ExpensiveSimplify();
                        var builder = new StringBuilder();
                        builder.AppendLine(
                            Strings.ViewGen_No_Default_Value_For_Configuration(currentPath.PathToString(false /* for alias */)));
                        _errorLog.AddEntry(
                            new ErrorLog.Record(
                                ViewGenErrorCode.NoDefaultValue, builder.ToString(), _context.AllWrappersForExtent, String.Empty));
                    }
                }
            }
        }
コード例 #6
0
        private void GenerateCaseStatements(
            IEnumerable<MemberPath> members,
            HashSet<FragmentQuery> outputUsedViews)
        {
            // Compute right domain query - non-simplified version of "basic view"
            // It is used below to check whether we need a default value in a case statement
            var usedCells = _context.AllWrappersForExtent.Where(w => _usedViews.Contains(w.FragmentQuery));
            CellTreeNode rightDomainQuery = new OpCellTreeNode(
                _context, CellTreeOpType.Union,
                usedCells.Select(wrapper => new LeafCellTreeNode(_context, wrapper)).ToArray());

            foreach (var currentPath in members)
            {
                // Add the types can member have, i.e., its type and its subtypes
                var domain = GetDomain(currentPath).ToList();
                var caseStatement = new CaseStatement(currentPath);

                Tile<FragmentQuery> unionCaseRewriting = null;

                // optimization for domain = {NULL, NOT_NULL}
                // Create a single case: WHEN True THEN currentPath
                // Reason: if the WHEN condition is not satisfied (say because of LOJ), then currentPath = NULL
                var needCaseStatement =
                    !(domain.Count == 2 &&
                      domain.Contains(Constant.Null, Constant.EqualityComparer) &&
                      domain.Contains(Constant.NotNull, Constant.EqualityComparer));
                {
                    // go over the domain
                    foreach (var domainValue in domain)
                    {
                        if (domainValue == Constant.Undefined
                            && _context.ViewTarget == ViewTarget.QueryView)
                        {
                            // we cannot assume closed domain for query views;
                            // if obtaining undefined is possible, we need to account for that
                            caseStatement.AddWhenThen(
                                BoolExpression.False /* arbitrary condition */,
                                new ConstantProjectedSlot(Constant.Undefined));
                            continue;
                        }
                        TraceVerbose("CASE STATEMENT FOR {0}={1}", currentPath, domainValue);

                        // construct WHERE clause for this value
                        var memberConditionQuery = CreateMemberConditionQuery(currentPath, domainValue);

                        Tile<FragmentQuery> caseRewriting;
                        if (FindRewritingAndUsedViews(
                            memberConditionQuery.Attributes, memberConditionQuery.Condition, outputUsedViews, out caseRewriting))
                        {
                            if (_context.ViewTarget
                                == ViewTarget.UpdateView)
                            {
                                unionCaseRewriting = (unionCaseRewriting != null)
                                                         ? _qp.Union(unionCaseRewriting, caseRewriting)
                                                         : caseRewriting;
                            }

                            if (needCaseStatement)
                            {
                                var isAlwaysTrue = AddRewritingToCaseStatement(caseRewriting, caseStatement, currentPath, domainValue);
                                if (isAlwaysTrue)
                                {
                                    break;
                                }
                            }
                        }
                        else
                        {
                            if (!IsDefaultValue(domainValue, currentPath))
                            {
                                Debug.Assert(_context.ViewTarget == ViewTarget.UpdateView || !_config.IsValidationEnabled);

                                if (!ErrorPatternMatcher.FindMappingErrors(_context, _domainMap, _errorLog))
                                {
                                    var builder = new StringBuilder();
                                    var extentName = StringUtil.FormatInvariant("{0}", _extentPath);
                                    var objectString = _context.ViewTarget == ViewTarget.QueryView
                                                           ? Strings.ViewGen_Entities
                                                           : Strings.ViewGen_Tuples;

                                    if (_context.ViewTarget
                                        == ViewTarget.QueryView)
                                    {
                                        builder.AppendLine(Strings.Viewgen_CannotGenerateQueryViewUnderNoValidation(extentName));
                                    }
                                    else
                                    {
                                        builder.AppendLine(Strings.ViewGen_Cannot_Disambiguate_MultiConstant(objectString, extentName));
                                    }
                                    RewritingValidator.EntityConfigurationToUserString(
                                        memberConditionQuery.Condition, builder, _context.ViewTarget == ViewTarget.UpdateView);
                                    var record = new ErrorLog.Record(
                                        ViewGenErrorCode.AmbiguousMultiConstants, builder.ToString(), _context.AllWrappersForExtent,
                                        String.Empty);
                                    _errorLog.AddEntry(record);
                                }
                            }
                        }
                    }
                }

                if (_errorLog.Count == 0)
                {
                    // for update views, add WHEN True THEN defaultValue
                    // which will ultimately be translated into a (possibly implicit) ELSE clause
                    if (_context.ViewTarget == ViewTarget.UpdateView && needCaseStatement)
                    {
                        AddElseDefaultToCaseStatement(currentPath, caseStatement, domain, rightDomainQuery, unionCaseRewriting);
                    }

                    if (caseStatement.Clauses.Count > 0)
                    {
                        TraceVerbose("{0}", caseStatement.ToString());
                        _caseStatements[currentPath] = caseStatement;
                    }
                }
            }
        }
コード例 #7
0
        // returns true when the case statement is completed
        private bool AddRewritingToCaseStatement(
            Tile<FragmentQuery> rewriting, CaseStatement caseStatement, MemberPath currentPath, Constant domainValue)
        {
            var whenCondition = BoolExpression.True;
            // check whether the rewriting is always true or always false
            // if it's always true, we don't need any other WHEN clauses in the case statement
            // if it's always false, we don't need to add this WHEN clause to the case statement
            // given: domainQuery is satisfied. Check (domainQuery -> rewriting)
            var isAlwaysTrue = _qp.IsContainedIn(CreateTile(_domainQuery), rewriting);
            var isAlwaysFalse = _qp.IsDisjointFrom(CreateTile(_domainQuery), rewriting);
            Debug.Assert(!(isAlwaysTrue && isAlwaysFalse));
            if (isAlwaysFalse)
            {
                return false; // don't need an unsatisfiable WHEN clause
            }
            if (isAlwaysTrue)
            {
                Debug.Assert(caseStatement.Clauses.Count == 0);
            }

            ProjectedSlot projectedSlot;
            if (domainValue.HasNotNull())
            {
                projectedSlot = new MemberProjectedSlot(currentPath);
            }
            else
            {
                projectedSlot = new ConstantProjectedSlot(domainValue);
            }

            if (!isAlwaysTrue)
            {
                whenCondition = TileToBoolExpr(rewriting);
            }
            else
            {
                whenCondition = BoolExpression.True;
            }
            caseStatement.AddWhenThen(whenCondition, projectedSlot);

            return isAlwaysTrue;
        }