/// <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)
 {
 }
 /// <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 #4
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();
 }
        // 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);
            }
        }
Example #6
0
 // effects: Intersects the values in second with this domain and
 // returns the result
 private Domain Intersect(Domain second)
 {
     CheckTwoDomainInvariants(this, second);
     var result = new Domain(this);
     result.m_domain.Intersect(second.m_domain);
     return result;
 }
Example #7
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 #8
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 #9
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
            var possibleValues = DeterminePossibleValues(conditionsForSlot.SelectMany(m => m.Select(c => c)), domain);

            var 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 #10
0
        internal override CqlBlock ToCqlBlock(
            bool[] requiredSlots, CqlIdentifiers identifiers, ref int blockAliasNum, ref List <WithRelationship> withRelationships)
        {
            // Get the projected slots and the boolean expressions
            var totalSlots = requiredSlots.Length;
            var cellQuery  = LeftCellWrapper.RightCellQuery;

            var 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 (var i = 0; i < cellQuery.NumProjectedSlots; i++)
            {
                var 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)
                {
                    var memberPath   = ProjectedSlotMap[i];
                    var defaultValue =
                        new ConstantProjectedSlot(Domain.GetDefaultValueForMemberPath(memberPath, GetLeaves(), ViewgenContext.Config));
                    cellQuery.FixMissingSlotAsDefaultConstant(i, defaultValue);
                    slot = defaultValue;
                }
                var slotInfo = new SlotInfo(
                    requiredSlots[i], slot != null,
                    slot, ProjectedSlotMap[i]);
                projectedSlots[i] = slotInfo;
            }

            // Add the boolean fields
            for (var boolNum = 0; boolNum < cellQuery.NumBoolVars; boolNum++)
            {
                var expr = cellQuery.GetBoolVar(boolNum);
                BooleanProjectedSlot boolSlot;
                if (expr != null)
                {
                    boolSlot = new BooleanProjectedSlot(expr, identifiers, boolNum);
                }
                else
                {
                    boolSlot = new BooleanProjectedSlot(BoolExpression.False, identifiers, boolNum);
                }
                var slotIndex = BoolIndexToSlot(boolNum);
                var 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 collocated foreign keys for which
            // we have to add With statements.
            IEnumerable <SlotInfo> totalProjectedSlots = projectedSlots;

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

            return(result);
        }
Example #11
0
        // 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
                var unrequiredSlotInfo = new SlotInfo(false, false, null, GetMemberPath(slotNum));
                return(unrequiredSlotInfo);
            }

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

            for (var childNum = 0; childNum < children.Count; childNum++)
            {
                var 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)
                        {
                            var 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;
                }
            }

            var           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));
                }
            }

            // 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.
            var 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
            var slotInfo = new SlotInfo(true, true, slot, memberPath, enforceNotNull);

            return(slotInfo);
        }
 internal ScalarRestriction(MemberProjectedSlot slot, Domain domain)
     : base(slot, domain)
 {
 }
Example #13
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();
 }
Example #14
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));
 }