Exemplo n.º 1
0
        // Builds a map from foreign key instances to commands, with an entry for every command that may need to
        // precede some other operation.
        //
        // Predecessor commands must precede other commands using those values. There are two kinds of
        // predecessor:
        //
        // - Commands (updates or inserts) inserting FK "targets" (referenced by the foreign key)
        // - Commands (updates or deletes) deleting FK "sources" (referencing the foreign key)
        //
        // To avoid violating constraints, FK values must be created before they are referenced, and
        // cannot be deleted before their references
        private KeyToListMap <ForeignKeyValue, UpdateCommand> DetermineForeignKeyPredecessors()
        {
            var predecessors = new KeyToListMap <ForeignKeyValue, UpdateCommand>(
                _keyComparer);

            foreach (var command in Vertices.OfType <DynamicUpdateCommand>())
            {
                if (ModificationOperator.Update == command.Operator
                    ||
                    ModificationOperator.Insert == command.Operator)
                {
                    foreach (var fkConstraint in _targetMap.EnumerateValues(command.Table))
                    {
                        ForeignKeyValue fk;
                        if (ForeignKeyValue.TryCreateTargetKey(fkConstraint, command.CurrentValues, true, out fk))
                        {
                            // if this is an update and the target key is unchanged, there is no
                            // need to add a dependency (from the perspective of the target, the update
                            // is a no-op)
                            ForeignKeyValue originalFK;
                            if (ModificationOperator.Update != command.Operator
                                ||
                                !ForeignKeyValue.TryCreateTargetKey(fkConstraint, command.OriginalValues, true, out originalFK)
                                ||
                                !_keyComparer.Equals(originalFK, fk))
                            {
                                predecessors.Add(fk, command);
                            }
                        }
                    }
                }

                // register all source predecessors
                if (ModificationOperator.Update == command.Operator
                    ||
                    ModificationOperator.Delete == command.Operator)
                {
                    foreach (var fkConstraint in _sourceMap.EnumerateValues(command.Table))
                    {
                        ForeignKeyValue fk;
                        if (ForeignKeyValue.TryCreateSourceKey(fkConstraint, command.OriginalValues, false, out fk))
                        {
                            // if this is an update and the source key is unchanged, there is no
                            // need to add a dependency (from the perspective of the source, the update
                            // is a no-op)
                            ForeignKeyValue currentFK;
                            if (ModificationOperator.Update != command.Operator
                                ||
                                !ForeignKeyValue.TryCreateSourceKey(fkConstraint, command.CurrentValues, false, out currentFK)
                                ||
                                !_keyComparer.Equals(currentFK, fk))
                            {
                                predecessors.Add(fk, command);
                            }
                        }
                    }
                }
            }
            return(predecessors);
        }
        private KeyToListMap <UpdateCommandOrderer.ForeignKeyValue, UpdateCommand> DetermineForeignKeyPredecessors()
        {
            KeyToListMap <UpdateCommandOrderer.ForeignKeyValue, UpdateCommand> keyToListMap = new KeyToListMap <UpdateCommandOrderer.ForeignKeyValue, UpdateCommand>((IEqualityComparer <UpdateCommandOrderer.ForeignKeyValue>) this._keyComparer);

            foreach (DynamicUpdateCommand dynamicUpdateCommand in this.Vertices.OfType <DynamicUpdateCommand>())
            {
                if (dynamicUpdateCommand.Operator == ModificationOperator.Update || ModificationOperator.Insert == dynamicUpdateCommand.Operator)
                {
                    foreach (ReferentialConstraint enumerateValue in this._targetMap.EnumerateValues((EntitySetBase)dynamicUpdateCommand.Table))
                    {
                        UpdateCommandOrderer.ForeignKeyValue key1;
                        UpdateCommandOrderer.ForeignKeyValue key2;
                        if (UpdateCommandOrderer.ForeignKeyValue.TryCreateTargetKey(enumerateValue, dynamicUpdateCommand.CurrentValues, true, out key1) && (dynamicUpdateCommand.Operator != ModificationOperator.Update || !UpdateCommandOrderer.ForeignKeyValue.TryCreateTargetKey(enumerateValue, dynamicUpdateCommand.OriginalValues, true, out key2) || !this._keyComparer.Equals(key2, key1)))
                        {
                            keyToListMap.Add(key1, (UpdateCommand)dynamicUpdateCommand);
                        }
                    }
                }
                if (dynamicUpdateCommand.Operator == ModificationOperator.Update || ModificationOperator.Delete == dynamicUpdateCommand.Operator)
                {
                    foreach (ReferentialConstraint enumerateValue in this._sourceMap.EnumerateValues((EntitySetBase)dynamicUpdateCommand.Table))
                    {
                        UpdateCommandOrderer.ForeignKeyValue key1;
                        UpdateCommandOrderer.ForeignKeyValue key2;
                        if (UpdateCommandOrderer.ForeignKeyValue.TryCreateSourceKey(enumerateValue, dynamicUpdateCommand.OriginalValues, false, out key1) && (dynamicUpdateCommand.Operator != ModificationOperator.Update || !UpdateCommandOrderer.ForeignKeyValue.TryCreateSourceKey(enumerateValue, dynamicUpdateCommand.CurrentValues, false, out key2) || !this._keyComparer.Equals(key2, key1)))
                        {
                            keyToListMap.Add(key1, (UpdateCommand)dynamicUpdateCommand);
                        }
                    }
                }
            }
            return(keyToListMap);
        }
        /// <summary>
        /// Determines model level dependencies for the current command. Dependencies are based
        /// on the model operations performed by the command (adding or deleting entities or relationships).
        /// </summary>
        internal void GetRequiredAndProducedEntities(UpdateTranslator translator,
                                                     KeyToListMap <EntityKey, UpdateCommand> addedEntities,
                                                     KeyToListMap <EntityKey, UpdateCommand> deletedEntities,
                                                     KeyToListMap <EntityKey, UpdateCommand> addedRelationships,
                                                     KeyToListMap <EntityKey, UpdateCommand> deletedRelationships)
        {
            IList <IEntityStateEntry> stateEntries = GetStateEntries(translator);

            foreach (IEntityStateEntry stateEntry in stateEntries)
            {
                if (!stateEntry.IsRelationship)
                {
                    if (stateEntry.State == EntityState.Added)
                    {
                        addedEntities.Add(stateEntry.EntityKey, this);
                    }
                    else if (stateEntry.State == EntityState.Deleted)
                    {
                        deletedEntities.Add(stateEntry.EntityKey, this);
                    }
                }
            }

            // process foreign keys
            if (null != this.OriginalValues)
            {
                // if a foreign key being deleted, it 'frees' or 'produces' the referenced key
                AddReferencedEntities(translator, this.OriginalValues, deletedRelationships);
            }
            if (null != this.CurrentValues)
            {
                // if a foreign key is being added, if requires the referenced key
                AddReferencedEntities(translator, this.CurrentValues, addedRelationships);
            }

            // process relationships
            foreach (IEntityStateEntry stateEntry in stateEntries)
            {
                if (stateEntry.IsRelationship)
                {
                    // only worry about the relationship if it is being added or deleted
                    bool isAdded = stateEntry.State == EntityState.Added;
                    if (isAdded || stateEntry.State == EntityState.Deleted)
                    {
                        DbDataRecord record = isAdded ? (DbDataRecord)stateEntry.CurrentValues : stateEntry.OriginalValues;
                        Debug.Assert(2 == record.FieldCount, "non-binary relationship?");
                        EntityKey end1 = (EntityKey)record[0];
                        EntityKey end2 = (EntityKey)record[1];

                        // relationships require the entity when they're added and free the entity when they're deleted...
                        KeyToListMap <EntityKey, UpdateCommand> affected = isAdded ? addedRelationships : deletedRelationships;

                        // both ends are being modified by the relationship
                        affected.Add(end1, this);
                        affected.Add(end2, this);
                    }
                }
            }
        }
        internal void GetRequiredAndProducedEntities(
            UpdateTranslator translator,
            KeyToListMap <EntityKey, UpdateCommand> addedEntities,
            KeyToListMap <EntityKey, UpdateCommand> deletedEntities,
            KeyToListMap <EntityKey, UpdateCommand> addedRelationships,
            KeyToListMap <EntityKey, UpdateCommand> deletedRelationships)
        {
            IList <IEntityStateEntry> stateEntries = this.GetStateEntries(translator);

            foreach (IEntityStateEntry entityStateEntry in (IEnumerable <IEntityStateEntry>)stateEntries)
            {
                if (!entityStateEntry.IsRelationship)
                {
                    if (entityStateEntry.State == EntityState.Added)
                    {
                        addedEntities.Add(entityStateEntry.EntityKey, this);
                    }
                    else if (entityStateEntry.State == EntityState.Deleted)
                    {
                        deletedEntities.Add(entityStateEntry.EntityKey, this);
                    }
                }
            }
            if (this.OriginalValues != null)
            {
                this.AddReferencedEntities(translator, this.OriginalValues, deletedRelationships);
            }
            if (this.CurrentValues != null)
            {
                this.AddReferencedEntities(translator, this.CurrentValues, addedRelationships);
            }
            foreach (IEntityStateEntry entityStateEntry in (IEnumerable <IEntityStateEntry>)stateEntries)
            {
                if (entityStateEntry.IsRelationship)
                {
                    bool flag = entityStateEntry.State == EntityState.Added;
                    if (flag || entityStateEntry.State == EntityState.Deleted)
                    {
                        DbDataRecord dbDataRecord = flag ? (DbDataRecord)entityStateEntry.CurrentValues : entityStateEntry.OriginalValues;
                        EntityKey    key1         = (EntityKey)dbDataRecord[0];
                        EntityKey    key2         = (EntityKey)dbDataRecord[1];
                        KeyToListMap <EntityKey, UpdateCommand> keyToListMap = flag ? addedRelationships : deletedRelationships;
                        keyToListMap.Add(key1, this);
                        keyToListMap.Add(key2, this);
                    }
                }
            }
        }
        private void CheckImplication(
            SchemaConstraints <ViewKeyConstraint> cViewConstraints,
            SchemaConstraints <ViewKeyConstraint> sViewConstraints)
        {
            this.CheckImplicationKeyConstraints(cViewConstraints, sViewConstraints);
            KeyToListMap <CellGroupValidator.ExtentPair, ViewKeyConstraint> keyToListMap = new KeyToListMap <CellGroupValidator.ExtentPair, ViewKeyConstraint>((IEqualityComparer <CellGroupValidator.ExtentPair>)EqualityComparer <CellGroupValidator.ExtentPair> .Default);

            foreach (ViewKeyConstraint keyConstraint in cViewConstraints.KeyConstraints)
            {
                CellGroupValidator.ExtentPair key = new CellGroupValidator.ExtentPair(keyConstraint.Cell.CQuery.Extent, keyConstraint.Cell.SQuery.Extent);
                keyToListMap.Add(key, keyConstraint);
            }
            foreach (CellGroupValidator.ExtentPair key in keyToListMap.Keys)
            {
                ReadOnlyCollection <ViewKeyConstraint> readOnlyCollection = keyToListMap.ListForKey(key);
                bool flag = false;
                foreach (ViewKeyConstraint second in readOnlyCollection)
                {
                    foreach (ViewKeyConstraint keyConstraint in sViewConstraints.KeyConstraints)
                    {
                        if (keyConstraint.Implies(second))
                        {
                            flag = true;
                            break;
                        }
                    }
                }
                if (!flag)
                {
                    this.m_errorLog.AddEntry(ViewKeyConstraint.GetErrorRecord((IEnumerable <ViewKeyConstraint>)readOnlyCollection));
                }
            }
        }
Exemplo n.º 6
0
        // effects: Given a list of node, produces a new list in which all
        // leaf nodes of the same extent are adjacent to each other. Non-leaf
        // nodes are also adjacent to each other. CHANGE_ADYA_IMPROVE: Merge with GroupByRightExtent
        private static List <CellTreeNode> GroupLeafChildrenByExtent(List <CellTreeNode> nodes)
        {
            // Keep track of leaf cells for each extent
            var extentMap =
                new KeyToListMap <EntitySetBase, CellTreeNode>(EqualityComparer <EntitySetBase> .Default);

            var newNodes = new List <CellTreeNode>();

            foreach (var node in nodes)
            {
                var leafNode = node as LeafCellTreeNode;
                // All non-leaf nodes are added to the result now
                // leaf nodes are added outside the loop
                if (leafNode != null)
                {
                    extentMap.Add(leafNode.LeftCellWrapper.RightCellQuery.Extent, leafNode);
                }
                else
                {
                    newNodes.Add(node);
                }
            }
            // Go through the map and add the leaf children
            newNodes.AddRange(extentMap.AllValues);
            return(newNodes);
        }
        internal KeyToListMap <int, TVertex> GenerateConnectedComponents()
        {
            int compNum = 0;
            Dictionary <TVertex, UndirectedGraph <TVertex> .ComponentNum> dictionary = new Dictionary <TVertex, UndirectedGraph <TVertex> .ComponentNum>(this.m_comparer);

            foreach (TVertex vertex in this.Vertices)
            {
                dictionary.Add(vertex, new UndirectedGraph <TVertex> .ComponentNum(compNum));
                ++compNum;
            }
            foreach (KeyValuePair <TVertex, TVertex> edge in this.Edges)
            {
                if (dictionary[edge.Key].componentNum != dictionary[edge.Value].componentNum)
                {
                    int componentNum1 = dictionary[edge.Value].componentNum;
                    int componentNum2 = dictionary[edge.Key].componentNum;
                    dictionary[edge.Value].componentNum = componentNum2;
                    foreach (TVertex key in dictionary.Keys)
                    {
                        if (dictionary[key].componentNum == componentNum1)
                        {
                            dictionary[key].componentNum = componentNum2;
                        }
                    }
                }
            }
            KeyToListMap <int, TVertex> keyToListMap = new KeyToListMap <int, TVertex>((IEqualityComparer <int>)EqualityComparer <int> .Default);

            foreach (TVertex vertex in this.Vertices)
            {
                int componentNum = dictionary[vertex].componentNum;
                keyToListMap.Add(componentNum, vertex);
            }
            return(keyToListMap);
        }
Exemplo n.º 8
0
        private static void InitializeForeignKeyMaps(HashSet <EntityContainer> containers, HashSet <EntitySet> tables, out KeyToListMap <EntitySetBase, ReferentialConstraint> sourceMap, out KeyToListMap <EntitySetBase, ReferentialConstraint> targetMap)
        {
            sourceMap = new KeyToListMap <EntitySetBase, ReferentialConstraint>(EqualityComparer <EntitySetBase> .Default);
            targetMap = new KeyToListMap <EntitySetBase, ReferentialConstraint>(EqualityComparer <EntitySetBase> .Default);

            // Retrieve relationship ends from each container to populate edges in dependency
            // graph
            foreach (EntityContainer container in containers)
            {
                foreach (EntitySetBase extent in container.BaseEntitySets)
                {
                    AssociationSet associationSet = extent as AssociationSet;

                    if (null != associationSet)
                    {
                        AssociationSetEnd source = null;
                        AssociationSetEnd target = null;

                        var ends = associationSet.AssociationSetEnds;

                        if (2 == ends.Count)
                        {
                            // source is equivalent to the "to" end of relationship, target is "from"
                            AssociationType       associationType = associationSet.ElementType;
                            bool                  constraintFound = false;
                            ReferentialConstraint fkConstraint    = null;
                            foreach (ReferentialConstraint constraint in associationType.ReferentialConstraints)
                            {
                                if (constraintFound)
                                {
                                    Debug.Fail("relationship set should have at most one constraint");
                                }
                                else
                                {
                                    constraintFound = true;
                                }
                                source       = associationSet.AssociationSetEnds[constraint.ToRole.Name];
                                target       = associationSet.AssociationSetEnds[constraint.FromRole.Name];
                                fkConstraint = constraint;
                            }

                            Debug.Assert(constraintFound && null != target && null != source, "relationship set must have at least one constraint");
                            // only understand binary (foreign key) relationships between entity sets
                            if (null != target && null != source)
                            {
                                if (tables.Contains(target.EntitySet) &&
                                    tables.Contains(source.EntitySet))
                                {
                                    // Remember metadata
                                    sourceMap.Add(source.EntitySet, fkConstraint);
                                    targetMap.Add(target.EntitySet, fkConstraint);
                                }
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 9
0
        private static KeyToListMap <EntitySetBase, Cell> GroupCellsByExtent(
            IEnumerable <Cell> cells,
            ViewTarget viewTarget)
        {
            KeyToListMap <EntitySetBase, Cell> keyToListMap = new KeyToListMap <EntitySetBase, Cell>((IEqualityComparer <EntitySetBase>)EqualityComparer <EntitySetBase> .Default);

            foreach (Cell cell in cells)
            {
                CellQuery leftQuery = cell.GetLeftQuery(viewTarget);
                keyToListMap.Add(leftQuery.Extent, cell);
            }
            return(keyToListMap);
        }
Exemplo n.º 10
0
        // effects: Given all the cells for a container, groups the cells by
        // the left query's extent and returns a dictionary for it
        private static KeyToListMap <EntitySetBase, Cell> GroupCellsByExtent(IEnumerable <Cell> cells, ViewTarget viewTarget)
        {
            // Partition cells by extent -- extent is the top node in
            // the tree. Even for compositions for now? CHANGE_ADYA_FEATURE_COMPOSITION
            var extentCellMap =
                new KeyToListMap <EntitySetBase, Cell>(EqualityComparer <EntitySetBase> .Default);

            foreach (var cell in cells)
            {
                // Get the cell query and determine its extent
                var cellQuery = cell.GetLeftQuery(viewTarget);
                extentCellMap.Add(cellQuery.Extent, cell);
            }
            return(extentCellMap);
        }
Exemplo n.º 11
0
        private void InitializeFunctionMappingTranslators(
            EntitySetBase entitySetBase,
            EntityContainerMapping mapping)
        {
            KeyToListMap <AssociationSet, AssociationEndMember> keyToListMap = new KeyToListMap <AssociationSet, AssociationEndMember>((IEqualityComparer <AssociationSet>)EqualityComparer <AssociationSet> .Default);

            if (!this.m_functionMappingTranslators.ContainsKey(entitySetBase))
            {
                foreach (EntitySetMapping entitySetMap in mapping.EntitySetMaps)
                {
                    if (0 < entitySetMap.ModificationFunctionMappings.Count)
                    {
                        this.m_functionMappingTranslators.Add(entitySetMap.Set, ModificationFunctionMappingTranslator.CreateEntitySetTranslator(entitySetMap));
                        foreach (AssociationSetEnd associationSetEnd in entitySetMap.ImplicitlyMappedAssociationSetEnds)
                        {
                            AssociationSet parentAssociationSet = associationSetEnd.ParentAssociationSet;
                            if (!this.m_functionMappingTranslators.ContainsKey((EntitySetBase)parentAssociationSet))
                            {
                                this.m_functionMappingTranslators.Add((EntitySetBase)parentAssociationSet, ModificationFunctionMappingTranslator.CreateAssociationSetTranslator((AssociationSetMapping)null));
                            }
                            AssociationSetEnd oppositeEnd = MetadataHelper.GetOppositeEnd(associationSetEnd);
                            keyToListMap.Add(parentAssociationSet, oppositeEnd.CorrespondingAssociationEndMember);
                        }
                    }
                    else
                    {
                        this.m_functionMappingTranslators.Add(entitySetMap.Set, (ModificationFunctionMappingTranslator)null);
                    }
                }
                foreach (AssociationSetMapping relationshipSetMap in mapping.RelationshipSetMaps)
                {
                    if (relationshipSetMap.ModificationFunctionMapping != null)
                    {
                        AssociationSet set = (AssociationSet)relationshipSetMap.Set;
                        this.m_functionMappingTranslators.Add((EntitySetBase)set, ModificationFunctionMappingTranslator.CreateAssociationSetTranslator(relationshipSetMap));
                        keyToListMap.AddRange(set, Enumerable.Empty <AssociationEndMember>());
                    }
                    else if (!this.m_functionMappingTranslators.ContainsKey(relationshipSetMap.Set))
                    {
                        this.m_functionMappingTranslators.Add(relationshipSetMap.Set, (ModificationFunctionMappingTranslator)null);
                    }
                }
            }
            foreach (AssociationSet key in keyToListMap.Keys)
            {
                this.m_associationSetMetadata.Add(key, new AssociationSetMetadata(keyToListMap.EnumerateValues(key)));
            }
        }
Exemplo n.º 12
0
        // effects: A restrictive version of GroupLeafChildrenByExtent --
        // only for LASJ and LOJ nodes (works for LOJ only when A LOJ B LOJ C
        // s.t., B and C are subsets of A -- in our case that is how LOJs are constructed
        private static List <CellTreeNode> GroupNonAssociativeLeafChildren(List <CellTreeNode> nodes)
        {
            // Keep track of leaf cells for each extent ignoring the 0th child
            var extentMap =
                new KeyToListMap <EntitySetBase, CellTreeNode>(EqualityComparer <EntitySetBase> .Default);

            var newNodes     = new List <CellTreeNode>();
            var nonLeafNodes = new List <CellTreeNode>();

            // Add the 0th child
            newNodes.Add(nodes[0]);
            for (var i = 1; i < nodes.Count; i++)
            {
                var node     = nodes[i];
                var leafNode = node as LeafCellTreeNode;
                // All non-leaf nodes are added to the result now
                // leaf nodes are added outside the loop
                if (leafNode != null)
                {
                    extentMap.Add(leafNode.LeftCellWrapper.RightCellQuery.Extent, leafNode);
                }
                else
                {
                    nonLeafNodes.Add(node);
                }
            }
            // Go through the map and add the leaf children
            // If a group of nodes exists for the 0th node's extent -- place
            // that group first
            var firstNode = nodes[0] as LeafCellTreeNode;

            if (firstNode != null)
            {
                var firstExtent = firstNode.LeftCellWrapper.RightCellQuery.Extent;
                if (extentMap.ContainsKey(firstExtent))
                {
                    newNodes.AddRange(extentMap.ListForKey(firstExtent));
                    // Remove this set from the map
                    extentMap.RemoveKey(firstExtent);
                }
            }
            newNodes.AddRange(extentMap.AllValues);
            newNodes.AddRange(nonLeafNodes);
            return(newNodes);
        }
Exemplo n.º 13
0
        private QueryRewriter GenerateViewsForExtentAndType(
            EdmType generatedType,
            ViewgenContext context,
            CqlIdentifiers identifiers,
            KeyToListMap <EntitySetBase, GeneratedView> views,
            ViewGenMode mode)
        {
            QueryRewriter queryRewriter = new QueryRewriter(generatedType, context, mode);

            queryRewriter.GenerateViewComponents();
            CellTreeNode basicView = queryRewriter.BasicView;

            if (this.m_config.IsNormalTracing)
            {
                Helpers.StringTrace("Basic View: ");
                Helpers.StringTraceLine(basicView.ToString());
            }
            CellTreeNode simplifiedView = ViewGenerator.GenerateSimplifiedView(basicView, queryRewriter.UsedCells);

            if (this.m_config.IsNormalTracing)
            {
                Helpers.StringTraceLine(string.Empty);
                Helpers.StringTrace("Simplified View: ");
                Helpers.StringTraceLine(simplifiedView.ToString());
            }
            CqlGenerator       cqlGenerator = new CqlGenerator(simplifiedView, queryRewriter.CaseStatements, identifiers, context.MemberMaps.ProjectedSlotMap, queryRewriter.UsedCells.Count, queryRewriter.TopLevelWhereClause, this.m_entityContainerMapping.StorageMappingItemCollection);
            string             eSQL;
            DbQueryCommandTree commandTree;

            if (this.m_config.GenerateEsql)
            {
                eSQL        = cqlGenerator.GenerateEsql();
                commandTree = (DbQueryCommandTree)null;
            }
            else
            {
                eSQL        = (string)null;
                commandTree = cqlGenerator.GenerateCqt();
            }
            GeneratedView generatedView = GeneratedView.CreateGeneratedView(context.Extent, generatedType, commandTree, eSQL, this.m_entityContainerMapping.StorageMappingItemCollection, this.m_config);

            views.Add(context.Extent, generatedView);
            return(queryRewriter);
        }
Exemplo n.º 14
0
        // effects: Checks if all sViewConstraints are implied by the
        // constraints in cViewConstraints. If some S-level constraints are
        // not implied, adds errors/warnings to m_errorLog
        private void CheckImplication(ViewSchemaConstraints cViewConstraints, ViewSchemaConstraints sViewConstraints)
        {
            // Check key constraints
            // i.e., if S has a key <k1, k2>, C must have a key that is a subset of this
            CheckImplicationKeyConstraints(cViewConstraints, sViewConstraints);

            // For updates, we need to ensure the following: for every
            // extent E, table T pair, some key of E is implied by T's key

            // Get all key constraints for each extent and each table
            var extentPairConstraints =
                new KeyToListMap <ExtentPair, ViewKeyConstraint>(EqualityComparer <ExtentPair> .Default);

            foreach (var cKeyConstraint in cViewConstraints.KeyConstraints)
            {
                var pair = new ExtentPair(cKeyConstraint.Cell.CQuery.Extent, cKeyConstraint.Cell.SQuery.Extent);
                extentPairConstraints.Add(pair, cKeyConstraint);
            }

            // Now check that we guarantee at least one constraint per
            // extent/table pair
            foreach (var extentPair in extentPairConstraints.Keys)
            {
                var cKeyConstraints = extentPairConstraints.ListForKey(extentPair);
                var sImpliesSomeC   = false;
                // Go through all key constraints for the extent/table pair, and find one that S implies
                foreach (var cKeyConstraint in cKeyConstraints)
                {
                    foreach (var sKeyConstraint in sViewConstraints.KeyConstraints)
                    {
                        if (sKeyConstraint.Implies(cKeyConstraint))
                        {
                            sImpliesSomeC = true;
                            break; // The implication holds - so no problem
                        }
                    }
                }
                if (sImpliesSomeC == false)
                {
                    // Indicate that at least one key must be ensured on the S-side
                    m_errorLog.AddEntry(ViewKeyConstraint.GetErrorRecord(cKeyConstraints));
                }
            }
        }
Exemplo n.º 15
0
        // effects: Given a graph of T, returns a map such that nodes in the
        // same connected component are in the same list in the KeyToListMap
        internal KeyToListMap <int, TVertex> GenerateConnectedComponents()
        {
            var count = 0;
            // Set the "component number" for each node
            var componentMap = new Dictionary <TVertex, ComponentNum>(m_comparer);

            foreach (var vertex in Vertices)
            {
                componentMap.Add(vertex, new ComponentNum(count));
                count++;
            }

            // Run the connected components algorithm (Page 441 of the CLR -- Cormen, Rivest, Lieserson)
            foreach (var edge in Edges)
            {
                if (componentMap[edge.Key].componentNum
                    != componentMap[edge.Value].componentNum)
                {
                    // Set the component numbers of both of the nodes to be the same
                    var oldValue = componentMap[edge.Value].componentNum;
                    var newValue = componentMap[edge.Key].componentNum;
                    componentMap[edge.Value].componentNum = newValue;
                    // Since we are resetting edge.Value's component number, find all components whose value
                    // is oldValue and reset it to the new value
                    foreach (var vertex in componentMap.Keys)
                    {
                        if (componentMap[vertex].componentNum == oldValue)
                        {
                            componentMap[vertex].componentNum = newValue;
                        }
                    }
                }
            }

            // Now just grab the vertices which have the same set numbers
            var result = new KeyToListMap <int, TVertex>(EqualityComparer <int> .Default);

            foreach (var vertex in Vertices)
            {
                var componentNum = componentMap[vertex].componentNum;
                result.Add(componentNum, vertex);
            }
            return(result);
        }
        internal ErrorLog.Record CheckForDuplicateFields(CellQuery cQuery, Cell sourceCell)
        {
            KeyToListMap <MemberProjectedSlot, int> keyToListMap = new KeyToListMap <MemberProjectedSlot, int>((IEqualityComparer <MemberProjectedSlot>)ProjectedSlot.EqualityComparer);

            for (int index = 0; index < this.m_projectedSlots.Length; ++index)
            {
                MemberProjectedSlot projectedSlot = this.m_projectedSlots[index] as MemberProjectedSlot;
                keyToListMap.Add(projectedSlot, index);
            }
            StringBuilder stringBuilder1 = (StringBuilder)null;
            bool          flag           = false;

            foreach (MemberProjectedSlot key in keyToListMap.Keys)
            {
                ReadOnlyCollection <int> cSideSlotIndexes = keyToListMap.ListForKey(key);
                if (cSideSlotIndexes.Count > 1 && !cQuery.AreSlotsEquivalentViaRefConstraints(cSideSlotIndexes))
                {
                    flag = true;
                    if (stringBuilder1 == null)
                    {
                        stringBuilder1 = new StringBuilder(Strings.ViewGen_Duplicate_CProperties((object)this.Extent.Name));
                        stringBuilder1.AppendLine();
                    }
                    StringBuilder stringBuilder2 = new StringBuilder();
                    for (int index1 = 0; index1 < cSideSlotIndexes.Count; ++index1)
                    {
                        int index2 = cSideSlotIndexes[index1];
                        if (index1 != 0)
                        {
                            stringBuilder2.Append(", ");
                        }
                        MemberProjectedSlot projectedSlot = (MemberProjectedSlot)cQuery.m_projectedSlots[index2];
                        stringBuilder2.Append(projectedSlot.ToUserString());
                    }
                    stringBuilder1.AppendLine(Strings.ViewGen_Duplicate_CProperties_IsMapped((object)key.ToUserString(), (object)stringBuilder2.ToString()));
                }
            }
            if (!flag)
            {
                return((ErrorLog.Record)null);
            }
            return(new ErrorLog.Record(ViewGenErrorCode.DuplicateCPropertiesMapped, stringBuilder1.ToString(), sourceCell, string.Empty));
        }
 private static void InitializeForeignKeyMaps(
     HashSet <EntityContainer> containers,
     HashSet <EntitySet> tables,
     out KeyToListMap <EntitySetBase, ReferentialConstraint> sourceMap,
     out KeyToListMap <EntitySetBase, ReferentialConstraint> targetMap)
 {
     sourceMap = new KeyToListMap <EntitySetBase, ReferentialConstraint>((IEqualityComparer <EntitySetBase>)EqualityComparer <EntitySetBase> .Default);
     targetMap = new KeyToListMap <EntitySetBase, ReferentialConstraint>((IEqualityComparer <EntitySetBase>)EqualityComparer <EntitySetBase> .Default);
     foreach (EntityContainer container in containers)
     {
         foreach (EntitySetBase baseEntitySet in container.BaseEntitySets)
         {
             AssociationSet associationSet = baseEntitySet as AssociationSet;
             if (associationSet != null)
             {
                 AssociationSetEnd associationSetEnd1 = (AssociationSetEnd)null;
                 AssociationSetEnd associationSetEnd2 = (AssociationSetEnd)null;
                 if (2 == associationSet.AssociationSetEnds.Count)
                 {
                     AssociationType       elementType            = associationSet.ElementType;
                     bool                  flag                   = false;
                     ReferentialConstraint referentialConstraint1 = (ReferentialConstraint)null;
                     foreach (ReferentialConstraint referentialConstraint2 in elementType.ReferentialConstraints)
                     {
                         if (!flag)
                         {
                             flag = true;
                         }
                         associationSetEnd1     = associationSet.AssociationSetEnds[referentialConstraint2.ToRole.Name];
                         associationSetEnd2     = associationSet.AssociationSetEnds[referentialConstraint2.FromRole.Name];
                         referentialConstraint1 = referentialConstraint2;
                     }
                     if (associationSetEnd2 != null && associationSetEnd1 != null && (tables.Contains(associationSetEnd2.EntitySet) && tables.Contains(associationSetEnd1.EntitySet)))
                     {
                         sourceMap.Add((EntitySetBase)associationSetEnd1.EntitySet, referentialConstraint1);
                         targetMap.Add((EntitySetBase)associationSetEnd2.EntitySet, referentialConstraint1);
                     }
                 }
             }
         }
     }
 }
 private void AddReferencedEntities(UpdateTranslator translator, PropagatorResult result, KeyToListMap <EntityKey, UpdateCommand> referencedEntities)
 {
     foreach (PropagatorResult property in result.GetMemberValues())
     {
         if (property.IsSimple && property.Identifier != PropagatorResult.NullIdentifier &&
             (PropagatorFlags.ForeignKey == (property.PropagatorFlags & PropagatorFlags.ForeignKey)))
         {
             foreach (int principal in translator.KeyManager.GetDirectReferences(property.Identifier))
             {
                 PropagatorResult owner;
                 if (translator.KeyManager.TryGetIdentifierOwner(principal, out owner) &&
                     null != owner.StateEntry)
                 {
                     Debug.Assert(!owner.StateEntry.IsRelationship, "owner must not be a relationship");
                     referencedEntities.Add(owner.StateEntry.EntityKey, this);
                 }
             }
         }
     }
 }
 private void AddReferencedEntities(
     UpdateTranslator translator,
     PropagatorResult result,
     KeyToListMap <EntityKey, UpdateCommand> referencedEntities)
 {
     foreach (PropagatorResult memberValue in result.GetMemberValues())
     {
         if (memberValue.IsSimple && memberValue.Identifier != -1 && PropagatorFlags.ForeignKey == (memberValue.PropagatorFlags & PropagatorFlags.ForeignKey))
         {
             foreach (int directReference in translator.KeyManager.GetDirectReferences(memberValue.Identifier))
             {
                 PropagatorResult owner;
                 if (translator.KeyManager.TryGetIdentifierOwner(directReference, out owner) && owner.StateEntry != null)
                 {
                     referencedEntities.Add(owner.StateEntry.EntityKey, this);
                 }
             }
         }
     }
 }
        private static List <CellTreeNode> GroupLeafChildrenByExtent(
            List <CellTreeNode> nodes)
        {
            KeyToListMap <EntitySetBase, CellTreeNode> keyToListMap = new KeyToListMap <EntitySetBase, CellTreeNode>((IEqualityComparer <EntitySetBase>)EqualityComparer <EntitySetBase> .Default);
            List <CellTreeNode> cellTreeNodeList = new List <CellTreeNode>();

            foreach (CellTreeNode node in nodes)
            {
                LeafCellTreeNode leafCellTreeNode = node as LeafCellTreeNode;
                if (leafCellTreeNode != null)
                {
                    keyToListMap.Add(leafCellTreeNode.LeftCellWrapper.RightCellQuery.Extent, (CellTreeNode)leafCellTreeNode);
                }
                else
                {
                    cellTreeNodeList.Add(node);
                }
            }
            cellTreeNodeList.AddRange(keyToListMap.AllValues);
            return(cellTreeNodeList);
        }
        internal CellTreeNode GroupByRightExtent(CellTreeNode rootNode)
        {
            KeyToListMap <EntitySetBase, LeafCellTreeNode> keyToListMap = new KeyToListMap <EntitySetBase, LeafCellTreeNode>((IEqualityComparer <EntitySetBase>)EqualityComparer <EntitySetBase> .Default);

            foreach (LeafCellTreeNode child in rootNode.Children)
            {
                EntitySetBase extent = child.LeftCellWrapper.RightCellQuery.Extent;
                keyToListMap.Add(extent, child);
            }
            OpCellTreeNode opCellTreeNode1 = new OpCellTreeNode(this.m_viewgenContext, CellTreeOpType.FOJ);

            foreach (EntitySetBase key in keyToListMap.Keys)
            {
                OpCellTreeNode opCellTreeNode2 = new OpCellTreeNode(this.m_viewgenContext, CellTreeOpType.FOJ);
                foreach (LeafCellTreeNode leafCellTreeNode in keyToListMap.ListForKey(key))
                {
                    opCellTreeNode2.Add((CellTreeNode)leafCellTreeNode);
                }
                opCellTreeNode1.Add((CellTreeNode)opCellTreeNode2);
            }
            return(opCellTreeNode1.Flatten());
        }
Exemplo n.º 22
0
        // requires: The tree rooted at cellTreeNode is an FOJ tree of
        // LeafCellTreeNodes only, i.e., there is an FOJ node with the
        // children being LeafCellTreeNodes
        //
        // effects: Given a tree rooted at rootNode, ensures that cells
        // of the same right extent are placed in their own subtree below
        // cellTreeNode. That is, if there are 3 cells of extent A and 2 of
        // extent B (i.e., 5 cells with an FOJ on it), the resulting tree has
        // an FOJ node with two children -- FOJ nodes. These FOJ nodes have 2
        // and 3 children
        internal CellTreeNode GroupByRightExtent(CellTreeNode rootNode)
        {
            // A dictionary that maps an extent to the nodes are from that extent
            // We want a ref comparer here
            var extentMap =
                new KeyToListMap <EntitySetBase, LeafCellTreeNode>(EqualityComparer <EntitySetBase> .Default);

            // CR_Meek_Low: method can be simplified (Map<Extent, OpCellTreeNode>, populate as you go)
            // (becomes self-documenting)
            // For each leaf child, find the extent of the child and place it
            // in extentMap
            foreach (LeafCellTreeNode childNode in rootNode.Children)
            {
                // A cell may contain P, P.PA -- we return P
                // CHANGE_ADYA_FEATURE_COMPOSITION Need to fix for composition!!
                var extent = childNode.LeftCellWrapper.RightCellQuery.Extent; // relation or extent to group by
                Debug.Assert(extent != null, "Each cell must have a right extent");

                // Add the childNode as a child of the FOJ tree for "extent"
                extentMap.Add(extent, childNode);
            }
            // Now go through the extent map and create FOJ nodes for each extent
            // Place the nodes for that extent in the newly-created FOJ subtree
            // Also add the op node for every node as a child of the final result
            var result = new OpCellTreeNode(m_viewgenContext, CellTreeOpType.FOJ);

            foreach (var extent in extentMap.Keys)
            {
                var extentFojNode = new OpCellTreeNode(m_viewgenContext, CellTreeOpType.FOJ);
                foreach (var childNode in extentMap.ListForKey(extent))
                {
                    extentFojNode.Add(childNode);
                }
                result.Add(extentFojNode);
            }
            // We call Flatten to remove any unnecessary nestings
            // where an OpNode has only 1 child.
            return(result.Flatten());
        }
        private static List <CellTreeNode> GroupNonAssociativeLeafChildren(
            List <CellTreeNode> nodes)
        {
            KeyToListMap <EntitySetBase, CellTreeNode> keyToListMap = new KeyToListMap <EntitySetBase, CellTreeNode>((IEqualityComparer <EntitySetBase>)EqualityComparer <EntitySetBase> .Default);
            List <CellTreeNode> cellTreeNodeList1 = new List <CellTreeNode>();
            List <CellTreeNode> cellTreeNodeList2 = new List <CellTreeNode>();

            cellTreeNodeList1.Add(nodes[0]);
            for (int index = 1; index < nodes.Count; ++index)
            {
                CellTreeNode     node             = nodes[index];
                LeafCellTreeNode leafCellTreeNode = node as LeafCellTreeNode;
                if (leafCellTreeNode != null)
                {
                    keyToListMap.Add(leafCellTreeNode.LeftCellWrapper.RightCellQuery.Extent, (CellTreeNode)leafCellTreeNode);
                }
                else
                {
                    cellTreeNodeList2.Add(node);
                }
            }
            LeafCellTreeNode node1 = nodes[0] as LeafCellTreeNode;

            if (node1 != null)
            {
                EntitySetBase extent = node1.LeftCellWrapper.RightCellQuery.Extent;
                if (keyToListMap.ContainsKey(extent))
                {
                    cellTreeNodeList1.AddRange((IEnumerable <CellTreeNode>)keyToListMap.ListForKey(extent));
                    keyToListMap.RemoveKey(extent);
                }
            }
            cellTreeNodeList1.AddRange(keyToListMap.AllValues);
            cellTreeNodeList1.AddRange((IEnumerable <CellTreeNode>)cellTreeNodeList2);
            return(cellTreeNodeList1);
        }
        private CellTreeNode ConvertUnionsToNormalizedLOJs(CellTreeNode rootNode)
        {
            for (int index = 0; index < rootNode.Children.Count; ++index)
            {
                rootNode.Children[index] = this.ConvertUnionsToNormalizedLOJs(rootNode.Children[index]);
            }
            if (rootNode.OpType != CellTreeOpType.LOJ || rootNode.Children.Count < 2)
            {
                return(rootNode);
            }
            OpCellTreeNode         opCellTreeNode1  = new OpCellTreeNode(this.m_viewgenContext, rootNode.OpType);
            List <CellTreeNode>    cellTreeNodeList = new List <CellTreeNode>();
            OpCellTreeNode         opCellTreeNode2  = (OpCellTreeNode)null;
            HashSet <CellTreeNode> cellTreeNodeSet  = (HashSet <CellTreeNode>)null;

            if (rootNode.Children[0].OpType == CellTreeOpType.IJ)
            {
                opCellTreeNode2 = new OpCellTreeNode(this.m_viewgenContext, rootNode.Children[0].OpType);
                opCellTreeNode1.Add((CellTreeNode)opCellTreeNode2);
                cellTreeNodeList.AddRange((IEnumerable <CellTreeNode>)rootNode.Children[0].Children);
                cellTreeNodeSet = new HashSet <CellTreeNode>((IEnumerable <CellTreeNode>)rootNode.Children[0].Children);
            }
            else
            {
                opCellTreeNode1.Add(rootNode.Children[0]);
            }
            foreach (CellTreeNode cellTreeNode in rootNode.Children.Skip <CellTreeNode>(1))
            {
                OpCellTreeNode opCellTreeNode3 = cellTreeNode as OpCellTreeNode;
                if (opCellTreeNode3 != null && opCellTreeNode3.OpType == CellTreeOpType.Union)
                {
                    cellTreeNodeList.AddRange((IEnumerable <CellTreeNode>)opCellTreeNode3.Children);
                }
                else
                {
                    cellTreeNodeList.Add(cellTreeNode);
                }
            }
            KeyToListMap <EntitySet, LeafCellTreeNode> keyToListMap1 = new KeyToListMap <EntitySet, LeafCellTreeNode>((IEqualityComparer <EntitySet>)EqualityComparer <EntitySet> .Default);

            foreach (CellTreeNode child in cellTreeNodeList)
            {
                LeafCellTreeNode leaf = child as LeafCellTreeNode;
                if (leaf != null)
                {
                    EntitySetBase leafNodeTable = (EntitySetBase)BasicViewGenerator.GetLeafNodeTable(leaf);
                    if (leafNodeTable != null)
                    {
                        keyToListMap1.Add((EntitySet)leafNodeTable, leaf);
                    }
                }
                else if (cellTreeNodeSet != null && cellTreeNodeSet.Contains(child))
                {
                    opCellTreeNode2.Add(child);
                }
                else
                {
                    opCellTreeNode1.Add(child);
                }
            }
            foreach (KeyValuePair <EntitySet, List <LeafCellTreeNode> > keyValuePair in keyToListMap1.KeyValuePairs.Where <KeyValuePair <EntitySet, List <LeafCellTreeNode> > >((Func <KeyValuePair <EntitySet, List <LeafCellTreeNode> >, bool>)(m => m.Value.Count > 1)).ToArray <KeyValuePair <EntitySet, List <LeafCellTreeNode> > >())
            {
                keyToListMap1.RemoveKey(keyValuePair.Key);
                foreach (LeafCellTreeNode leafCellTreeNode in keyValuePair.Value)
                {
                    if (cellTreeNodeSet != null && cellTreeNodeSet.Contains((CellTreeNode)leafCellTreeNode))
                    {
                        opCellTreeNode2.Add((CellTreeNode)leafCellTreeNode);
                    }
                    else
                    {
                        opCellTreeNode1.Add((CellTreeNode)leafCellTreeNode);
                    }
                }
            }
            KeyToListMap <EntitySet, EntitySet>    keyToListMap2 = new KeyToListMap <EntitySet, EntitySet>((IEqualityComparer <EntitySet>)EqualityComparer <EntitySet> .Default);
            Dictionary <EntitySet, OpCellTreeNode> dictionary    = new Dictionary <EntitySet, OpCellTreeNode>((IEqualityComparer <EntitySet>)EqualityComparer <EntitySet> .Default);

            foreach (KeyValuePair <EntitySet, List <LeafCellTreeNode> > keyValuePair in keyToListMap1.KeyValuePairs)
            {
                EntitySet key = keyValuePair.Key;
                foreach (EntitySet fkOverPkDependent in BasicViewGenerator.GetFKOverPKDependents(key))
                {
                    ReadOnlyCollection <LeafCellTreeNode> valueCollection;
                    if (keyToListMap1.TryGetListForKey(fkOverPkDependent, out valueCollection) && (cellTreeNodeSet == null || !cellTreeNodeSet.Contains((CellTreeNode)valueCollection.Single <LeafCellTreeNode>())))
                    {
                        keyToListMap2.Add(key, fkOverPkDependent);
                    }
                }
                OpCellTreeNode opCellTreeNode3 = new OpCellTreeNode(this.m_viewgenContext, CellTreeOpType.LOJ);
                opCellTreeNode3.Add((CellTreeNode)keyValuePair.Value.Single <LeafCellTreeNode>());
                dictionary.Add(key, opCellTreeNode3);
            }
            Dictionary <EntitySet, EntitySet> nestedExtents = new Dictionary <EntitySet, EntitySet>((IEqualityComparer <EntitySet>)EqualityComparer <EntitySet> .Default);

            foreach (KeyValuePair <EntitySet, List <EntitySet> > keyValuePair in keyToListMap2.KeyValuePairs)
            {
                EntitySet key = keyValuePair.Key;
                foreach (EntitySet entitySet in keyValuePair.Value)
                {
                    OpCellTreeNode opCellTreeNode3;
                    if (dictionary.TryGetValue(entitySet, out opCellTreeNode3) && !nestedExtents.ContainsKey(entitySet) && !BasicViewGenerator.CheckLOJCycle(entitySet, key, nestedExtents))
                    {
                        dictionary[keyValuePair.Key].Add((CellTreeNode)opCellTreeNode3);
                        nestedExtents.Add(entitySet, key);
                    }
                }
            }
            foreach (KeyValuePair <EntitySet, OpCellTreeNode> keyValuePair in dictionary)
            {
                if (!nestedExtents.ContainsKey(keyValuePair.Key))
                {
                    OpCellTreeNode opCellTreeNode3 = keyValuePair.Value;
                    if (cellTreeNodeSet != null && cellTreeNodeSet.Contains(opCellTreeNode3.Children[0]))
                    {
                        opCellTreeNode2.Add((CellTreeNode)opCellTreeNode3);
                    }
                    else
                    {
                        opCellTreeNode1.Add((CellTreeNode)opCellTreeNode3);
                    }
                }
            }
            return(opCellTreeNode1.Flatten());
        }
        internal FunctionImportStructuralTypeMappingKB(
            IEnumerable<FunctionImportStructuralTypeMapping> structuralTypeMappings,
            ItemCollection itemCollection)
        {
            DebugCheck.NotNull(structuralTypeMappings);
            DebugCheck.NotNull(itemCollection);

            m_itemCollection = itemCollection;

            // If no specific type mapping.
            if (structuralTypeMappings.Count() == 0)
            {
                // Initialize with defaults.
                ReturnTypeColumnsRenameMapping = new Dictionary<string, FunctionImportReturnTypeStructuralTypeColumnRenameMapping>();
                NormalizedEntityTypeMappings =
                    new ReadOnlyCollection<FunctionImportNormalizedEntityTypeMapping>(
                        new List<FunctionImportNormalizedEntityTypeMapping>());
                DiscriminatorColumns = new ReadOnlyCollection<string>(new List<string>());
                MappedEntityTypes = new ReadOnlyCollection<EntityType>(new List<EntityType>());
                return;
            }

            var entityTypeMappings = structuralTypeMappings.OfType<FunctionImportEntityTypeMapping>();

            // FunctionImportEntityTypeMapping
            if (null != entityTypeMappings
                && null != entityTypeMappings.FirstOrDefault())
            {
                var isOfTypeEntityTypeColumnsRenameMapping =
                    new Dictionary<EntityType, Collection<FunctionImportReturnTypePropertyMapping>>();
                var entityTypeColumnsRenameMapping = new Dictionary<EntityType, Collection<FunctionImportReturnTypePropertyMapping>>();
                var normalizedEntityTypeMappings = new List<FunctionImportNormalizedEntityTypeMapping>();

                // Collect all mapped entity types.
                MappedEntityTypes = entityTypeMappings
                    .SelectMany(mapping => mapping.GetMappedEntityTypes(m_itemCollection))
                    .Distinct()
                    .ToList()
                    .AsReadOnly();

                // Collect all discriminator columns.
                DiscriminatorColumns = entityTypeMappings
                    .SelectMany(mapping => mapping.GetDiscriminatorColumns())
                    .Distinct()
                    .ToList()
                    .AsReadOnly();

                m_entityTypeLineInfos = new KeyToListMap<EntityType, LineInfo>(EqualityComparer<EntityType>.Default);
                m_isTypeOfLineInfos = new KeyToListMap<EntityType, LineInfo>(EqualityComparer<EntityType>.Default);

                foreach (var entityTypeMapping in entityTypeMappings)
                {
                    // Remember LineInfos for error reporting.
                    foreach (var entityType in entityTypeMapping.EntityTypes)
                    {
                        m_entityTypeLineInfos.Add(entityType, entityTypeMapping.LineInfo);
                    }
                    foreach (var isTypeOf in entityTypeMapping.IsOfTypeEntityTypes)
                    {
                        m_isTypeOfLineInfos.Add(isTypeOf, entityTypeMapping.LineInfo);
                    }

                    // Create map from column name to condition.
                    var columnMap = entityTypeMapping.Conditions.ToDictionary(
                        condition => condition.ColumnName,
                        condition => condition);

                    // Align conditions with discriminator columns.
                    var columnMappings = new List<FunctionImportEntityTypeMappingCondition>(DiscriminatorColumns.Count);
                    for (var i = 0; i < DiscriminatorColumns.Count; i++)
                    {
                        var discriminatorColumn = DiscriminatorColumns[i];
                        FunctionImportEntityTypeMappingCondition mappingCondition;
                        if (columnMap.TryGetValue(discriminatorColumn, out mappingCondition))
                        {
                            columnMappings.Add(mappingCondition);
                        }
                        else
                        {
                            // Null indicates the value for this discriminator doesn't matter.
                            columnMappings.Add(null);
                        }
                    }

                    // Create bit map for implied entity types.
                    var impliedEntityTypesBitMap = new bool[MappedEntityTypes.Count];
                    var impliedEntityTypesSet = new Set<EntityType>(entityTypeMapping.GetMappedEntityTypes(m_itemCollection));
                    for (var i = 0; i < MappedEntityTypes.Count; i++)
                    {
                        impliedEntityTypesBitMap[i] = impliedEntityTypesSet.Contains(MappedEntityTypes[i]);
                    }

                    // Construct normalized mapping.
                    normalizedEntityTypeMappings.Add(
                        new FunctionImportNormalizedEntityTypeMapping(this, columnMappings, new BitArray(impliedEntityTypesBitMap)));

                    // Construct the rename mappings by adding isTypeOf types and specific entity types to the corresponding lists.
                    foreach (var isOfType in entityTypeMapping.IsOfTypeEntityTypes)
                    {
                        if (!isOfTypeEntityTypeColumnsRenameMapping.Keys.Contains(isOfType))
                        {
                            isOfTypeEntityTypeColumnsRenameMapping.Add(
                                isOfType, new Collection<FunctionImportReturnTypePropertyMapping>());
                        }
                        foreach (var rename in entityTypeMapping.ColumnsRenameList)
                        {
                            isOfTypeEntityTypeColumnsRenameMapping[isOfType].Add(rename);
                        }
                    }
                    foreach (var entityType in entityTypeMapping.EntityTypes)
                    {
                        if (!entityTypeColumnsRenameMapping.Keys.Contains(entityType))
                        {
                            entityTypeColumnsRenameMapping.Add(entityType, new Collection<FunctionImportReturnTypePropertyMapping>());
                        }
                        foreach (var rename in entityTypeMapping.ColumnsRenameList)
                        {
                            entityTypeColumnsRenameMapping[entityType].Add(rename);
                        }
                    }
                }

                ReturnTypeColumnsRenameMapping =
                    new FunctionImportReturnTypeEntityTypeColumnsRenameBuilder(
                        isOfTypeEntityTypeColumnsRenameMapping,
                        entityTypeColumnsRenameMapping)
                        .ColumnRenameMapping;

                NormalizedEntityTypeMappings = new ReadOnlyCollection<FunctionImportNormalizedEntityTypeMapping>(
                    normalizedEntityTypeMappings);
            }
            else
            {
                // FunctionImportComplexTypeMapping
                Debug.Assert(
                    structuralTypeMappings.First() is FunctionImportComplexTypeMapping,
                    "only two types can have renames, complexType and entityType");
                var complexTypeMappings = structuralTypeMappings.Cast<FunctionImportComplexTypeMapping>();

                Debug.Assert(
                    complexTypeMappings.Count() == 1, "how come there are more than 1, complex type cannot derive from other complex type");

                ReturnTypeColumnsRenameMapping = new Dictionary<string, FunctionImportReturnTypeStructuralTypeColumnRenameMapping>();
                foreach (var rename in complexTypeMappings.First().ColumnsRenameList)
                {
                    var columnRenameMapping = new FunctionImportReturnTypeStructuralTypeColumnRenameMapping(rename.CMember);
                    columnRenameMapping.AddRename(
                        new FunctionImportReturnTypeStructuralTypeColumn(
                            rename.SColumn,
                            complexTypeMappings.First().ReturnType,
                            false,
                            rename.LineInfo));
                    ReturnTypeColumnsRenameMapping.Add(rename.CMember, columnRenameMapping);
                }

                // Initialize the entity mapping data as empty.
                NormalizedEntityTypeMappings =
                    new ReadOnlyCollection<FunctionImportNormalizedEntityTypeMapping>(
                        new List<FunctionImportNormalizedEntityTypeMapping>());
                DiscriminatorColumns = new ReadOnlyCollection<string>(
                    new List<string>
                        {
                        });
                MappedEntityTypes = new ReadOnlyCollection<EntityType>(
                    new List<EntityType>
                        {
                        });
            }
        }
Exemplo n.º 26
0
        private CellTreeNode ConvertUnionsToNormalizedLOJs(CellTreeNode rootNode)
        {
            // Recursively, transform the subtrees rooted at rootNode's children.
            for (var i = 0; i < rootNode.Children.Count; i++)
            {
                // Method modifies input as well.
                rootNode.Children[i] = ConvertUnionsToNormalizedLOJs(rootNode.Children[i]);
            }

            // We rewrite only LOJs.
            if (rootNode.OpType != CellTreeOpType.LOJ ||
                rootNode.Children.Count < 2)
            {
                return(rootNode);
            }

            // Create the resulting LOJ node.
            var result = new OpCellTreeNode(m_viewgenContext, rootNode.OpType);

            // Create working collection for the LOJ children.
            var children = new List <CellTreeNode>();

            // If rootNode looks something like ((V0 IJ V1) LOJ V2 LOJ V3),
            // and it turns out that there are FK associations from V2 or V3 pointing, let's say at V0,
            // then we want to rewrite the result as (V1 IJ (V0 LOJ V2 LOJ V3)).
            // If we don't do this, then plan compiler won't have a chance to eliminate LOJ V2 LOJ V3.
            // Hence, flatten the first child or rootNode if it's IJ, but remember that its parts are driving nodes for the LOJ,
            // so that we don't accidentally nest them.
            OpCellTreeNode         resultIJDriver         = null;
            HashSet <CellTreeNode> resultIJDriverChildren = null;

            if (rootNode.Children[0].OpType
                == CellTreeOpType.IJ)
            {
                // Create empty resultIJDriver node and add it as the first child (driving) into the LOJ result.
                resultIJDriver = new OpCellTreeNode(m_viewgenContext, rootNode.Children[0].OpType);
                result.Add(resultIJDriver);

                children.AddRange(rootNode.Children[0].Children);
                resultIJDriverChildren = new HashSet <CellTreeNode>(rootNode.Children[0].Children);
            }
            else
            {
                result.Add(rootNode.Children[0]);
            }

            // Flatten unions in non-driving nodes: (V0 LOJ (V1 Union V2 Union V3)) -> (V0 LOJ V1 LOJ V2 LOJ V3)
            foreach (var child in rootNode.Children.Skip(1))
            {
                var opNode = child as OpCellTreeNode;
                if (opNode != null &&
                    opNode.OpType == CellTreeOpType.Union)
                {
                    children.AddRange(opNode.Children);
                }
                else
                {
                    children.Add(child);
                }
            }

            // A dictionary that maps an extent to the nodes that are from that extent.
            // We want a ref comparer here.
            var extentMap = new KeyToListMap <EntitySet, LeafCellTreeNode>(EqualityComparer <EntitySet> .Default);

            // Note that we skip non-leaf nodes (non-leaf nodes don't have FKs) and attach them directly to the result.
            foreach (var child in children)
            {
                var leaf = child as LeafCellTreeNode;
                if (leaf != null)
                {
                    EntitySetBase extent = GetLeafNodeTable(leaf);
                    if (extent != null)
                    {
                        extentMap.Add((EntitySet)extent, leaf);
                    }
                }
                else
                {
                    if (resultIJDriverChildren != null &&
                        resultIJDriverChildren.Contains(child))
                    {
                        resultIJDriver.Add(child);
                    }
                    else
                    {
                        result.Add(child);
                    }
                }
            }

            // We only deal with simple cases - one node per extent, remove the rest from children and attach directly to result.
            var nonTrivial = extentMap.KeyValuePairs.Where(m => m.Value.Count > 1).ToArray();

            foreach (var m in nonTrivial)
            {
                extentMap.RemoveKey(m.Key);
                foreach (var n in m.Value)
                {
                    if (resultIJDriverChildren != null &&
                        resultIJDriverChildren.Contains(n))
                    {
                        resultIJDriver.Add(n);
                    }
                    else
                    {
                        result.Add(n);
                    }
                }
            }
            Debug.Assert(extentMap.KeyValuePairs.All(m => m.Value.Count == 1), "extentMap must map to single nodes only.");

            // Walk the extents in extentMap and for each extent build PK -> FK1(PK1), FK2(PK2), ... map
            // where PK is the primary key of the left extent, and FKn(PKn) is an FK of a right extent that
            // points to the PK of the left extent and is based on the PK columns of the right extent.
            // Example:
            //           table tBaseType(Id int, c1 int), PK = (tBaseType.Id)
            //           table tDerivedType1(Id int, c2 int), PK1 = (tDerivedType1.Id), FK1 = (tDerivedType1.Id -> tBaseType.Id)
            //           table tDerivedType2(Id int, c3 int), PK2 = (tDerivedType2.Id), FK2 = (tDerivedType2.Id -> tBaseType.Id)
            // Will produce:
            //           (tBaseType) -> (tDerivedType1, tDerivedType2)
            var pkFkMap = new KeyToListMap <EntitySet, EntitySet>(EqualityComparer <EntitySet> .Default);
            // Also for each extent in extentMap, build another map (extent) -> (LOJ node).
            // It will be used to construct the nesting in the next step.
            var extentLOJs = new Dictionary <EntitySet, OpCellTreeNode>(EqualityComparer <EntitySet> .Default);

            foreach (var extentInfo in extentMap.KeyValuePairs)
            {
                var principalExtent = extentInfo.Key;
                foreach (var fkExtent in GetFKOverPKDependents(principalExtent))
                {
                    // Only track fkExtents that are in extentMap.
                    ReadOnlyCollection <LeafCellTreeNode> nodes;
                    if (extentMap.TryGetListForKey(fkExtent, out nodes))
                    {
                        // Make sure that we are not adding resultIJDriverChildren as FK dependents - we do not want them to get nested.
                        if (resultIJDriverChildren == null ||
                            !resultIJDriverChildren.Contains(nodes.Single()))
                        {
                            pkFkMap.Add(principalExtent, fkExtent);
                        }
                    }
                }
                var extentLojNode = new OpCellTreeNode(m_viewgenContext, CellTreeOpType.LOJ);
                extentLojNode.Add(extentInfo.Value.Single());
                extentLOJs.Add(principalExtent, extentLojNode);
            }

            // Construct LOJ nesting inside extentLOJs based on the information in pkFkMap.
            // Also, track nested extents using nestedExtents.
            // Example:
            // We start with nestedExtents empty extentLOJs as such:
            //      tBaseType -> LOJ(BaseTypeNode)
            //      tDerivedType1 -> LOJ(DerivedType1Node)*
            //      tDerivedType2 -> LOJ(DerivedType2Node)**
            // Note that * and ** represent object references. So each time something is nested,
            // we don't clone, but nest the original LOJ. When we get to processing the extent of that LOJ,
            // we might add other children to that nested LOJ.
            // As we walk pkFkMap, we end up with this:
            //      tBaseType -> LOJ(BaseTypeNode, LOJ(DerivedType1Node)*, LOJ(DerivedType2Node)**)
            //      tDerivedType1 -> LOJ(DerivedType1Node)*
            //      tDerivedType2 -> LOJ(DerivedType2Node)**
            // nestedExtens = (tDerivedType1, tDerivedType2)
            var nestedExtents = new Dictionary <EntitySet, EntitySet>(EqualityComparer <EntitySet> .Default);

            foreach (var m in pkFkMap.KeyValuePairs)
            {
                var principalExtent = m.Key;
                foreach (var fkExtent in m.Value)
                {
                    OpCellTreeNode fkExtentLOJ;
                    if (extentLOJs.TryGetValue(fkExtent, out fkExtentLOJ)
                        &&
                        // make sure we don't nest twice and we don't create a cycle.
                        !nestedExtents.ContainsKey(fkExtent) &&
                        !CheckLOJCycle(fkExtent, principalExtent, nestedExtents))
                    {
                        extentLOJs[m.Key].Add(fkExtentLOJ);
                        nestedExtents.Add(fkExtent, principalExtent);
                    }
                }
            }

            // Now we need to grab the LOJs that have not been nested and add them to the result.
            // All LOJs that have been nested must be somewhere inside the LOJs that have not been nested,
            // so they as well end up in the result as part of the unnested ones.
            foreach (var m in extentLOJs)
            {
                if (!nestedExtents.ContainsKey(m.Key))
                {
                    // extentLOJ represents (Vx LOJ Vy LOJ(Vm LOJ Vn)) where Vx is the original node from rootNode.Children or resultIJDriverChildren.
                    var extentLOJ = m.Value;
                    if (resultIJDriverChildren != null &&
                        resultIJDriverChildren.Contains(extentLOJ.Children[0]))
                    {
                        resultIJDriver.Add(extentLOJ);
                    }
                    else
                    {
                        result.Add(extentLOJ);
                    }
                }
            }

            return(result.Flatten());
        }
Exemplo n.º 27
0
        // requires: All slots in this are join tree slots
        // This method is called for an S-side query
        // cQuery is the corresponding C-side query in the cell
        // sourceCell is the original cell for "this" and cQuery
        // effects: Checks if any of the columns in "this" are mapped to multiple properties in cQuery. If so,
        // returns an error record about the duplicated slots
        internal ErrorLog.Record CheckForDuplicateFields(CellQuery cQuery, Cell sourceCell)
        {
            // slotMap stores the slots on the S-side and the
            // C-side properties that it maps to
            var slotMap = new KeyToListMap <MemberProjectedSlot, int>(ProjectedSlot.EqualityComparer);

            // Note that this does work for self-association. In the manager
            // employee example, ManagerId and EmployeeId from the SEmployee
            // table map to the two ends -- Manager.ManagerId and
            // Employee.EmployeeId in the C Space

            for (var i = 0; i < m_projectedSlots.Length; i++)
            {
                var projectedSlot = m_projectedSlots[i];
                var slot          = projectedSlot as MemberProjectedSlot;
                Debug.Assert(slot != null, "All slots for this method must be JoinTreeSlots");
                slotMap.Add(slot, i);
            }

            StringBuilder builder = null;

            // Now determine the entries that have more than one integer per slot
            var isErrorSituation = false;

            foreach (var slot in slotMap.Keys)
            {
                var indexes = slotMap.ListForKey(slot);
                Debug.Assert(indexes.Count >= 1, "Each slot must have one index at least");

                if (indexes.Count > 1
                    &&
                    cQuery.AreSlotsEquivalentViaRefConstraints(indexes) == false)
                {
                    // The column is mapped to more than one property and it
                    // failed the "association corresponds to referential
                    // constraints" check

                    isErrorSituation = true;
                    if (builder == null)
                    {
                        builder = new StringBuilder(Strings.ViewGen_Duplicate_CProperties(Extent.Name));
                        builder.AppendLine();
                    }
                    var tmpBuilder = new StringBuilder();
                    for (var i = 0; i < indexes.Count; i++)
                    {
                        var index = indexes[i];
                        if (i != 0)
                        {
                            tmpBuilder.Append(", ");
                        }
                        // The slot must be a JoinTreeSlot. If it isn't it is an internal error
                        var cSlot = (MemberProjectedSlot)cQuery.m_projectedSlots[index];
                        tmpBuilder.Append(cSlot.ToUserString());
                    }
                    builder.AppendLine(Strings.ViewGen_Duplicate_CProperties_IsMapped(slot.ToUserString(), tmpBuilder.ToString()));
                }
            }

            if (false == isErrorSituation)
            {
                return(null);
            }

            var record = new ErrorLog.Record(ViewGenErrorCode.DuplicateCPropertiesMapped, builder.ToString(), sourceCell, String.Empty);

            return(record);
        }
Exemplo n.º 28
0
 // effects: Given all the cells for a container, groups the cells by
 // the left query's extent and returns a dictionary for it
 private static KeyToListMap<EntitySetBase, Cell> GroupCellsByExtent(IEnumerable<Cell> cells, ViewTarget viewTarget)
 {
     // Partition cells by extent -- extent is the top node in
     // the tree. Even for compositions for now? CHANGE_ADYA_FEATURE_COMPOSITION
     var extentCellMap =
         new KeyToListMap<EntitySetBase, Cell>(EqualityComparer<EntitySetBase>.Default);
     foreach (var cell in cells)
     {
         // Get the cell query and determine its extent
         var cellQuery = cell.GetLeftQuery(viewTarget);
         extentCellMap.Add(cellQuery.Extent, cell);
     }
     return extentCellMap;
 }
        private CellTreeNode ConvertUnionsToNormalizedLOJs(CellTreeNode rootNode)
        {
            // Recursively, transform the subtrees rooted at rootNode's children.
            for (var i = 0; i < rootNode.Children.Count; i++)
            {
                // Method modifies input as well.
                rootNode.Children[i] = ConvertUnionsToNormalizedLOJs(rootNode.Children[i]);
            }

            // We rewrite only LOJs.
            if (rootNode.OpType != CellTreeOpType.LOJ
                || rootNode.Children.Count < 2)
            {
                return rootNode;
            }

            // Create the resulting LOJ node.
            var result = new OpCellTreeNode(m_viewgenContext, rootNode.OpType);

            // Create working collection for the LOJ children.
            var children = new List<CellTreeNode>();

            // If rootNode looks something like ((V0 IJ V1) LOJ V2 LOJ V3),
            // and it turns out that there are FK associations from V2 or V3 pointing, let's say at V0,
            // then we want to rewrite the result as (V1 IJ (V0 LOJ V2 LOJ V3)).
            // If we don't do this, then plan compiler won't have a chance to eliminate LOJ V2 LOJ V3.
            // Hence, flatten the first child or rootNode if it's IJ, but remember that its parts are driving nodes for the LOJ,
            // so that we don't accidentally nest them.
            OpCellTreeNode resultIJDriver = null;
            HashSet<CellTreeNode> resultIJDriverChildren = null;
            if (rootNode.Children[0].OpType
                == CellTreeOpType.IJ)
            {
                // Create empty resultIJDriver node and add it as the first child (driving) into the LOJ result.
                resultIJDriver = new OpCellTreeNode(m_viewgenContext, rootNode.Children[0].OpType);
                result.Add(resultIJDriver);

                children.AddRange(rootNode.Children[0].Children);
                resultIJDriverChildren = new HashSet<CellTreeNode>(rootNode.Children[0].Children);
            }
            else
            {
                result.Add(rootNode.Children[0]);
            }

            // Flatten unions in non-driving nodes: (V0 LOJ (V1 Union V2 Union V3)) -> (V0 LOJ V1 LOJ V2 LOJ V3) 
            foreach (var child in rootNode.Children.Skip(1))
            {
                var opNode = child as OpCellTreeNode;
                if (opNode != null
                    && opNode.OpType == CellTreeOpType.Union)
                {
                    children.AddRange(opNode.Children);
                }
                else
                {
                    children.Add(child);
                }
            }

            // A dictionary that maps an extent to the nodes that are from that extent.
            // We want a ref comparer here.
            var extentMap = new KeyToListMap<EntitySet, LeafCellTreeNode>(EqualityComparer<EntitySet>.Default);
            // Note that we skip non-leaf nodes (non-leaf nodes don't have FKs) and attach them directly to the result.
            foreach (var child in children)
            {
                var leaf = child as LeafCellTreeNode;
                if (leaf != null)
                {
                    EntitySetBase extent = GetLeafNodeTable(leaf);
                    if (extent != null)
                    {
                        extentMap.Add((EntitySet)extent, leaf);
                    }
                }
                else
                {
                    if (resultIJDriverChildren != null
                        && resultIJDriverChildren.Contains(child))
                    {
                        resultIJDriver.Add(child);
                    }
                    else
                    {
                        result.Add(child);
                    }
                }
            }

            // We only deal with simple cases - one node per extent, remove the rest from children and attach directly to result.
            var nonTrivial = extentMap.KeyValuePairs.Where(m => m.Value.Count > 1).ToArray();
            foreach (var m in nonTrivial)
            {
                extentMap.RemoveKey(m.Key);
                foreach (var n in m.Value)
                {
                    if (resultIJDriverChildren != null
                        && resultIJDriverChildren.Contains(n))
                    {
                        resultIJDriver.Add(n);
                    }
                    else
                    {
                        result.Add(n);
                    }
                }
            }
            Debug.Assert(extentMap.KeyValuePairs.All(m => m.Value.Count == 1), "extentMap must map to single nodes only.");

            // Walk the extents in extentMap and for each extent build PK -> FK1(PK1), FK2(PK2), ... map
            // where PK is the primary key of the left extent, and FKn(PKn) is an FK of a right extent that 
            // points to the PK of the left extent and is based on the PK columns of the right extent.
            // Example:
            //           table tBaseType(Id int, c1 int), PK = (tBaseType.Id)
            //           table tDerivedType1(Id int, c2 int), PK1 = (tDerivedType1.Id), FK1 = (tDerivedType1.Id -> tBaseType.Id)
            //           table tDerivedType2(Id int, c3 int), PK2 = (tDerivedType2.Id), FK2 = (tDerivedType2.Id -> tBaseType.Id)
            // Will produce:
            //           (tBaseType) -> (tDerivedType1, tDerivedType2)
            var pkFkMap = new KeyToListMap<EntitySet, EntitySet>(EqualityComparer<EntitySet>.Default);
            // Also for each extent in extentMap, build another map (extent) -> (LOJ node).
            // It will be used to construct the nesting in the next step.
            var extentLOJs = new Dictionary<EntitySet, OpCellTreeNode>(EqualityComparer<EntitySet>.Default);
            foreach (var extentInfo in extentMap.KeyValuePairs)
            {
                var principalExtent = extentInfo.Key;
                foreach (var fkExtent in GetFKOverPKDependents(principalExtent))
                {
                    // Only track fkExtents that are in extentMap.
                    ReadOnlyCollection<LeafCellTreeNode> nodes;
                    if (extentMap.TryGetListForKey(fkExtent, out nodes))
                    {
                        // Make sure that we are not adding resultIJDriverChildren as FK dependents - we do not want them to get nested.
                        if (resultIJDriverChildren == null
                            || !resultIJDriverChildren.Contains(nodes.Single()))
                        {
                            pkFkMap.Add(principalExtent, fkExtent);
                        }
                    }
                }
                var extentLojNode = new OpCellTreeNode(m_viewgenContext, CellTreeOpType.LOJ);
                extentLojNode.Add(extentInfo.Value.Single());
                extentLOJs.Add(principalExtent, extentLojNode);
            }

            // Construct LOJ nesting inside extentLOJs based on the information in pkFkMap.
            // Also, track nested extents using nestedExtents.
            // Example:
            // We start with nestedExtents empty extentLOJs as such:
            //      tBaseType -> LOJ(BaseTypeNode)
            //      tDerivedType1 -> LOJ(DerivedType1Node)*
            //      tDerivedType2 -> LOJ(DerivedType2Node)**
            // Note that * and ** represent object references. So each time something is nested, 
            // we don't clone, but nest the original LOJ. When we get to processing the extent of that LOJ,
            // we might add other children to that nested LOJ.
            // As we walk pkFkMap, we end up with this:
            //      tBaseType -> LOJ(BaseTypeNode, LOJ(DerivedType1Node)*, LOJ(DerivedType2Node)**)
            //      tDerivedType1 -> LOJ(DerivedType1Node)*
            //      tDerivedType2 -> LOJ(DerivedType2Node)**
            // nestedExtens = (tDerivedType1, tDerivedType2)
            var nestedExtents = new Dictionary<EntitySet, EntitySet>(EqualityComparer<EntitySet>.Default);
            foreach (var m in pkFkMap.KeyValuePairs)
            {
                var principalExtent = m.Key;
                foreach (var fkExtent in m.Value)
                {
                    OpCellTreeNode fkExtentLOJ;
                    if (extentLOJs.TryGetValue(fkExtent, out fkExtentLOJ) &&
                        // make sure we don't nest twice and we don't create a cycle.
                        !nestedExtents.ContainsKey(fkExtent)
                        && !CheckLOJCycle(fkExtent, principalExtent, nestedExtents))
                    {
                        extentLOJs[m.Key].Add(fkExtentLOJ);
                        nestedExtents.Add(fkExtent, principalExtent);
                    }
                }
            }

            // Now we need to grab the LOJs that have not been nested and add them to the result.
            // All LOJs that have been nested must be somewhere inside the LOJs that have not been nested,
            // so they as well end up in the result as part of the unnested ones.
            foreach (var m in extentLOJs)
            {
                if (!nestedExtents.ContainsKey(m.Key))
                {
                    // extentLOJ represents (Vx LOJ Vy LOJ(Vm LOJ Vn)) where Vx is the original node from rootNode.Children or resultIJDriverChildren.
                    var extentLOJ = m.Value;
                    if (resultIJDriverChildren != null
                        && resultIJDriverChildren.Contains(extentLOJ.Children[0]))
                    {
                        resultIJDriver.Add(extentLOJ);
                    }
                    else
                    {
                        result.Add(extentLOJ);
                    }
                }
            }

            return result.Flatten();
        }
        // requires: The tree rooted at cellTreeNode is an FOJ tree of
        // LeafCellTreeNodes only, i.e., there is an FOJ node with the
        // children being LeafCellTreeNodes
        // 
        // effects: Given a tree rooted at rootNode, ensures that cells
        // of the same right extent are placed in their own subtree below
        // cellTreeNode. That is, if there are 3 cells of extent A and 2 of
        // extent B (i.e., 5 cells with an FOJ on it), the resulting tree has
        // an FOJ node with two children -- FOJ nodes. These FOJ nodes have 2
        // and 3 children
        internal CellTreeNode GroupByRightExtent(CellTreeNode rootNode)
        {
            // A dictionary that maps an extent to the nodes are from that extent
            // We want a ref comparer here
            var extentMap =
                new KeyToListMap<EntitySetBase, LeafCellTreeNode>(EqualityComparer<EntitySetBase>.Default);

            // CR_Meek_Low: method can be simplified (Map<Extent, OpCellTreeNode>, populate as you go)
            // (becomes self-documenting)
            // For each leaf child, find the extent of the child and place it
            // in extentMap
            foreach (LeafCellTreeNode childNode in rootNode.Children)
            {
                // A cell may contain P, P.PA -- we return P
                // CHANGE_ADYA_FEATURE_COMPOSITION Need to fix for composition!!
                var extent = childNode.LeftCellWrapper.RightCellQuery.Extent; // relation or extent to group by
                Debug.Assert(extent != null, "Each cell must have a right extent");

                // Add the childNode as a child of the FOJ tree for "extent"
                extentMap.Add(extent, childNode);
            }
            // Now go through the extent map and create FOJ nodes for each extent
            // Place the nodes for that extent in the newly-created FOJ subtree
            // Also add the op node for every node as a child of the final result
            var result = new OpCellTreeNode(m_viewgenContext, CellTreeOpType.FOJ);

            foreach (var extent in extentMap.Keys)
            {
                var extentFojNode = new OpCellTreeNode(m_viewgenContext, CellTreeOpType.FOJ);
                foreach (var childNode in extentMap.ListForKey(extent))
                {
                    extentFojNode.Add(childNode);
                }
                result.Add(extentFojNode);
            }
            // We call Flatten to remove any unnecessary nestings
            // where an OpNode has only 1 child.
            return result.Flatten();
        }
        // Loads and registers any function mapping translators for the given extent (and related container)
        private void InitializeFunctionMappingTranslators(EntitySetBase entitySetBase, EntityContainerMapping mapping)
        {
            var requiredEnds = new KeyToListMap <AssociationSet, AssociationEndMember>(
                EqualityComparer <AssociationSet> .Default);

            // see if function mapping metadata needs to be processed
            if (!m_functionMappingTranslators.ContainsKey(entitySetBase))
            {
                // load all function mapping data from the current entity container
                foreach (EntitySetMapping entitySetMapping in mapping.EntitySetMaps)
                {
                    if (0 < entitySetMapping.ModificationFunctionMappings.Count)
                    {
                        // register the function mapping
                        m_functionMappingTranslators.Add(
                            entitySetMapping.Set, ModificationFunctionMappingTranslator.CreateEntitySetTranslator(entitySetMapping));

                        // register "null" function translators for all implicitly mapped association sets
                        foreach (var end in entitySetMapping.ImplicitlyMappedAssociationSetEnds)
                        {
                            var associationSet = end.ParentAssociationSet;
                            if (!m_functionMappingTranslators.ContainsKey(associationSet))
                            {
                                m_functionMappingTranslators.Add(
                                    associationSet, ModificationFunctionMappingTranslator.CreateAssociationSetTranslator(null));
                            }

                            // Remember that the current entity set is required for all updates to the collocated
                            // relationship set. This entity set's end is opposite the target end for the mapping.
                            var oppositeEnd = MetadataHelper.GetOppositeEnd(end);
                            requiredEnds.Add(associationSet, oppositeEnd.CorrespondingAssociationEndMember);
                        }
                    }
                    else
                    {
                        // register null translator (so that we never attempt to process this extent again)
                        m_functionMappingTranslators.Add(entitySetMapping.Set, null);
                    }
                }

                foreach (AssociationSetMapping associationSetMapping in mapping.RelationshipSetMaps)
                {
                    if (null != associationSetMapping.ModificationFunctionMapping)
                    {
                        var set = (AssociationSet)associationSetMapping.Set;

                        // use indexer rather than Add since the association set may already have an implicit function
                        // mapping -- this explicit function mapping takes precedence in such cases
                        m_functionMappingTranslators.Add(
                            set,
                            ModificationFunctionMappingTranslator.CreateAssociationSetTranslator(associationSetMapping));

                        // remember that we've seen a function mapping for this association set, which overrides
                        // any other behaviors for determining required/optional ends
                        requiredEnds.AddRange(set, Enumerable.Empty <AssociationEndMember>());
                    }
                    else
                    {
                        if (!m_functionMappingTranslators.ContainsKey(associationSetMapping.Set))
                        {
                            // register null translator (so that we never attempt to process this extent again)
                            m_functionMappingTranslators.Add(associationSetMapping.Set, null);
                        }
                    }
                }
            }

            // register association metadata for all association sets encountered
            foreach (var associationSet in requiredEnds.Keys)
            {
                m_associationSetMetadata.Add(
                    associationSet, new AssociationSetMetadata(
                        requiredEnds.EnumerateValues(associationSet)));
            }
        }
        internal FunctionImportStructuralTypeMappingKB(
            IEnumerable <FunctionImportStructuralTypeMapping> structuralTypeMappings,
            ItemCollection itemCollection)
        {
            DebugCheck.NotNull(structuralTypeMappings);
            DebugCheck.NotNull(itemCollection);

            m_itemCollection = itemCollection;

            // If no specific type mapping.
            if (structuralTypeMappings.Count() == 0)
            {
                // Initialize with defaults.
                ReturnTypeColumnsRenameMapping = new Dictionary <string, FunctionImportReturnTypeStructuralTypeColumnRenameMapping>();
                NormalizedEntityTypeMappings   =
                    new ReadOnlyCollection <FunctionImportNormalizedEntityTypeMapping>(
                        new List <FunctionImportNormalizedEntityTypeMapping>());
                DiscriminatorColumns = new ReadOnlyCollection <string>(new List <string>());
                MappedEntityTypes    = new ReadOnlyCollection <EntityType>(new List <EntityType>());
                return;
            }

            var entityTypeMappings = structuralTypeMappings.OfType <FunctionImportEntityTypeMapping>();

            // FunctionImportEntityTypeMapping
            if (null != entityTypeMappings &&
                null != entityTypeMappings.FirstOrDefault())
            {
                var isOfTypeEntityTypeColumnsRenameMapping =
                    new Dictionary <EntityType, Collection <FunctionImportReturnTypePropertyMapping> >();
                var entityTypeColumnsRenameMapping = new Dictionary <EntityType, Collection <FunctionImportReturnTypePropertyMapping> >();
                var normalizedEntityTypeMappings   = new List <FunctionImportNormalizedEntityTypeMapping>();

                // Collect all mapped entity types.
                MappedEntityTypes = entityTypeMappings
                                    .SelectMany(mapping => mapping.GetMappedEntityTypes(m_itemCollection))
                                    .Distinct()
                                    .ToList()
                                    .AsReadOnly();

                // Collect all discriminator columns.
                DiscriminatorColumns = entityTypeMappings
                                       .SelectMany(mapping => mapping.GetDiscriminatorColumns())
                                       .Distinct()
                                       .ToList()
                                       .AsReadOnly();

                m_entityTypeLineInfos = new KeyToListMap <EntityType, LineInfo>(EqualityComparer <EntityType> .Default);
                m_isTypeOfLineInfos   = new KeyToListMap <EntityType, LineInfo>(EqualityComparer <EntityType> .Default);

                foreach (var entityTypeMapping in entityTypeMappings)
                {
                    // Remember LineInfos for error reporting.
                    foreach (var entityType in entityTypeMapping.EntityTypes)
                    {
                        m_entityTypeLineInfos.Add(entityType, entityTypeMapping.LineInfo);
                    }
                    foreach (var isTypeOf in entityTypeMapping.IsOfTypeEntityTypes)
                    {
                        m_isTypeOfLineInfos.Add(isTypeOf, entityTypeMapping.LineInfo);
                    }

                    // Create map from column name to condition.
                    var columnMap = entityTypeMapping.Conditions.ToDictionary(
                        condition => condition.ColumnName,
                        condition => condition);

                    // Align conditions with discriminator columns.
                    var columnMappings = new List <FunctionImportEntityTypeMappingCondition>(DiscriminatorColumns.Count);
                    for (var i = 0; i < DiscriminatorColumns.Count; i++)
                    {
                        var discriminatorColumn = DiscriminatorColumns[i];
                        FunctionImportEntityTypeMappingCondition mappingCondition;
                        if (columnMap.TryGetValue(discriminatorColumn, out mappingCondition))
                        {
                            columnMappings.Add(mappingCondition);
                        }
                        else
                        {
                            // Null indicates the value for this discriminator doesn't matter.
                            columnMappings.Add(null);
                        }
                    }

                    // Create bit map for implied entity types.
                    var impliedEntityTypesBitMap = new bool[MappedEntityTypes.Count];
                    var impliedEntityTypesSet    = new Set <EntityType>(entityTypeMapping.GetMappedEntityTypes(m_itemCollection));
                    for (var i = 0; i < MappedEntityTypes.Count; i++)
                    {
                        impliedEntityTypesBitMap[i] = impliedEntityTypesSet.Contains(MappedEntityTypes[i]);
                    }

                    // Construct normalized mapping.
                    normalizedEntityTypeMappings.Add(
                        new FunctionImportNormalizedEntityTypeMapping(this, columnMappings, new BitArray(impliedEntityTypesBitMap)));

                    // Construct the rename mappings by adding isTypeOf types and specific entity types to the corresponding lists.
                    foreach (var isOfType in entityTypeMapping.IsOfTypeEntityTypes)
                    {
                        if (!isOfTypeEntityTypeColumnsRenameMapping.Keys.Contains(isOfType))
                        {
                            isOfTypeEntityTypeColumnsRenameMapping.Add(
                                isOfType, new Collection <FunctionImportReturnTypePropertyMapping>());
                        }
                        foreach (var rename in entityTypeMapping.ColumnsRenameList)
                        {
                            isOfTypeEntityTypeColumnsRenameMapping[isOfType].Add(rename);
                        }
                    }
                    foreach (var entityType in entityTypeMapping.EntityTypes)
                    {
                        if (!entityTypeColumnsRenameMapping.Keys.Contains(entityType))
                        {
                            entityTypeColumnsRenameMapping.Add(entityType, new Collection <FunctionImportReturnTypePropertyMapping>());
                        }
                        foreach (var rename in entityTypeMapping.ColumnsRenameList)
                        {
                            entityTypeColumnsRenameMapping[entityType].Add(rename);
                        }
                    }
                }

                ReturnTypeColumnsRenameMapping =
                    new FunctionImportReturnTypeEntityTypeColumnsRenameBuilder(
                        isOfTypeEntityTypeColumnsRenameMapping,
                        entityTypeColumnsRenameMapping)
                    .ColumnRenameMapping;

                NormalizedEntityTypeMappings = new ReadOnlyCollection <FunctionImportNormalizedEntityTypeMapping>(
                    normalizedEntityTypeMappings);
            }
            else
            {
                // FunctionImportComplexTypeMapping
                Debug.Assert(
                    structuralTypeMappings.First() is FunctionImportComplexTypeMapping,
                    "only two types can have renames, complexType and entityType");
                var complexTypeMappings = structuralTypeMappings.Cast <FunctionImportComplexTypeMapping>();

                Debug.Assert(
                    complexTypeMappings.Count() == 1, "how come there are more than 1, complex type cannot derive from other complex type");

                ReturnTypeColumnsRenameMapping = new Dictionary <string, FunctionImportReturnTypeStructuralTypeColumnRenameMapping>();
                foreach (var rename in complexTypeMappings.First().ColumnsRenameList)
                {
                    var columnRenameMapping = new FunctionImportReturnTypeStructuralTypeColumnRenameMapping(rename.CMember);
                    columnRenameMapping.AddRename(
                        new FunctionImportReturnTypeStructuralTypeColumn(
                            rename.SColumn,
                            complexTypeMappings.First().ReturnType,
                            false,
                            rename.LineInfo));
                    ReturnTypeColumnsRenameMapping.Add(rename.CMember, columnRenameMapping);
                }

                // Initialize the entity mapping data as empty.
                NormalizedEntityTypeMappings =
                    new ReadOnlyCollection <FunctionImportNormalizedEntityTypeMapping>(
                        new List <FunctionImportNormalizedEntityTypeMapping>());
                DiscriminatorColumns = new ReadOnlyCollection <string>(
                    new List <string>
                {
                });
                MappedEntityTypes = new ReadOnlyCollection <EntityType>(
                    new List <EntityType>
                {
                });
            }
        }
        // effects: A restrictive version of GroupLeafChildrenByExtent --
        // only for LASJ and LOJ nodes (works for LOJ only when A LOJ B LOJ C
        // s.t., B and C are subsets of A -- in our case that is how LOJs are constructed
        private static List<CellTreeNode> GroupNonAssociativeLeafChildren(List<CellTreeNode> nodes)
        {
            // Keep track of leaf cells for each extent ignoring the 0th child
            KeyToListMap<EntitySetBase, CellTreeNode> extentMap =
                new KeyToListMap<EntitySetBase, CellTreeNode>(EqualityComparer<EntitySetBase>.Default);

            List<CellTreeNode> newNodes = new List<CellTreeNode>();
            List<CellTreeNode> nonLeafNodes = new List<CellTreeNode>();
            // Add the 0th child
            newNodes.Add(nodes[0]);
            for (int i = 1; i < nodes.Count; i++)
            {
                CellTreeNode node = nodes[i];
                LeafCellTreeNode leafNode = node as LeafCellTreeNode;
                // All non-leaf nodes are added to the result now
                // leaf nodes are added outside the loop
                if (leafNode != null)
                {
                    extentMap.Add(leafNode.LeftCellWrapper.RightCellQuery.Extent, leafNode);
                }
                else
                {
                    nonLeafNodes.Add(node);
                }
            }
            // Go through the map and add the leaf children
            // If a group of nodes exists for the 0th node's extent -- place
            // that group first
            LeafCellTreeNode firstNode = nodes[0] as LeafCellTreeNode;
            if (firstNode != null)
            {
                EntitySetBase firstExtent = firstNode.LeftCellWrapper.RightCellQuery.Extent;
                if (extentMap.ContainsKey(firstExtent))
                {
                    newNodes.AddRange(extentMap.ListForKey(firstExtent));
                    // Remove this set from the map
                    extentMap.RemoveKey(firstExtent);
                }
            }
            newNodes.AddRange(extentMap.AllValues);
            newNodes.AddRange(nonLeafNodes);
            return newNodes;
        }
Exemplo n.º 34
0
        // effects: Checks if all sViewConstraints are implied by the
        // constraints in cViewConstraints. If some S-level constraints are
        // not implied, adds errors/warnings to m_errorLog
        private void CheckImplication(ViewSchemaConstraints cViewConstraints, ViewSchemaConstraints sViewConstraints)
        {
            // Check key constraints
            // i.e., if S has a key <k1, k2>, C must have a key that is a subset of this
            CheckImplicationKeyConstraints(cViewConstraints, sViewConstraints);

            // For updates, we need to ensure the following: for every
            // extent E, table T pair, some key of E is implied by T's key

            // Get all key constraints for each extent and each table
            var extentPairConstraints =
                new KeyToListMap<ExtentPair, ViewKeyConstraint>(EqualityComparer<ExtentPair>.Default);

            foreach (var cKeyConstraint in cViewConstraints.KeyConstraints)
            {
                var pair = new ExtentPair(cKeyConstraint.Cell.CQuery.Extent, cKeyConstraint.Cell.SQuery.Extent);
                extentPairConstraints.Add(pair, cKeyConstraint);
            }

            // Now check that we guarantee at least one constraint per
            // extent/table pair
            foreach (var extentPair in extentPairConstraints.Keys)
            {
                var cKeyConstraints = extentPairConstraints.ListForKey(extentPair);
                var sImpliesSomeC = false;
                // Go through all key constraints for the extent/table pair, and find one that S implies
                foreach (var cKeyConstraint in cKeyConstraints)
                {
                    foreach (var sKeyConstraint in sViewConstraints.KeyConstraints)
                    {
                        if (sKeyConstraint.Implies(cKeyConstraint))
                        {
                            sImpliesSomeC = true;
                            break; // The implication holds - so no problem
                        }
                    }
                }
                if (sImpliesSomeC == false)
                {
                    // Indicate that at least one key must be ensured on the S-side
                    m_errorLog.AddEntry(ViewKeyConstraint.GetErrorRecord(cKeyConstraints));
                }
            }
        }
Exemplo n.º 35
0
        // requires: All slots in this are join tree slots
        // This method is called for an S-side query
        // cQuery is the corresponding C-side query in the cell
        // sourceCell is the original cell for "this" and cQuery
        // effects: Checks if any of the columns in "this" are mapped to multiple properties in cQuery. If so,
        // returns an error record about the duplicated slots
        internal ErrorLog.Record CheckForDuplicateFields(CellQuery cQuery, Cell sourceCell)
        {
            // slotMap stores the slots on the S-side and the
            // C-side properties that it maps to
            var slotMap = new KeyToListMap<MemberProjectedSlot, int>(ProjectedSlot.EqualityComparer);

            // Note that this does work for self-association. In the manager
            // employee example, ManagerId and EmployeeId from the SEmployee
            // table map to the two ends -- Manager.ManagerId and
            // Employee.EmployeeId in the C Space

            for (var i = 0; i < m_projectedSlots.Length; i++)
            {
                var projectedSlot = m_projectedSlots[i];
                var slot = projectedSlot as MemberProjectedSlot;
                Debug.Assert(slot != null, "All slots for this method must be JoinTreeSlots");
                slotMap.Add(slot, i);
            }

            StringBuilder builder = null;

            // Now determine the entries that have more than one integer per slot
            var isErrorSituation = false;

            foreach (var slot in slotMap.Keys)
            {
                var indexes = slotMap.ListForKey(slot);
                Debug.Assert(indexes.Count >= 1, "Each slot must have one index at least");

                if (indexes.Count > 1
                    &&
                    cQuery.AreSlotsEquivalentViaRefConstraints(indexes) == false)
                {
                    // The column is mapped to more than one property and it
                    // failed the "association corresponds to referential
                    // constraints" check

                    isErrorSituation = true;
                    if (builder == null)
                    {
                        builder = new StringBuilder(Strings.ViewGen_Duplicate_CProperties(Extent.Name));
                        builder.AppendLine();
                    }
                    var tmpBuilder = new StringBuilder();
                    for (var i = 0; i < indexes.Count; i++)
                    {
                        var index = indexes[i];
                        if (i != 0)
                        {
                            tmpBuilder.Append(", ");
                        }
                        // The slot must be a JoinTreeSlot. If it isn't it is an internal error
                        var cSlot = (MemberProjectedSlot)cQuery.m_projectedSlots[index];
                        tmpBuilder.Append(cSlot.ToUserString());
                    }
                    builder.AppendLine(Strings.ViewGen_Duplicate_CProperties_IsMapped(slot.ToUserString(), tmpBuilder.ToString()));
                }
            }

            if (false == isErrorSituation)
            {
                return null;
            }

            var record = new ErrorLog.Record(ViewGenErrorCode.DuplicateCPropertiesMapped, builder.ToString(), sourceCell, String.Empty);
            return record;
        }
        // effects: Given a list of node, produces a new list in which all
        // leaf nodes of the same extent are adjacent to each other. Non-leaf
        // nodes are also adjacent to each other. CHANGE_[....]_IMPROVE: Merge with GroupByRightExtent
        private static List<CellTreeNode> GroupLeafChildrenByExtent(List<CellTreeNode> nodes)
        {
            // Keep track of leaf cells for each extent
            KeyToListMap<EntitySetBase, CellTreeNode> extentMap =
                new KeyToListMap<EntitySetBase, CellTreeNode>(EqualityComparer<EntitySetBase>.Default);

            List<CellTreeNode> newNodes = new List<CellTreeNode>();
            foreach (CellTreeNode node in nodes)
            {
                LeafCellTreeNode leafNode = node as LeafCellTreeNode;
                // All non-leaf nodes are added to the result now
                // leaf nodes are added outside the loop
                if (leafNode != null)
                {
                    extentMap.Add(leafNode.LeftCellWrapper.RightCellQuery.Extent, leafNode);
                }
                else
                {
                    newNodes.Add(node);
                }
            }
            // Go through the map and add the leaf children
            newNodes.AddRange(extentMap.AllValues);
            return newNodes;
        }