private bool CheckConstraintWhenParentChildMapped(
            Cell cell,
            ErrorLog errorLog,
            AssociationEndMember parentEnd,
            ConfigViewGenerator config)
        {
            bool flag = true;

            if (parentEnd.RelationshipMultiplicity == RelationshipMultiplicity.Many)
            {
                ErrorLog.Record record = new ErrorLog.Record(ViewGenErrorCode.ForeignKeyUpperBoundMustBeOne, Strings.ViewGen_Foreign_Key_UpperBound_MustBeOne((object)this.ToUserString(), (object)cell.CQuery.Extent.Name, (object)parentEnd.Name), cell, string.Empty);
                errorLog.AddEntry(record);
                flag = false;
            }
            if (!MemberPath.AreAllMembersNullable(this.ChildColumns) && parentEnd.RelationshipMultiplicity != RelationshipMultiplicity.One)
            {
                ErrorLog.Record record = new ErrorLog.Record(ViewGenErrorCode.ForeignKeyLowerBoundMustBeOne, Strings.ViewGen_Foreign_Key_LowerBound_MustBeOne((object)this.ToUserString(), (object)cell.CQuery.Extent.Name, (object)parentEnd.Name), cell, string.Empty);
                errorLog.AddEntry(record);
                flag = false;
            }
            if (config.IsNormalTracing && flag)
            {
                Trace.WriteLine("Foreign key mapped to relationship " + cell.CQuery.Extent.Name);
            }
            return(flag);
        }
 internal InputForComputingCellGroups(
     EntityContainerMapping containerMapping,
     ConfigViewGenerator config)
 {
     this.ContainerMapping = containerMapping;
     this.Config           = config;
 }
        // requires: constraint.ChildColumns form a key in
        // constraint.ChildTable (actually they should subsume the primary key)
        private void GuaranteeForeignKeyConstraintInCSpace(QueryRewriter childRewriter, QueryRewriter parentRewriter,
                                                           ErrorLog errorLog, ConfigViewGenerator config)
        {
            ViewgenContext childContext  = childRewriter.ViewgenContext;
            ViewgenContext parentContext = parentRewriter.ViewgenContext;
            CellTreeNode   cNode         = childRewriter.BasicView;
            CellTreeNode   pNode         = parentRewriter.BasicView;

            FragmentQueryProcessor qp = FragmentQueryProcessor.Merge(childContext.RightFragmentQP, parentContext.RightFragmentQP);
            bool cImpliesP            = qp.IsContainedIn(cNode.RightFragmentQuery, pNode.RightFragmentQuery);

            if (false == cImpliesP)
            {
                // Foreign key constraint not being ensured in C-space
                string childExtents  = LeftCellWrapper.GetExtentListAsUserString(cNode.GetLeaves());
                string parentExtents = LeftCellWrapper.GetExtentListAsUserString(pNode.GetLeaves());
                string message       = System.Data.Entity.Strings.ViewGen_Foreign_Key_Not_Guaranteed_InCSpace(
                    ToUserString());
                // Add all wrappers into allWrappers
                Set <LeftCellWrapper> allWrappers = new Set <LeftCellWrapper>(pNode.GetLeaves());
                allWrappers.AddRange(cNode.GetLeaves());
                ErrorLog.Record record = new ErrorLog.Record(true, ViewGenErrorCode.ForeignKeyNotGuaranteedInCSpace, message, allWrappers, String.Empty);
                errorLog.AddEntry(record);
            }
        }
        // effects: Shrinks the domain of members whose types can be enumerated - currently it applies
        // only to boolean type as for enums we don't restrict enum values to specified members only.
        // For example NOT(False, True, Null) for a boolean domain should be removed
        internal void ReduceEnumerableDomainToEnumeratedValues(ConfigViewGenerator config)
        {
            // Go through the two maps

            ReduceEnumerableDomainToEnumeratedValues(m_conditionDomainMap, config, m_edmItemCollection);
            ReduceEnumerableDomainToEnumeratedValues(m_nonConditionDomainMap, config, m_edmItemCollection);
        }
Пример #5
0
        internal QueryRewriter(EdmType generatedType, ViewgenContext context, ViewGenMode typesGenerationMode)
        {
            Debug.Assert(typesGenerationMode != ViewGenMode.GenerateAllViews);

            _typesGenerationMode = typesGenerationMode;
            _context = context;
            _generatedType = generatedType;
            _domainMap = context.MemberMaps.LeftDomainMap;
            _config = context.Config;
            _identifiers = context.CqlIdentifiers;
            _qp = new RewritingProcessor<Tile<FragmentQuery>>(new DefaultTileProcessor<FragmentQuery>(context.LeftFragmentQP));
            _extentPath = new MemberPath(context.Extent);
            _keyAttributes = new List<MemberPath>(MemberPath.GetKeyMembers(context.Extent, _domainMap));

            // populate _fragmentQueries and _views
            foreach (var leftCellWrapper in _context.AllWrappersForExtent)
            {
                var query = leftCellWrapper.FragmentQuery;
                Tile<FragmentQuery> tile = CreateTile(query);
                _fragmentQueries.Add(query);
                _views.Add(tile);
            }
            Debug.Assert(_views.Count > 0);

            AdjustMemberDomainsForUpdateViews();

            // must be done after adjusting domains
            _domainQuery = GetDomainQuery(FragmentQueries, generatedType);

            _usedViews = new HashSet<FragmentQuery>();
        }
 internal QueryRewriter(
     EdmType generatedType,
     ViewgenContext context,
     ViewGenMode typesGenerationMode)
 {
     this._typesGenerationMode = typesGenerationMode;
     this._context             = context;
     this._generatedType       = generatedType;
     this._domainMap           = context.MemberMaps.LeftDomainMap;
     this._config        = context.Config;
     this._identifiers   = context.CqlIdentifiers;
     this._qp            = new RewritingProcessor <Tile <FragmentQuery> >((TileProcessor <Tile <FragmentQuery> >) new DefaultTileProcessor <FragmentQuery>((TileQueryProcessor <FragmentQuery>)context.LeftFragmentQP));
     this._extentPath    = new MemberPath(context.Extent);
     this._keyAttributes = new List <MemberPath>(MemberPath.GetKeyMembers(context.Extent, this._domainMap));
     foreach (LeftCellWrapper leftCellWrapper in this._context.AllWrappersForExtent)
     {
         FragmentQuery        fragmentQuery = leftCellWrapper.FragmentQuery;
         Tile <FragmentQuery> tile          = (Tile <FragmentQuery>)QueryRewriter.CreateTile(fragmentQuery);
         this._fragmentQueries.Add(fragmentQuery);
         this._views.Add(tile);
     }
     this.AdjustMemberDomainsForUpdateViews();
     this._domainQuery = this.GetDomainQuery(this.FragmentQueries, generatedType);
     this._usedViews   = new HashSet <FragmentQuery>();
 }
 internal static void ThrowMappingException(ErrorLog errorLog, ConfigViewGenerator config)
 {
     InternalMappingException exception = new InternalMappingException(errorLog.ToUserString(), errorLog);
     if (config.IsNormalTracing)
     {
         exception.ErrorLog.PrintTrace();
     }
     throw exception;
 }
        internal static void ThrowMappingException(ErrorLog.Record errorRecord, ConfigViewGenerator config)
        {
            InternalMappingException exception = new InternalMappingException(errorRecord.ToUserString(), errorRecord);

            if (config.IsNormalTracing)
            {
                exception.ErrorLog.PrintTrace();
            }
            throw exception;
        }
        internal static void ThrowMappingException(ErrorLog errorLog, ConfigViewGenerator config)
        {
            InternalMappingException mappingException = new InternalMappingException(errorLog.ToUserString(), errorLog);

            if (config.IsNormalTracing)
            {
                mappingException.ErrorLog.PrintTrace();
            }
            throw mappingException;
        }
        internal MemberDomainMap(
            ViewTarget viewTarget,
            bool isValidationEnabled,
            IEnumerable <Cell> extentCells,
            EdmItemCollection edmItemCollection,
            ConfigViewGenerator config,
            Dictionary <EntityType, Set <EntityType> > inheritanceGraph)
        {
            this.m_conditionDomainMap = new Dictionary <MemberPath, Set <Constant> >(MemberPath.EqualityComparer);
            this.m_edmItemCollection  = edmItemCollection;
            Dictionary <MemberPath, Set <Constant> > dictionary = viewTarget != ViewTarget.UpdateView ? Domain.ComputeConstantDomainSetsForSlotsInQueryViews(extentCells, this.m_edmItemCollection, isValidationEnabled) : Domain.ComputeConstantDomainSetsForSlotsInUpdateViews(extentCells, this.m_edmItemCollection);

            foreach (Cell extentCell in extentCells)
            {
                foreach (MemberRestriction memberRestriction in extentCell.GetLeftQuery(viewTarget).GetConjunctsFromWhereClause())
                {
                    MemberPath     memberPath = memberRestriction.RestrictedMemberSlot.MemberPath;
                    Set <Constant> set;
                    if (!dictionary.TryGetValue(memberPath, out set))
                    {
                        set = Domain.DeriveDomainFromMemberPath(memberPath, edmItemCollection, isValidationEnabled);
                    }
                    if (set.Contains(Constant.Null) || !memberRestriction.Domain.Values.All <Constant>((Func <Constant, bool>)(conditionConstant => conditionConstant.Equals((object)Constant.NotNull))))
                    {
                        if (set.Count <= 0 || !set.Contains(Constant.Null) && memberRestriction.Domain.Values.Contains <Constant>(Constant.Null))
                        {
                            ExceptionHelpers.ThrowMappingException(new ErrorLog.Record(ViewGenErrorCode.InvalidCondition, Strings.ViewGen_InvalidCondition((object)memberPath.PathToString(new bool?(false))), extentCell, string.Empty), config);
                        }
                        if (!memberPath.IsAlwaysDefined(inheritanceGraph))
                        {
                            set.Add(Constant.Undefined);
                        }
                        this.AddToDomainMap(memberPath, (IEnumerable <Constant>)set);
                    }
                }
            }
            this.m_nonConditionDomainMap = new Dictionary <MemberPath, Set <Constant> >(MemberPath.EqualityComparer);
            foreach (Cell extentCell in extentCells)
            {
                foreach (MemberProjectedSlot allQuerySlot in extentCell.GetLeftQuery(viewTarget).GetAllQuerySlots())
                {
                    MemberPath memberPath = allQuerySlot.MemberPath;
                    if (!this.m_conditionDomainMap.ContainsKey(memberPath) && !this.m_nonConditionDomainMap.ContainsKey(memberPath))
                    {
                        Set <Constant> set = Domain.DeriveDomainFromMemberPath(memberPath, this.m_edmItemCollection, true);
                        if (!memberPath.IsAlwaysDefined(inheritanceGraph))
                        {
                            set.Add(Constant.Undefined);
                        }
                        Set <Constant> iconstants = Domain.ExpandNegationsInDomain((IEnumerable <Constant>)set, (IEnumerable <Constant>)set);
                        this.m_nonConditionDomainMap.Add(memberPath, (Set <Constant>) new MemberDomainMap.CellConstantSetInfo(iconstants));
                    }
                }
            }
        }
 internal void CheckConstraint(
     Set <Cell> cells,
     QueryRewriter childRewriter,
     QueryRewriter parentRewriter,
     ErrorLog errorLog,
     ConfigViewGenerator config)
 {
     if (!this.IsConstraintRelevantForCells((IEnumerable <Cell>)cells))
     {
         return;
     }
     if (config.IsNormalTracing)
     {
         Trace.WriteLine(string.Empty);
         Trace.WriteLine(string.Empty);
         Trace.Write("Checking: ");
         Trace.WriteLine((object)this);
     }
     if (childRewriter == null && parentRewriter == null)
     {
         return;
     }
     if (childRewriter == null)
     {
         ErrorLog.Record record = new ErrorLog.Record(ViewGenErrorCode.ForeignKeyMissingTableMapping, Strings.ViewGen_Foreign_Key_Missing_Table_Mapping((object)this.ToUserString(), (object)this.ChildTable.Name), (IEnumerable <LeftCellWrapper>)parentRewriter.UsedCells, string.Empty);
         errorLog.AddEntry(record);
     }
     else if (parentRewriter == null)
     {
         ErrorLog.Record record = new ErrorLog.Record(ViewGenErrorCode.ForeignKeyMissingTableMapping, Strings.ViewGen_Foreign_Key_Missing_Table_Mapping((object)this.ToUserString(), (object)this.ParentTable.Name), (IEnumerable <LeftCellWrapper>)childRewriter.UsedCells, string.Empty);
         errorLog.AddEntry(record);
     }
     else
     {
         if (this.CheckIfConstraintMappedToForeignKeyAssociation(childRewriter, parentRewriter, cells))
         {
             return;
         }
         int count = errorLog.Count;
         if (this.IsForeignKeySuperSetOfPrimaryKeyInChildTable())
         {
             this.GuaranteeForeignKeyConstraintInCSpace(childRewriter, parentRewriter, errorLog);
         }
         else
         {
             this.GuaranteeMappedRelationshipForForeignKey(childRewriter, parentRewriter, (IEnumerable <Cell>)cells, errorLog, config);
         }
         if (count != errorLog.Count)
         {
             return;
         }
         this.CheckForeignKeyColumnOrder(cells, errorLog);
     }
 }
Пример #12
0
        internal static Constant GetDefaultValueForMemberPath(
            MemberPath memberPath,
            IEnumerable <LeftCellWrapper> wrappersForErrorReporting,
            ConfigViewGenerator config)
        {
            Constant defaultConstant = (Constant)null;

            if (!Domain.TryGetDefaultValueForMemberPath(memberPath, out defaultConstant))
            {
                ExceptionHelpers.ThrowMappingException(new ErrorLog.Record(ViewGenErrorCode.NoDefaultValue, Strings.ViewGen_No_Default_Value((object)memberPath.Extent.Name, (object)memberPath.PathToString(new bool?(false))), wrappersForErrorReporting, string.Empty), config);
            }
            return(defaultConstant);
        }
Пример #13
0
        internal static Constant GetDefaultValueForMemberPath(MemberPath memberPath, IEnumerable <LeftCellWrapper> wrappersForErrorReporting,
                                                              ConfigViewGenerator config)
        {
            Constant defaultValue = null;

            if (!Domain.TryGetDefaultValueForMemberPath(memberPath, out defaultValue))
            {
                string          message = Strings.ViewGen_No_Default_Value(memberPath.Extent.Name, memberPath.PathToString(false));
                ErrorLog.Record record  = new ErrorLog.Record(true, ViewGenErrorCode.NoDefaultValue, message, wrappersForErrorReporting, String.Empty);
                ExceptionHelpers.ThrowMappingException(record, config);
            }
            return(defaultValue);
        }
        /// <summary>
        /// This method compiles all the user defined query views in the <paramref name="entityContainerMapping"/>.
        /// </summary>
        private static void CompileUserDefinedQueryViews(StorageEntityContainerMapping entityContainerMapping,
                                                         Dictionary <EntitySetBase, GeneratedView> userDefinedQueryViewsDict,
                                                         Dictionary <OfTypeQVCacheKey, GeneratedView> userDefinedQueryViewsOfTypeDict,
                                                         IList <EdmSchemaError> errors)
        {
            ConfigViewGenerator config = new ConfigViewGenerator();

            foreach (StorageSetMapping setMapping in entityContainerMapping.AllSetMaps)
            {
                if (setMapping.QueryView != null)
                {
                    GeneratedView generatedView;
                    if (!userDefinedQueryViewsDict.TryGetValue(setMapping.Set, out generatedView))
                    {
                        // Parse the view so that we will get back any errors in the view.
                        if (GeneratedView.TryParseUserSpecifiedView(setMapping,
                                                                    setMapping.Set.ElementType,
                                                                    setMapping.QueryView,
                                                                    true, // includeSubtypes
                                                                    entityContainerMapping.StorageMappingItemCollection,
                                                                    config,
                                                                    /*out*/ errors,
                                                                    out generatedView))
                        {
                            // Add first QueryView
                            userDefinedQueryViewsDict.Add(setMapping.Set, generatedView);
                        }

                        // Add all type-specific QueryViews
                        foreach (OfTypeQVCacheKey key in setMapping.GetTypeSpecificQVKeys())
                        {
                            Debug.Assert(key.First.Equals(setMapping.Set));

                            if (GeneratedView.TryParseUserSpecifiedView(setMapping,
                                                                        key.Second.First,  // type
                                                                        setMapping.GetTypeSpecificQueryView(key),
                                                                        key.Second.Second, // includeSubtypes
                                                                        entityContainerMapping.StorageMappingItemCollection,
                                                                        config,
                                                                        /*out*/ errors,
                                                                        out generatedView))
                            {
                                userDefinedQueryViewsOfTypeDict.Add(key, generatedView);
                            }
                        }
                    }
                }
            }
        }
Пример #15
0
        // requires: IsForeignKeySuperSetOfPrimaryKeyInChildTable() is false
        // effects: Given that both the ChildColumns in this and the
        // primaryKey of ChildTable are mapped. Return true iff no error occurred
        private bool CheckConstraintWhenParentChildMapped(
            Cell cell, ErrorLog errorLog,
            AssociationEndMember parentEnd, ConfigViewGenerator config)
        {
            var ok = true;

            // The foreign key constraint has been mapped to a
            // relationship. Check if the multiplicities are consistent
            // If all columns in the child table (corresponding to
            // the constraint) are nullable, the parent end can be
            // 0..1 or 1..1. Else if must be 1..1
            if (parentEnd.RelationshipMultiplicity
                == RelationshipMultiplicity.Many)
            {
                // Parent should at most one since we are talking
                // about foreign keys here
                var message = Strings.ViewGen_Foreign_Key_UpperBound_MustBeOne(
                    ToUserString(),
                    cell.CQuery.Extent.Name, parentEnd.Name);
                var record = new ErrorLog.Record(ViewGenErrorCode.ForeignKeyUpperBoundMustBeOne, message, cell, String.Empty);
                errorLog.AddEntry(record);
                ok = false;
            }

            if (MemberPath.AreAllMembersNullable(ChildColumns) == false &&
                parentEnd.RelationshipMultiplicity != RelationshipMultiplicity.One)
            {
                // Some column in the constraint in the child table
                // is non-nullable and lower bound is not 1
                var message = Strings.ViewGen_Foreign_Key_LowerBound_MustBeOne(
                    ToUserString(),
                    cell.CQuery.Extent.Name, parentEnd.Name);
                var record = new ErrorLog.Record(ViewGenErrorCode.ForeignKeyLowerBoundMustBeOne, message, cell, String.Empty);
                errorLog.AddEntry(record);
                ok = false;
            }

            if (config.IsNormalTracing && ok)
            {
                Trace.WriteLine("Foreign key mapped to relationship " + cell.CQuery.Extent.Name);
            }
            return(ok);
        }
        // requires: IsForeignKeySuperSetOfPrimaryKeyInChildTable() is false
        // and primaryKeys of ChildTable are not mapped in cell. cell
        // corresponds to an association set. parentSet is the set
        // corresponding to the end that we are looking at
        // effects: Checks if the constraint is correctly maintained in
        // C-space via an association set (being a subset of the
        // corresponding entitySet)
        private bool CheckConstraintWhenOnlyParentMapped(Cell cell, EntitySet parentSet, AssociationSet assocSet, AssociationEndMember endMember,
                                                         QueryRewriter childRewriter, QueryRewriter parentRewriter,
                                                         ConfigViewGenerator config)
        {
            ViewgenContext childContext  = childRewriter.ViewgenContext;
            ViewgenContext parentContext = parentRewriter.ViewgenContext;

            CellTreeNode pNode = parentRewriter.BasicView;

            Debug.Assert(pNode != null);

            RoleBoolean endRoleBoolean = new RoleBoolean(assocSet.AssociationSetEnds[endMember.Name]);
            // use query in pNode as a factory to create a bool expression for the endRoleBoolean
            BoolExpression endCondition = pNode.RightFragmentQuery.Condition.Create(endRoleBoolean);
            FragmentQuery  cNodeQuery   = FragmentQuery.Create(pNode.RightFragmentQuery.Attributes, endCondition);

            FragmentQueryProcessor qp = FragmentQueryProcessor.Merge(childContext.RightFragmentQP, parentContext.RightFragmentQP);
            bool cImpliesP            = qp.IsContainedIn(cNodeQuery, pNode.RightFragmentQuery);

            return(cImpliesP);
        }
 private static void ReduceEnumerableDomainToEnumeratedValues(
     Dictionary <MemberPath, Set <Constant> > domainMap,
     ConfigViewGenerator config,
     EdmItemCollection edmItemCollection)
 {
     foreach (MemberPath key in domainMap.Keys)
     {
         if (MetadataHelper.HasDiscreteDomain(key.EdmType))
         {
             Set <Constant> set1 = Domain.DeriveDomainFromMemberPath(key, edmItemCollection, true);
             Set <Constant> set2 = domainMap[key].Difference((IEnumerable <Constant>)set1);
             set2.Remove(Constant.Undefined);
             if (set2.Count > 0)
             {
                 if (config.IsNormalTracing)
                 {
                     Helpers.FormatTraceLine("Changed domain of {0} from {1} - subtract {2}", (object)key, (object)domainMap[key], (object)set2);
                 }
                 domainMap[key].Subtract((IEnumerable <Constant>)set2);
             }
         }
     }
 }
 // effects: Fixes the domains of variables in this as specified in FixEnumerableDomains
 private static void ReduceEnumerableDomainToEnumeratedValues(
     Dictionary <MemberPath, CellConstantSet> domainMap, ConfigViewGenerator config,
     EdmItemCollection edmItemCollection)
 {
     foreach (var member in domainMap.Keys)
     {
         if (MetadataHelper.HasDiscreteDomain(member.EdmType) == false)
         {
             continue;
         }
         var domain = Domain.DeriveDomainFromMemberPath(member, edmItemCollection, true /* leaveDomainUnbounded */);
         var extra  = domainMap[member].Difference(domain);
         extra.Remove(Constant.Undefined);
         if (extra.Count > 0)
         {
             // domainMap has extra members -- we should get rid of them
             if (config.IsNormalTracing)
             {
                 Helpers.FormatTraceLine("Changed domain of {0} from {1} - subtract {2}", member, domainMap[member], extra);
             }
             domainMap[member].Subtract(extra);
         }
     }
 }
        // requires: constraint.ChildColumns form a key in
        // constraint.ChildTable (actually they should subsume the primary key)
        private void GuaranteeForeignKeyConstraintInCSpace(QueryRewriter childRewriter, QueryRewriter parentRewriter,
                                                           ErrorLog errorLog, ConfigViewGenerator config)
        {
            ViewgenContext childContext = childRewriter.ViewgenContext;
            ViewgenContext parentContext = parentRewriter.ViewgenContext;
            CellTreeNode cNode = childRewriter.BasicView;
            CellTreeNode pNode = parentRewriter.BasicView;

            FragmentQueryProcessor qp = FragmentQueryProcessor.Merge(childContext.RightFragmentQP, parentContext.RightFragmentQP);
            bool cImpliesP = qp.IsContainedIn(cNode.RightFragmentQuery, pNode.RightFragmentQuery);

            if (false == cImpliesP)
            {
                // Foreign key constraint not being ensured in C-space
                string childExtents = LeftCellWrapper.GetExtentListAsUserString(cNode.GetLeaves());
                string parentExtents = LeftCellWrapper.GetExtentListAsUserString(pNode.GetLeaves());
                string message = System.Data.Entity.Strings.ViewGen_Foreign_Key_Not_Guaranteed_InCSpace(
                                               ToUserString());
                // Add all wrappers into allWrappers
                Set<LeftCellWrapper> allWrappers = new Set<LeftCellWrapper>(pNode.GetLeaves());
                allWrappers.AddRange(cNode.GetLeaves());
                ErrorLog.Record record = new ErrorLog.Record(true, ViewGenErrorCode.ForeignKeyNotGuaranteedInCSpace, message, allWrappers, String.Empty);
                errorLog.AddEntry(record);
            }
        }
        // requires: IsForeignKeySuperSetOfPrimaryKeyInChildTable() is false
        // effects: Given that both the ChildColumns in this and the
        // primaryKey of ChildTable are mapped. Return true iff no error occurred
        private bool CheckConstraintWhenParentChildMapped(
            Cell cell, ErrorLog errorLog,
            AssociationEndMember parentEnd, ConfigViewGenerator config)
        {
            var ok = true;

            // The foreign key constraint has been mapped to a
            // relationship. Check if the multiplicities are consistent
            // If all columns in the child table (corresponding to
            // the constraint) are nullable, the parent end can be
            // 0..1 or 1..1. Else if must be 1..1
            if (parentEnd.RelationshipMultiplicity
                == RelationshipMultiplicity.Many)
            {
                // Parent should at most one since we are talking
                // about foreign keys here
                var message = Strings.ViewGen_Foreign_Key_UpperBound_MustBeOne(
                    ToUserString(),
                    cell.CQuery.Extent.Name, parentEnd.Name);
                var record = new ErrorLog.Record(ViewGenErrorCode.ForeignKeyUpperBoundMustBeOne, message, cell, String.Empty);
                errorLog.AddEntry(record);
                ok = false;
            }

            if (MemberPath.AreAllMembersNullable(ChildColumns) == false
                && parentEnd.RelationshipMultiplicity != RelationshipMultiplicity.One)
            {
                // Some column in the constraint in the child table
                // is non-nullable and lower bound is not 1
                var message = Strings.ViewGen_Foreign_Key_LowerBound_MustBeOne(
                    ToUserString(),
                    cell.CQuery.Extent.Name, parentEnd.Name);
                var record = new ErrorLog.Record(ViewGenErrorCode.ForeignKeyLowerBoundMustBeOne, message, cell, String.Empty);
                errorLog.AddEntry(record);
                ok = false;
            }

            if (config.IsNormalTracing && ok)
            {
                Trace.WriteLine("Foreign key mapped to relationship " + cell.CQuery.Extent.Name);
            }
            return ok;
        }
        // effects: Ensures that there is a relationship mapped into the C-space for some cell in m_cellGroup. Else
        // adds an error to errorLog
        private void GuaranteeMappedRelationshipForForeignKey(
            QueryRewriter childRewriter, QueryRewriter parentRewriter,
            IEnumerable<Cell> cells,
            ErrorLog errorLog, ConfigViewGenerator config)
        {
            var childContext = childRewriter.ViewgenContext;
            var parentContext = parentRewriter.ViewgenContext;

            // Find a cell where this foreign key is mapped as a relationship
            var prefix = new MemberPath(ChildTable);
            var primaryKey = ExtentKey.GetPrimaryKeyForEntityType(prefix, ChildTable.ElementType);
            var primaryKeyFields = primaryKey.KeyFields;
            var foundCell = false;

            var foundValidParentColumnsForForeignKey = false; //we need to find only one, dont error on any one check being false
            List<ErrorLog.Record> errorListForInvalidParentColumnsForForeignKey = null;
            foreach (var cell in cells)
            {
                if (cell.SQuery.Extent.Equals(ChildTable) == false)
                {
                    continue;
                }

                // The childtable is mapped to a relationship in the C-space in cell
                // Check that all the columns of the foreign key and the primary key in the child table are mapped to some
                // property in the C-space

                var parentEnd = GetRelationEndForColumns(cell, ChildColumns);
                if (parentEnd != null
                    && CheckParentColumnsForForeignKey(cell, cells, parentEnd, ref errorListForInvalidParentColumnsForForeignKey) == false)
                {
                    // Not an error unless we find no valid case
                    continue;
                }
                else
                {
                    foundValidParentColumnsForForeignKey = true;
                }

                var childEnd = GetRelationEndForColumns(cell, primaryKeyFields);
                Debug.Assert(
                    childEnd == null || parentEnd != childEnd,
                    "Ends are same => PKey and child columns are same - code should gone to other method");
                // Note: If both of them are not-null, they are mapped to the
                // same association set -- since we checked that particular cell

                if (childEnd != null && parentEnd != null
                    &&
                    FindEntitySetForColumnsMappedToEntityKeys(cells, primaryKeyFields) != null)
                {
                    foundCell = true;
                    CheckConstraintWhenParentChildMapped(cell, errorLog, parentEnd, config);
                    break; // Done processing for the foreign key - either it was mapped correctly or it was not
                }
                else if (parentEnd != null)
                {
                    // At this point, we know cell corresponds to an association set
                    var assocSet = (AssociationSet)cell.CQuery.Extent;
                    var parentSet = MetadataHelper.GetEntitySetAtEnd(assocSet, parentEnd);
                    foundCell = CheckConstraintWhenOnlyParentMapped(assocSet, parentEnd, childRewriter, parentRewriter);
                    if (foundCell)
                    {
                        break;
                    }
                }
            }

            //CheckParentColumnsForForeignKey has returned no matches, Error.
            if (!foundValidParentColumnsForForeignKey)
            {
                Debug.Assert(
                    errorListForInvalidParentColumnsForForeignKey != null && errorListForInvalidParentColumnsForForeignKey.Count > 0);
                foreach (var errorRecord in errorListForInvalidParentColumnsForForeignKey)
                {
                    errorLog.AddEntry(errorRecord);
                }
                return;
            }

            if (foundCell == false)
            {
                // No cell found -- Declare error
                var message = Strings.ViewGen_Foreign_Key_Missing_Relationship_Mapping(ToUserString());

                IEnumerable<LeftCellWrapper> parentWrappers = GetWrappersFromContext(parentContext, ParentTable);
                IEnumerable<LeftCellWrapper> childWrappers = GetWrappersFromContext(childContext, ChildTable);
                var bothExtentWrappers =
                    new Set<LeftCellWrapper>(parentWrappers);
                bothExtentWrappers.AddRange(childWrappers);
                var record = new ErrorLog.Record(
                    ViewGenErrorCode.ForeignKeyMissingRelationshipMapping, message, bothExtentWrappers, String.Empty);
                errorLog.AddEntry(record);
            }
        }
        // effects: Checks that this foreign key constraints for all the
        // tables are being ensured on the C-side as well. If not, adds 
        // errors to the errorLog
        internal void CheckConstraint(
            Set<Cell> cells, QueryRewriter childRewriter, QueryRewriter parentRewriter,
            ErrorLog errorLog, ConfigViewGenerator config)
        {
            if (IsConstraintRelevantForCells(cells) == false)
            {
                // if the constraint does not deal with any cell in this group, ignore it
                return;
            }

            if (config.IsNormalTracing)
            {
                Trace.WriteLine(String.Empty);
                Trace.WriteLine(String.Empty);
                Trace.Write("Checking: ");
                Trace.WriteLine(this);
            }

            if (childRewriter == null
                && parentRewriter == null)
            {
                // Neither table is mapped - so we are fine
                return;
            }

            // If the child table has not been mapped, we used to say that we
            // are fine. However, if we have SPerson(pid) and SAddress(aid,
            // pid), where pid is an FK into SPerson, we are in trouble if
            // SAddress is not mapped - SPerson could get deleted. So we
            // check for it as well
            // if the parent table is not mapped, we also have a problem

            if (childRewriter == null)
            {
                var message = Strings.ViewGen_Foreign_Key_Missing_Table_Mapping(
                    ToUserString(), ChildTable.Name);
                // Get the cells from the parent table
                var record = new ErrorLog.Record(
                    ViewGenErrorCode.ForeignKeyMissingTableMapping, message, parentRewriter.UsedCells, String.Empty);
                errorLog.AddEntry(record);
                return;
            }

            if (parentRewriter == null)
            {
                var message = Strings.ViewGen_Foreign_Key_Missing_Table_Mapping(
                    ToUserString(), ParentTable.Name);
                // Get the cells from the child table
                var record = new ErrorLog.Record(
                    ViewGenErrorCode.ForeignKeyMissingTableMapping, message, childRewriter.UsedCells, String.Empty);
                errorLog.AddEntry(record);
                return;
            }

            // Note: we do not check if the parent columns correspond to the
            // table's keys - metadata checks for that

            //First check if the FK is covered by Foreign Key Association
            //If we find this, we don't need to check for independent associations. If user maps the Fk to both FK and independent associations,
            //the regular round tripping validation will catch the error.
            if (CheckIfConstraintMappedToForeignKeyAssociation(childRewriter, parentRewriter, cells))
            {
                return;
            }

            // Check if the foreign key in the child table corresponds to the primary key, i.e., if
            // the foreign key (e.g., pid, pid2) is a superset of the actual key members (e.g., pid), it means
            // that the foreign key is also the primary key for this table -- so we can propagate the queries upto C-Space
            // rather than doing the cell check

            var initialErrorLogSize = errorLog.Count;
            if (IsForeignKeySuperSetOfPrimaryKeyInChildTable())
            {
                GuaranteeForeignKeyConstraintInCSpace(childRewriter, parentRewriter, errorLog);
            }
            else
            {
                GuaranteeMappedRelationshipForForeignKey(childRewriter, parentRewriter, cells, errorLog, config);
            }

            if (initialErrorLogSize == errorLog.Count)
            {
                // Check if the order of columns in foreign key correponds to the
                // mappings in m_cellGroup, e.g., if <pid1, pid2> in SAddress is
                // a foreign key into <pid1, pid2> of the SPerson table, make
                // sure that this order is preserved through the mappings in m_cellGroup
                CheckForeignKeyColumnOrder(cells, errorLog);
            }
        }
Пример #23
0
 internal static Constant GetDefaultValueForMemberPath(MemberPath memberPath, IEnumerable<LeftCellWrapper> wrappersForErrorReporting,
                                                           ConfigViewGenerator config)
 {
     Constant defaultValue = null;
     if (!Domain.TryGetDefaultValueForMemberPath(memberPath, out defaultValue))
     {
         string message = Strings.ViewGen_No_Default_Value(memberPath.Extent.Name, memberPath.PathToString(false));
         ErrorLog.Record record = new ErrorLog.Record(true, ViewGenErrorCode.NoDefaultValue, message, wrappersForErrorReporting, String.Empty);
         ExceptionHelpers.ThrowMappingException(record, config);
     }
     return defaultValue;
 }
Пример #24
0
        // effects: Creates a map with all the condition member constants
        // from extentCells. viewtarget determines whether the view is an
        // update or query view
        internal MemberDomainMap(ViewTarget viewTarget, bool isValidationEnabled, IEnumerable<Cell> extentCells, EdmItemCollection edmItemCollection, ConfigViewGenerator config, Dictionary<EntityType, Set<EntityType>> inheritanceGraph)
        {
            m_conditionDomainMap = new Dictionary<MemberPath, CellConstantSet>(MemberPath.EqualityComparer);
            m_edmItemCollection = edmItemCollection;

            Dictionary<MemberPath, CellConstantSet> domainMap = null;
            if (viewTarget == ViewTarget.UpdateView)
            {
                domainMap = Domain.ComputeConstantDomainSetsForSlotsInUpdateViews(extentCells, m_edmItemCollection);
            }
            else
            {
                domainMap = Domain.ComputeConstantDomainSetsForSlotsInQueryViews(extentCells, m_edmItemCollection, isValidationEnabled);
            }

            foreach (Cell cell in extentCells)
            {
                CellQuery cellQuery = cell.GetLeftQuery(viewTarget);
                // Get the atoms from cellQuery and only keep the ones that
                // are condition members
                foreach (MemberRestriction condition in cellQuery.GetConjunctsFromWhereClause())
                {
                    // Note: TypeConditions are created using OneOfTypeConst and
                    // scalars are created using OneOfScalarConst
                    MemberPath memberPath = condition.RestrictedMemberSlot.MemberPath;

                    Debug.Assert(condition is ScalarRestriction || condition is TypeRestriction,
                                 "Unexpected restriction");

                    // Take the narrowed domain from domainMap, if any
                    CellConstantSet domainValues;
                    if (!domainMap.TryGetValue(memberPath, out domainValues))
                    {
                        domainValues = Domain.DeriveDomainFromMemberPath(memberPath, edmItemCollection, isValidationEnabled);
                    }

                    //Don't count conditions that are satisfied through IsNull=false 
                    if (!domainValues.Contains(Constant.Null))
                    {
                        //multiple values of condition represent disjunction in conditions (not currently supported)
                        // if there is any condition constant that is NotNull
                        if (condition.Domain.Values.All(conditionConstant => (conditionConstant.Equals(Constant.NotNull))))
                        {
                            continue;
                        }
                        //else there is atleast one condition value that is allowed, continue view generation
                    }

                    //------------------------------------------
                    //|  Nullable  |   IsNull  |   Test case   |
                    //|     T      |     T     |       T       |
                    //|     T      |     F     |       T       |
                    //|     F      |     T     |       F       |
                    //|     F      |     F     |       T       |
                    //------------------------------------------
                    //IsNull condition on a member that is non nullable is an invalid condition
                    if (domainValues.Count <= 0 || (!domainValues.Contains(Constant.Null) && condition.Domain.Values.Contains(Constant.Null)))
                    {
                        string message = System.Data.Entity.Strings.ViewGen_InvalidCondition(memberPath.PathToString(false));
                        ErrorLog.Record record = new ErrorLog.Record(true, ViewGenErrorCode.InvalidCondition, message, cell, String.Empty);
                        ExceptionHelpers.ThrowMappingException(record, config);
                    }
                    if (memberPath.IsAlwaysDefined(inheritanceGraph) == false)
                    {
                        domainValues.Add(Constant.Undefined);
                    }

                    AddToDomainMap(memberPath, domainValues);
                }
            }

            // Fill up the domains for the remaining slots as well
            m_nonConditionDomainMap = new Dictionary<MemberPath, CellConstantSet>(MemberPath.EqualityComparer);
            foreach (Cell cell in extentCells)
            {
                CellQuery cellQuery = cell.GetLeftQuery(viewTarget);
                // Get the atoms from cellQuery and only keep the ones that
                // are condition members
                foreach (MemberProjectedSlot slot in cellQuery.GetAllQuerySlots())
                {
                    MemberPath member = slot.MemberPath;
                    if (m_conditionDomainMap.ContainsKey(member) == false && m_nonConditionDomainMap.ContainsKey(member) == false)
                    {
                        CellConstantSet memberSet = Domain.DeriveDomainFromMemberPath(member, m_edmItemCollection, true /* Regardless of validation, leave the domain unbounded because this is not a condition member */);
                        if (member.IsAlwaysDefined(inheritanceGraph) == false)
                        { // nonConditionMember may belong to subclass
                            memberSet.Add(Constant.Undefined);
                        }
                        memberSet = Domain.ExpandNegationsInDomain(memberSet, memberSet);
                        m_nonConditionDomainMap.Add(member, new CellConstantSetInfo(memberSet, slot));
                    }
                }
            }
        }
Пример #25
0
 // effects: Fixes the domains of variables in this as specified in FixEnumerableDomains
 private static void ReduceEnumerableDomainToEnumeratedValues(ViewTarget target, Dictionary<MemberPath, CellConstantSet> domainMap, ConfigViewGenerator config,
                                               EdmItemCollection edmItemCollection)
 {
     foreach (MemberPath member in domainMap.Keys)
     {
         if (MetadataHelper.HasDiscreteDomain(member.EdmType) == false)
         {
             continue;
         }
         CellConstantSet domain = Domain.DeriveDomainFromMemberPath(member, edmItemCollection, true /* leaveDomainUnbounded */);
         CellConstantSet extra = domainMap[member].Difference(domain);
         extra.Remove(Constant.Undefined);
         if (extra.Count > 0)
         { // domainMap has extra members -- we should get rid of them
             if (config.IsNormalTracing)
             {
                 Helpers.FormatTraceLine("Changed domain of {0} from {1} - subtract {2}", member, domainMap[member], extra);
             }
             domainMap[member].Subtract(extra);
         }
     }
 }
Пример #26
0
        // effects: Shrinks the domain of members whose types can be enumerated - currently it applies 
        // only to boolean type as for enums we don't restrict enum values to specified members only. 
        // For example NOT(False, True, Null) for a boolean domain should be removed
        internal void ReduceEnumerableDomainToEnumeratedValues(ViewTarget target, ConfigViewGenerator config)
        {
            // Go through the two maps

            ReduceEnumerableDomainToEnumeratedValues(target, m_conditionDomainMap, config, m_edmItemCollection);
            ReduceEnumerableDomainToEnumeratedValues(target, m_nonConditionDomainMap, config, m_edmItemCollection);
        }
        internal MemberDomainMap(
            ViewTarget viewTarget, bool isValidationEnabled, IEnumerable <Cell> extentCells, EdmItemCollection edmItemCollection,
            ConfigViewGenerator config, Dictionary <EntityType, Set <EntityType> > inheritanceGraph)
        {
            m_conditionDomainMap = new Dictionary <MemberPath, CellConstantSet>(MemberPath.EqualityComparer);
            m_edmItemCollection  = edmItemCollection;

            Dictionary <MemberPath, CellConstantSet> domainMap = null;

            if (viewTarget == ViewTarget.UpdateView)
            {
                domainMap = Domain.ComputeConstantDomainSetsForSlotsInUpdateViews(extentCells, m_edmItemCollection);
            }
            else
            {
                domainMap = Domain.ComputeConstantDomainSetsForSlotsInQueryViews(extentCells, m_edmItemCollection, isValidationEnabled);
            }

            foreach (var cell in extentCells)
            {
                var cellQuery = cell.GetLeftQuery(viewTarget);
                // Get the atoms from cellQuery and only keep the ones that
                // are condition members
                foreach (var condition in cellQuery.GetConjunctsFromWhereClause())
                {
                    // Note: TypeConditions are created using OneOfTypeConst and
                    // scalars are created using OneOfScalarConst
                    var memberPath = condition.RestrictedMemberSlot.MemberPath;

                    Debug.Assert(
                        condition is ScalarRestriction || condition is TypeRestriction,
                        "Unexpected restriction");

                    // Take the narrowed domain from domainMap, if any
                    CellConstantSet domainValues;
                    if (!domainMap.TryGetValue(memberPath, out domainValues))
                    {
                        domainValues = Domain.DeriveDomainFromMemberPath(memberPath, edmItemCollection, isValidationEnabled);
                    }

                    //Don't count conditions that are satisfied through IsNull=false
                    if (!domainValues.Contains(Constant.Null))
                    {
                        //multiple values of condition represent disjunction in conditions (not currently supported)
                        // if there is any condition constant that is NotNull
                        if (condition.Domain.Values.All(conditionConstant => (conditionConstant.Equals(Constant.NotNull))))
                        {
                            continue;
                        }
                        //else there is atleast one condition value that is allowed, continue view generation
                    }

                    //------------------------------------------
                    //|  Nullable  |   IsNull  |   Test case   |
                    //|     T      |     T     |       T       |
                    //|     T      |     F     |       T       |
                    //|     F      |     T     |       F       |
                    //|     F      |     F     |       T       |
                    //------------------------------------------
                    //IsNull condition on a member that is non nullable is an invalid condition
                    if (domainValues.Count <= 0 ||
                        (!domainValues.Contains(Constant.Null) && condition.Domain.Values.Contains(Constant.Null)))
                    {
                        var message = Strings.ViewGen_InvalidCondition(memberPath.PathToString(false));
                        var record  = new ErrorLog.Record(ViewGenErrorCode.InvalidCondition, message, cell, String.Empty);
                        ExceptionHelpers.ThrowMappingException(record, config);
                    }
                    if (memberPath.IsAlwaysDefined(inheritanceGraph) == false)
                    {
                        domainValues.Add(Constant.Undefined);
                    }

                    AddToDomainMap(memberPath, domainValues);
                }
            }

            // Fill up the domains for the remaining slots as well
            m_nonConditionDomainMap = new Dictionary <MemberPath, CellConstantSet>(MemberPath.EqualityComparer);
            foreach (var cell in extentCells)
            {
                var cellQuery = cell.GetLeftQuery(viewTarget);
                // Get the atoms from cellQuery and only keep the ones that
                // are condition members
                foreach (var slot in cellQuery.GetAllQuerySlots())
                {
                    var member = slot.MemberPath;
                    if (m_conditionDomainMap.ContainsKey(member) == false &&
                        m_nonConditionDomainMap.ContainsKey(member) == false)
                    {
                        var memberSet = Domain.DeriveDomainFromMemberPath(
                            member, m_edmItemCollection, true
                            /* Regardless of validation, leave the domain unbounded because this is not a condition member */);
                        if (member.IsAlwaysDefined(inheritanceGraph) == false)
                        {
                            // nonConditionMember may belong to subclass
                            memberSet.Add(Constant.Undefined);
                        }
                        memberSet = Domain.ExpandNegationsInDomain(memberSet, memberSet);
                        m_nonConditionDomainMap.Add(member, new CellConstantSetInfo(memberSet));
                    }
                }
            }
        }
 internal void ReduceEnumerableDomainToEnumeratedValues(ConfigViewGenerator config)
 {
     MemberDomainMap.ReduceEnumerableDomainToEnumeratedValues(this.m_conditionDomainMap, config, this.m_edmItemCollection);
     MemberDomainMap.ReduceEnumerableDomainToEnumeratedValues(this.m_nonConditionDomainMap, config, this.m_edmItemCollection);
 }
        // requires: IsForeignKeySuperSetOfPrimaryKeyInChildTable() is false
        // and primaryKeys of ChildTable are not mapped in cell. cell
        // corresponds to an association set. parentSet is the set
        // corresponding to the end that we are looking at
        // effects: Checks if the constraint is correctly maintained in
        // C-space via an association set (being a subset of the
        // corresponding entitySet)
        private bool CheckConstraintWhenOnlyParentMapped(Cell cell, EntitySet parentSet, AssociationSet assocSet, AssociationEndMember endMember,
                                                         QueryRewriter childRewriter, QueryRewriter parentRewriter,
                                                         ConfigViewGenerator config)
        {

            ViewgenContext childContext = childRewriter.ViewgenContext;
            ViewgenContext parentContext = parentRewriter.ViewgenContext;

            CellTreeNode pNode = parentRewriter.BasicView;
            Debug.Assert(pNode != null);

            RoleBoolean endRoleBoolean = new RoleBoolean(assocSet.AssociationSetEnds[endMember.Name]);
            // use query in pNode as a factory to create a bool expression for the endRoleBoolean
            BoolExpression endCondition = pNode.RightFragmentQuery.Condition.Create(endRoleBoolean);
            FragmentQuery cNodeQuery = FragmentQuery.Create(pNode.RightFragmentQuery.Attributes, endCondition);

            FragmentQueryProcessor qp = FragmentQueryProcessor.Merge(childContext.RightFragmentQP, parentContext.RightFragmentQP);
            bool cImpliesP = qp.IsContainedIn(cNodeQuery, pNode.RightFragmentQuery);
            return cImpliesP;
        }
        private void GuaranteeMappedRelationshipForForeignKey(
            QueryRewriter childRewriter,
            QueryRewriter parentRewriter,
            IEnumerable <Cell> cells,
            ErrorLog errorLog,
            ConfigViewGenerator config)
        {
            ViewgenContext           viewgenContext1 = childRewriter.ViewgenContext;
            ViewgenContext           viewgenContext2 = parentRewriter.ViewgenContext;
            IEnumerable <MemberPath> keyFields       = ExtentKey.GetPrimaryKeyForEntityType(new MemberPath((EntitySetBase)this.ChildTable), this.ChildTable.ElementType).KeyFields;
            bool flag1 = false;
            bool flag2 = false;
            List <ErrorLog.Record> errorList = (List <ErrorLog.Record>)null;

            foreach (Cell cell in cells)
            {
                if (cell.SQuery.Extent.Equals((object)this.ChildTable))
                {
                    AssociationEndMember relationEndForColumns = ForeignConstraint.GetRelationEndForColumns(cell, this.ChildColumns);
                    if (relationEndForColumns == null || this.CheckParentColumnsForForeignKey(cell, cells, relationEndForColumns, ref errorList))
                    {
                        flag2 = true;
                        if (ForeignConstraint.GetRelationEndForColumns(cell, keyFields) != null && relationEndForColumns != null && ForeignConstraint.FindEntitySetForColumnsMappedToEntityKeys(cells, keyFields).Count > 0)
                        {
                            flag1 = true;
                            this.CheckConstraintWhenParentChildMapped(cell, errorLog, relationEndForColumns, config);
                            break;
                        }
                        if (relationEndForColumns != null)
                        {
                            AssociationSet extent = (AssociationSet)cell.CQuery.Extent;
                            MetadataHelper.GetEntitySetAtEnd(extent, relationEndForColumns);
                            flag1 = ForeignConstraint.CheckConstraintWhenOnlyParentMapped(extent, relationEndForColumns, childRewriter, parentRewriter);
                            if (flag1)
                            {
                                break;
                            }
                        }
                    }
                }
            }
            if (!flag2)
            {
                foreach (ErrorLog.Record record in errorList)
                {
                    errorLog.AddEntry(record);
                }
            }
            else
            {
                if (flag1)
                {
                    return;
                }
                string message = Strings.ViewGen_Foreign_Key_Missing_Relationship_Mapping((object)this.ToUserString());
                IEnumerable <LeftCellWrapper> wrappersFromContext1 = (IEnumerable <LeftCellWrapper>)ForeignConstraint.GetWrappersFromContext(viewgenContext2, (EntitySetBase)this.ParentTable);
                IEnumerable <LeftCellWrapper> wrappersFromContext2 = (IEnumerable <LeftCellWrapper>)ForeignConstraint.GetWrappersFromContext(viewgenContext1, (EntitySetBase)this.ChildTable);
                Set <LeftCellWrapper>         set = new Set <LeftCellWrapper>(wrappersFromContext1);
                set.AddRange(wrappersFromContext2);
                ErrorLog.Record record = new ErrorLog.Record(ViewGenErrorCode.ForeignKeyMissingRelationshipMapping, message, (IEnumerable <LeftCellWrapper>)set, string.Empty);
                errorLog.AddEntry(record);
            }
        }
Пример #31
0
 internal InputForComputingCellGroups(StorageEntityContainerMapping containerMapping, ConfigViewGenerator config)
 {
     ContainerMapping = containerMapping;
     Config           = config;
 }
Пример #32
0
        // effects: Ensures that there is a relationship mapped into the C-space for some cell in m_cellGroup. Else
        // adds an error to errorLog
        private void GuaranteeMappedRelationshipForForeignKey(
            QueryRewriter childRewriter, QueryRewriter parentRewriter,
            IEnumerable <Cell> cells,
            ErrorLog errorLog, ConfigViewGenerator config)
        {
            var childContext  = childRewriter.ViewgenContext;
            var parentContext = parentRewriter.ViewgenContext;

            // Find a cell where this foreign key is mapped as a relationship
            var prefix           = new MemberPath(ChildTable);
            var primaryKey       = ExtentKey.GetPrimaryKeyForEntityType(prefix, ChildTable.ElementType);
            var primaryKeyFields = primaryKey.KeyFields;
            var foundCell        = false;

            var foundValidParentColumnsForForeignKey = false; //we need to find only one, dont error on any one check being false
            List <ErrorLog.Record> errorListForInvalidParentColumnsForForeignKey = null;

            foreach (var cell in cells)
            {
                if (cell.SQuery.Extent.Equals(ChildTable) == false)
                {
                    continue;
                }

                // The childtable is mapped to a relationship in the C-space in cell
                // Check that all the columns of the foreign key and the primary key in the child table are mapped to some
                // property in the C-space

                var parentEnd = GetRelationEndForColumns(cell, ChildColumns);
                if (parentEnd != null &&
                    CheckParentColumnsForForeignKey(cell, cells, parentEnd, ref errorListForInvalidParentColumnsForForeignKey) == false)
                {
                    // Not an error unless we find no valid case
                    continue;
                }
                else
                {
                    foundValidParentColumnsForForeignKey = true;
                }

                var childEnd = GetRelationEndForColumns(cell, primaryKeyFields);
                Debug.Assert(
                    childEnd == null || parentEnd != childEnd,
                    "Ends are same => PKey and child columns are same - code should gone to other method");
                // Note: If both of them are not-null, they are mapped to the
                // same association set -- since we checked that particular cell

                if (childEnd != null &&
                    parentEnd != null
                    &&
                    FindEntitySetForColumnsMappedToEntityKeys(cells, primaryKeyFields) != null)
                {
                    foundCell = true;
                    CheckConstraintWhenParentChildMapped(cell, errorLog, parentEnd, config);
                    break; // Done processing for the foreign key - either it was mapped correctly or it was not
                }
                else if (parentEnd != null)
                {
                    // At this point, we know cell corresponds to an association set
                    var assocSet  = (AssociationSet)cell.CQuery.Extent;
                    var parentSet = MetadataHelper.GetEntitySetAtEnd(assocSet, parentEnd);
                    foundCell = CheckConstraintWhenOnlyParentMapped(assocSet, parentEnd, childRewriter, parentRewriter);
                    if (foundCell)
                    {
                        break;
                    }
                }
            }

            //CheckParentColumnsForForeignKey has returned no matches, Error.
            if (!foundValidParentColumnsForForeignKey)
            {
                Debug.Assert(
                    errorListForInvalidParentColumnsForForeignKey != null && errorListForInvalidParentColumnsForForeignKey.Count > 0);
                foreach (var errorRecord in errorListForInvalidParentColumnsForForeignKey)
                {
                    errorLog.AddEntry(errorRecord);
                }
                return;
            }

            if (foundCell == false)
            {
                // No cell found -- Declare error
                var message = Strings.ViewGen_Foreign_Key_Missing_Relationship_Mapping(ToUserString());

                IEnumerable <LeftCellWrapper> parentWrappers = GetWrappersFromContext(parentContext, ParentTable);
                IEnumerable <LeftCellWrapper> childWrappers  = GetWrappersFromContext(childContext, ChildTable);
                var bothExtentWrappers =
                    new Set <LeftCellWrapper>(parentWrappers);
                bothExtentWrappers.AddRange(childWrappers);
                var record = new ErrorLog.Record(
                    ViewGenErrorCode.ForeignKeyMissingRelationshipMapping, message, bothExtentWrappers, String.Empty);
                errorLog.AddEntry(record);
            }
        }
Пример #33
0
        // effects: Checks that this foreign key constraints for all the
        // tables are being ensured on the C-side as well. If not, adds
        // errors to the errorLog
        internal void CheckConstraint(
            Set <Cell> cells, QueryRewriter childRewriter, QueryRewriter parentRewriter,
            ErrorLog errorLog, ConfigViewGenerator config)
        {
            if (IsConstraintRelevantForCells(cells) == false)
            {
                // if the constraint does not deal with any cell in this group, ignore it
                return;
            }

            if (config.IsNormalTracing)
            {
                Trace.WriteLine(String.Empty);
                Trace.WriteLine(String.Empty);
                Trace.Write("Checking: ");
                Trace.WriteLine(this);
            }

            if (childRewriter == null &&
                parentRewriter == null)
            {
                // Neither table is mapped - so we are fine
                return;
            }

            // If the child table has not been mapped, we used to say that we
            // are fine. However, if we have SPerson(pid) and SAddress(aid,
            // pid), where pid is an FK into SPerson, we are in trouble if
            // SAddress is not mapped - SPerson could get deleted. So we
            // check for it as well
            // if the parent table is not mapped, we also have a problem

            if (childRewriter == null)
            {
                var message = Strings.ViewGen_Foreign_Key_Missing_Table_Mapping(
                    ToUserString(), ChildTable.Name);
                // Get the cells from the parent table
                var record = new ErrorLog.Record(
                    ViewGenErrorCode.ForeignKeyMissingTableMapping, message, parentRewriter.UsedCells, String.Empty);
                errorLog.AddEntry(record);
                return;
            }

            if (parentRewriter == null)
            {
                var message = Strings.ViewGen_Foreign_Key_Missing_Table_Mapping(
                    ToUserString(), ParentTable.Name);
                // Get the cells from the child table
                var record = new ErrorLog.Record(
                    ViewGenErrorCode.ForeignKeyMissingTableMapping, message, childRewriter.UsedCells, String.Empty);
                errorLog.AddEntry(record);
                return;
            }

            // Note: we do not check if the parent columns correspond to the
            // table's keys - metadata checks for that

            //First check if the FK is covered by Foreign Key Association
            //If we find this, we don't need to check for independent associations. If user maps the Fk to both FK and independent associations,
            //the regular round tripping validation will catch the error.
            if (CheckIfConstraintMappedToForeignKeyAssociation(childRewriter, parentRewriter, cells))
            {
                return;
            }

            // Check if the foreign key in the child table corresponds to the primary key, i.e., if
            // the foreign key (e.g., pid, pid2) is a superset of the actual key members (e.g., pid), it means
            // that the foreign key is also the primary key for this table -- so we can propagate the queries upto C-Space
            // rather than doing the cell check

            var initialErrorLogSize = errorLog.Count;

            if (IsForeignKeySuperSetOfPrimaryKeyInChildTable())
            {
                GuaranteeForeignKeyConstraintInCSpace(childRewriter, parentRewriter, errorLog);
            }
            else
            {
                GuaranteeMappedRelationshipForForeignKey(childRewriter, parentRewriter, cells, errorLog, config);
            }

            if (initialErrorLogSize == errorLog.Count)
            {
                // Check if the order of columns in foreign key correponds to the
                // mappings in m_cellGroup, e.g., if <pid1, pid2> in SAddress is
                // a foreign key into <pid1, pid2> of the SPerson table, make
                // sure that this order is preserved through the mappings in m_cellGroup
                CheckForeignKeyColumnOrder(cells, errorLog);
            }
        }