/// <summary>
 /// Creates a complete member restriction with the meaning "<paramref name="slot"/> in <paramref name="domain"/>".
 /// </summary>
 protected MemberRestriction(MemberProjectedSlot slot, Domain domain)
 {
     m_restrictedMemberSlot = slot;
     m_domain = domain;
     m_isComplete = true;
     Debug.Assert(m_domain.Count != 0, "If you want a boolean that evaluates to false, " +
                  "use the ConstantBool abstraction");
 }
 /// <summary>
 /// Creates a scalar member restriction with the meaning "<paramref name="slot"/> in <paramref name="domain"/>".
 /// </summary>
 internal ScalarRestriction(MemberProjectedSlot slot, Domain domain)
     : base(slot, domain)
 { }
Example #3
0
 // effects: Creates a copy of the set "domain"
 internal Domain(Domain domain)
 {
     m_domain = new Set<Constant>(domain.m_domain, Constant.EqualityComparer);
     m_possibleValues = new Set<Constant>(domain.m_possibleValues, Constant.EqualityComparer);
     AssertInvariant();
 }
 /// <summary>
 /// Creates an incomplete member restriction with the meaning "<paramref name="slot"/> in <paramref name="values"/>".
 /// </summary>
 protected MemberRestriction(MemberProjectedSlot slot, IEnumerable<Constant> values)
 {
     m_restrictedMemberSlot = slot;
     m_domain = new Domain(values, values);
 }
Example #5
0
 // effects: Intersects the values in second with this domain and
 // returns the result
 private Domain Intersect(Domain second)
 {
     CheckTwoDomainInvariants(this, second);
     Domain result = new Domain(this);
     result.m_domain.Intersect(second.m_domain);
     return result;
 }
Example #6
0
        private static void CheckTwoDomainInvariants(Domain domain1, Domain domain2)
        {
            domain1.AssertInvariant();
            domain2.AssertInvariant();

            // The possible values must match
            Debug.Assert(domain1.m_possibleValues.SetEquals(domain2.m_possibleValues), "domains must be compatible");
        }
Example #7
0
 // effects: Returns true iff this domain has the same values as
 // second. Note that this method performs a semantic check not just
 // an element by element check
 internal bool IsEqualTo(Domain second)
 {
     return m_domain.SetEquals(second.m_domain);
 }
Example #8
0
        // 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);
        }
Example #9
0
        internal override CqlBlock ToCqlBlock(bool[] requiredSlots, CqlIdentifiers identifiers, ref int blockAliasNum, ref List <WithRelationship> withRelationships)
        {
            // Get the projected slots and the boolean expressions
            int       totalSlots = requiredSlots.Length;
            CellQuery cellQuery  = LeftCellWrapper.RightCellQuery;

            SlotInfo[] projectedSlots = new SlotInfo[totalSlots];
            Debug.Assert(cellQuery.NumProjectedSlots + cellQuery.NumBoolVars == totalSlots,
                         "Wrong number of projected slots in node");

            Debug.Assert(cellQuery.NumProjectedSlots == ProjectedSlotMap.Count,
                         "Different number of slots in cell query and what we have mappings for");
            // Add the regular fields
            for (int i = 0; i < cellQuery.NumProjectedSlots; i++)
            {
                ProjectedSlot slot = cellQuery.ProjectedSlotAt(i);
                // If the slot is not null, we will project it
                // For extents, we say that all requiredlots are the only the
                // ones that are CLR non-null. Recall that "real" nulls are
                // handled by having a CellConstant.Null in ConstantSlot
                if (requiredSlots[i] && slot == null)
                {
                    MemberPath            memberPath   = ProjectedSlotMap[i];
                    ConstantProjectedSlot defaultValue = new ConstantProjectedSlot(Domain.GetDefaultValueForMemberPath(memberPath, GetLeaves(), ViewgenContext.Config), memberPath);
                    cellQuery.FixMissingSlotAsDefaultConstant(i, defaultValue);
                    slot = defaultValue;
                }
                SlotInfo slotInfo = new SlotInfo(requiredSlots[i], slot != null,
                                                 slot, ProjectedSlotMap[i]);
                projectedSlots[i] = slotInfo;
            }

            // Add the boolean fields
            for (int boolNum = 0; boolNum < cellQuery.NumBoolVars; boolNum++)
            {
                BoolExpression       expr = cellQuery.GetBoolVar(boolNum);
                BooleanProjectedSlot boolSlot;
                if (expr != null)
                {
                    boolSlot = new BooleanProjectedSlot(expr, identifiers, boolNum);
                }
                else
                {
                    boolSlot = new BooleanProjectedSlot(BoolExpression.False, identifiers, boolNum);
                }
                int      slotIndex = BoolIndexToSlot(boolNum);
                SlotInfo slotInfo  = new SlotInfo(requiredSlots[slotIndex], expr != null,
                                                  boolSlot, null);
                projectedSlots[slotIndex] = slotInfo;
            }

            // See if we are generating a query view and whether there are any colocated foreign keys for which
            // we have to add With statements.
            IEnumerable <SlotInfo> totalProjectedSlots = projectedSlots;

            if ((cellQuery.Extent.EntityContainer.DataSpace == DataSpace.SSpace) &&
                (this.m_cellWrapper.LeftExtent.BuiltInTypeKind == BuiltInTypeKind.EntitySet))
            {
                IEnumerable <StorageAssociationSetMapping> associationSetMaps =
                    this.ViewgenContext.EntityContainerMapping.GetRelationshipSetMappingsFor(this.m_cellWrapper.LeftExtent, cellQuery.Extent);
                List <SlotInfo> foreignKeySlots = new List <SlotInfo>();
                foreach (StorageAssociationSetMapping colocatedAssociationSetMap in associationSetMaps)
                {
                    WithRelationship withRelationship;
                    if (TryGetWithRelationship(colocatedAssociationSetMap, this.m_cellWrapper.LeftExtent, cellQuery.SourceExtentMemberPath, ref foreignKeySlots, out withRelationship))
                    {
                        withRelationships.Add(withRelationship);
                        totalProjectedSlots = projectedSlots.Concat(foreignKeySlots);
                    }
                }
            }
            ExtentCqlBlock result = new ExtentCqlBlock(cellQuery.Extent, cellQuery.SelectDistinctFlag, totalProjectedSlots.ToArray(),
                                                       cellQuery.WhereClause, identifiers, ++blockAliasNum);

            return(result);
        }
        // determine the domain query, i.e., the query that returns all keys of the extent to be populated
        internal FragmentQuery GetDomainQuery(IEnumerable<FragmentQuery> fragmentQueries, EdmType generatedType)
        {
            BoolExpression domainQueryCondition = null;
            if (_context.ViewTarget
                == ViewTarget.QueryView)
            {
                if (generatedType == null)
                {
                    // domainQuery for entire extent: True
                    domainQueryCondition = BoolExpression.True;
                }
                else // domainQuery for specific type: WHERE type(path) IS OF (Type)
                {
                    //If Mode is OFTypeOnlyViews then don't get subtypes
                    IEnumerable<EdmType> derivedTypes;
                    if (_typesGenerationMode == ViewGenMode.OfTypeOnlyViews)
                    {
                        Debug.Assert(!Helper.IsRefType(_generatedType));
                        var type = new HashSet<EdmType>();
                        type.Add(_generatedType);
                        derivedTypes = type;
                    }
                    else
                    {
                        derivedTypes = MetadataHelper.GetTypeAndSubtypesOf(
                            generatedType, _context.EdmItemCollection, false /* don't include abstract types */);
                    }

                    var typeDomain = new Domain(GetTypeConstants(derivedTypes), _domainMap.GetDomain(_extentPath));
                    domainQueryCondition =
                        BoolExpression.CreateLiteral(new TypeRestriction(new MemberProjectedSlot(_extentPath), typeDomain), _domainMap);
                }
                return FragmentQuery.Create(_keyAttributes, domainQueryCondition);
            }
            else // for update views, domain query = exposed tiles
            {
                var whereClauses = from fragmentQuery in fragmentQueries
                                   select fragmentQuery.Condition;

                var exposedRegionCondition = BoolExpression.CreateOr(whereClauses.ToArray());
                return FragmentQuery.Create(_keyAttributes, exposedRegionCondition);
            }
        }
 // effects: Creates a copy of the set "domain"
 internal Domain(Domain domain)
 {
     m_domain         = new Set <Constant>(domain.m_domain, Constant.EqualityComparer);
     m_possibleValues = new Set <Constant>(domain.m_possibleValues, Constant.EqualityComparer);
     AssertInvariant();
 }
 // effects: Returns true iff this domain has the same values as
 // second. Note that this method performs a semantic check not just
 // an element by element check
 internal bool IsEqualTo(Domain second)
 {
     return(m_domain.SetEquals(second.m_domain));
 }
Example #13
0
        // 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));
                    }
                }
            }
        }
        // effects: Generates a SlotInfo object for a slot of a join node. It
        // uses the type of the join operation (opType), whether the slot is
        // required by the parent or not (isRequiredSlot), the children of
        // this node (children) and the number of the slotNum
        private SlotInfo GetJoinSlotInfo(CellTreeOpType opType, bool isRequiredSlot,
                                         List <CqlBlock> children, int slotNum, CqlIdentifiers identifiers)
        {
            if (false == isRequiredSlot)
            {
                // The slot will not be used. So we can set the projected slot to be null
                SlotInfo unrequiredSlotInfo = new SlotInfo(false, false, null, GetMemberPath(slotNum));
                return(unrequiredSlotInfo);
            }

            // For a required slot, determine the child who is contributing to this value
            int           childDefiningSlot = -1;
            CaseStatement caseForOuterJoins = null;

            for (int childNum = 0; childNum < children.Count; childNum++)
            {
                CqlBlock child = children[childNum];
                if (false == child.IsProjected(slotNum))
                {
                    continue;
                }
                // For keys, we can pick any child block. So the first
                // one that we find is fine as well
                if (IsKeySlot(slotNum))
                {
                    childDefiningSlot = childNum;
                    break;
                }
                else if (opType == CellTreeOpType.IJ)
                {
                    // For Inner Joins, most of the time, the entries will be
                    // the same in all the children. However, in some cases,
                    // we will end up with NULL in one child and an actual
                    // value in another -- we should pick up the actual value in that case
                    childDefiningSlot = GetInnerJoinChildForSlot(children, slotNum);
                    break;
                }
                else
                {
                    // For LOJs, we generate a case statement if more than
                    // one child generates the value - until then we do not
                    // create the caseForOuterJoins object
                    if (childDefiningSlot != -1)
                    {
                        // We really need a case statement now
                        // We have the value being generated by another child
                        // We need to fetch the variable from the appropriate child
                        Debug.Assert(false == IsBoolSlot(slotNum), "Boolean slots cannot come from two children");
                        if (caseForOuterJoins == null)
                        {
                            MemberPath outputMember = GetMemberPath(slotNum);
                            caseForOuterJoins = new CaseStatement(outputMember);
                            // Add the child that we had not added in the first shot
                            AddCaseForOuterJoins(caseForOuterJoins, children[childDefiningSlot], slotNum, identifiers);
                        }
                        AddCaseForOuterJoins(caseForOuterJoins, child, slotNum, identifiers);
                    }
                    childDefiningSlot = childNum;
                }
            }

            MemberPath    memberPath = GetMemberPath(slotNum);
            ProjectedSlot slot       = null;

            // Generate the slot value -- case statement slot, or a qualified slot or null or false.
            // If case statement slot has nothing, treat it as null/empty.
            if (caseForOuterJoins != null && (caseForOuterJoins.Clauses.Count > 0 || caseForOuterJoins.ElseValue != null))
            {
                caseForOuterJoins.Simplify();
                slot = new CaseStatementProjectedSlot(caseForOuterJoins, null);
            }
            else if (childDefiningSlot >= 0)
            {
                slot = children[childDefiningSlot].QualifySlotWithBlockAlias(slotNum);
            }
            else
            {
                // need to produce output slot, but don't have a value
                // output NULL for fields or False for bools
                if (IsBoolSlot(slotNum))
                {
                    slot = new BooleanProjectedSlot(BoolExpression.False, identifiers, SlotToBoolIndex(slotNum));
                }
                else
                {
                    slot = new ConstantProjectedSlot(Domain.GetDefaultValueForMemberPath(memberPath, GetLeaves(), ViewgenContext.Config), memberPath);
                }
            }

            // We need to ensure that _from variables are never null since
            // view generation uses 2-valued boolean logic.
            // They can become null in outer joins. We compensate for it by
            // adding AND NOT NULL condition on boolean slots coming from outer joins.
            bool enforceNotNull = IsBoolSlot(slotNum) &&
                                  ((opType == CellTreeOpType.LOJ && childDefiningSlot > 0) ||
                                   opType == CellTreeOpType.FOJ);
            // We set isProjected to be true since we have come up with some value for it
            SlotInfo slotInfo = new SlotInfo(true, true, slot, memberPath, enforceNotNull);

            return(slotInfo);
        }
Example #15
0
 /// <summary>
 /// Creates a scalar member restriction with the meaning "<paramref name="slot"/> in <paramref name="domain"/>".
 /// </summary>
 internal ScalarRestriction(MemberProjectedSlot slot, Domain domain)
     : base(slot, domain)
 {
 }