Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Map / ViewGeneration / ViewGenerator.cs / 1305376 / ViewGenerator.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.Data.Common.Utils; using System.Data.Common.Utils.Boolean; using System.Data.Mapping.ViewGeneration.Structures; using System.Data.Mapping.ViewGeneration.Validation; using System.Data.Mapping.ViewGeneration.QueryRewriting; using System.Collections.Generic; using System.Text; using System.Diagnostics; using System.Data.Mapping.ViewGeneration.Utils; using System.Data.Metadata.Edm; using System.Linq; namespace System.Data.Mapping.ViewGeneration { using ViewSet = KeyToListMap; using CellGroup = Set ; using WrapperBoolExpr = BoolExpr | ; using WrapperTrueExpr = TrueExpr ; using WrapperFalseExpr = FalseExpr ; using WrapperNotExpr = NotExpr ; using WrapperOrExpr = OrExpr ; // This class is responsible for generating query or update mapping // views from the initial cells. internal class ViewGenerator : InternalBase { #region Fields private CellGroup m_cellGroup; // The initial cells from which we produce views private ConfigViewGenerator m_config; // Configuration variables private MemberDomainMap m_queryDomainMap; private MemberDomainMap m_updateDomainMap; private Dictionary m_queryRewriterCache; private List m_foreignKeyConstraints; private StorageEntityContainerMapping m_entityContainerMapping; #endregion #region Internal API - Only Gatekeeper calls it // effects: Creates a ViewGenerator object that is capable of // producing query or update mapping views given the relevant schema // given the "cells" internal ViewGenerator(CellGroup cellGroup, ConfigViewGenerator config, List foreignKeyConstraints, StorageEntityContainerMapping entityContainerMapping) { m_cellGroup = cellGroup; m_config = config; m_queryRewriterCache = new Dictionary (); m_foreignKeyConstraints = foreignKeyConstraints; m_entityContainerMapping = entityContainerMapping; Dictionary > inheritanceGraph = MetadataHelper.BuildUndirectedGraphOfTypes(entityContainerMapping.StorageMappingItemCollection.EdmItemCollection); SetConfiguration(entityContainerMapping); // We fix all the cells at this point m_queryDomainMap = new MemberDomainMap(ViewTarget.QueryView, m_config.IsValidationEnabled, cellGroup, entityContainerMapping.StorageMappingItemCollection.EdmItemCollection, m_config, inheritanceGraph); m_updateDomainMap = new MemberDomainMap(ViewTarget.UpdateView, m_config.IsValidationEnabled, cellGroup, entityContainerMapping.StorageMappingItemCollection.EdmItemCollection, m_config, inheritanceGraph); // We now go and fix the queryDomain map so that it has all the // values from the S-side as well -- this is needed for domain // constraint propagation, i.e., values from the S-side get // propagated to te oneOfConst on the C-side. So we better get // the "possiblveValues" stuff to contain those constants as well MemberDomainMap.PropagateUpdateDomainToQueryDomain(cellGroup, m_queryDomainMap, m_updateDomainMap); UpdateWhereClauseForEachCell(cellGroup, m_queryDomainMap, m_updateDomainMap, m_config); // We need to simplify cell queries, yet we don't want the conditions to disappear // So, add an extra value to the domain, temporarily MemberDomainMap queryOpenDomain = m_queryDomainMap.GetOpenDomain(); MemberDomainMap updateOpenDomain = m_updateDomainMap.GetOpenDomain(); // Make sure the WHERE clauses of the cells reflect the changes foreach (Cell cell in cellGroup) { cell.CQuery.WhereClause.FixDomainMap(queryOpenDomain); cell.SQuery.WhereClause.FixDomainMap(updateOpenDomain); cell.CQuery.WhereClause.ExpensiveSimplify(); cell.SQuery.WhereClause.ExpensiveSimplify(); cell.CQuery.WhereClause.FixDomainMap(m_queryDomainMap); cell.SQuery.WhereClause.FixDomainMap(m_updateDomainMap); } } private void SetConfiguration(StorageEntityContainerMapping entityContainerMapping) { m_config.IsValidationEnabled = entityContainerMapping.Validate; m_config.GenerateUpdateViews = entityContainerMapping.GenerateUpdateViews; } // effects: Generates views for the particular cellgroup in this. Returns an // error log describing the errors that were encountered (if none // were encountered, the ErrorLog.Count is 0). Places the generated // views in result internal ErrorLog GenerateAllBidirectionalViews(ViewSet views, CqlIdentifiers identifiers) { // Allow missing attributes for now to make entity splitting run through // we cannot do this for query views in general: need to obtain the exact enumerated domain if (m_config.IsNormalTracing) { StringBuilder builder = new StringBuilder(); Cell.CellsToBuilder(builder, m_cellGroup); Helpers.StringTraceLine(builder.ToString()); } m_config.SetTimeForFinishedActivity(PerfType.CellCreation); // Check if the cellgroup is consistent and all known S constraints are // satisified by the known C constraints CellGroupValidator validator = new CellGroupValidator(m_cellGroup, m_config); ErrorLog errorLog = validator.Validate(); if (errorLog.Count > 0) { errorLog.PrintTrace(); return errorLog; } m_config.SetTimeForFinishedActivity(PerfType.KeyConstraint); // We generate update views first since they perform the main // validation checks if (m_config.GenerateUpdateViews) { errorLog = GenerateDirectionalViews(ViewTarget.UpdateView, identifiers, views); if (errorLog.Count > 0) { return errorLog; // If we have discovered errors here, do not generate query views } } // Make sure that the foreign key constraints are not violated if (m_config.IsValidationEnabled) { CheckForeignKeyConstraints(errorLog); } m_config.SetTimeForFinishedActivity(PerfType.ForeignConstraint); if (errorLog.Count > 0) { errorLog.PrintTrace(); return errorLog; // If we have discovered errors here, do not generate query views } // Query views - do not allow missing attributes // For the S-side, we add NOT ... for each scalar constant so // that if we have C, P in the mapping but the store has C, P, S, // we can handle it in the query views m_updateDomainMap.ExpandDomainsToIncludeAllPossibleValues(); errorLog = GenerateDirectionalViews(ViewTarget.QueryView, identifiers, views); return errorLog; } internal ErrorLog GenerateQueryViewForSingleExtent(ViewSet views, CqlIdentifiers identifiers, EntitySetBase entity, EntityTypeBase type, ViewGenerationMode mode) { Debug.Assert(mode != ViewGenerationMode.GenerateAllViews); if (m_config.IsNormalTracing) { StringBuilder builder = new StringBuilder(); Cell.CellsToBuilder(builder, m_cellGroup); Helpers.StringTraceLine(builder.ToString()); } // Check if the cellgroup is consistent and all known S constraints are // satisified by the known C constraints CellGroupValidator validator = new CellGroupValidator(m_cellGroup, m_config); ErrorLog errorLog = validator.Validate(); if (errorLog.Count > 0) { errorLog.PrintTrace(); return errorLog; } // Make sure that the foreign key constraints are not violated if (m_config.IsValidationEnabled) { CheckForeignKeyConstraints(errorLog); } if (errorLog.Count > 0) { errorLog.PrintTrace(); return errorLog; // If we have discovered errors here, do not generate query views } // For the S-side, we add NOT ... for each scalar constant so // that if we have C, P in the mapping but the store has C, P, S, // we can handle it in the query views m_updateDomainMap.ExpandDomainsToIncludeAllPossibleValues(); foreach (Cell cell in m_cellGroup) { cell.SQuery.WhereClause.FixDomainMap(m_updateDomainMap); } errorLog = GenerateQueryViewForExtentAndType(m_entityContainerMapping, identifiers, views, entity, type, mode); return errorLog; } #endregion #region Private Methods // effects: Given the extent cells and a map for the domains of all // variables in it, fixes the cell constant domains of the where // clauses in the left queries of cells (left is defined using viewTarget) private static void UpdateWhereClauseForEachCell(IEnumerable extentCells, MemberDomainMap queryDomainMap, MemberDomainMap updateDomainMap, ConfigViewGenerator config) { foreach (Cell cell in extentCells) { cell.CQuery.UpdateWhereClause(queryDomainMap); cell.SQuery.UpdateWhereClause(updateDomainMap); } // Fix domains of enumerated and boolean types -- i.e., whose domains are enumerable queryDomainMap.ReduceDomainOfEnumerableToEnumeratedValues(ViewTarget.QueryView, config); updateDomainMap.ReduceDomainOfEnumerableToEnumeratedValues(ViewTarget.UpdateView, config); } private ErrorLog GenerateQueryViewForExtentAndType(StorageEntityContainerMapping entityContainerMapping, CqlIdentifiers identifiers, ViewSet views, EntitySetBase entity, EntityTypeBase type, ViewGenerationMode mode) { Debug.Assert(mode != ViewGenerationMode.GenerateAllViews); // Keep track of the mapping exceptions that we have generated ErrorLog errorLog = new ErrorLog(); if (m_config.IsViewTracing) { Helpers.StringTraceLine(String.Empty); Helpers.StringTraceLine(String.Empty); Helpers.FormatTraceLine("================= Generating {0} Query View for: {1} ===========================", (mode == ViewGenerationMode.OfTypeViews) ? "OfType" : "OfTypeOnly", entity.Name); Helpers.StringTraceLine(String.Empty); Helpers.StringTraceLine(String.Empty); } try { // (1) view generation (checks that extents are fully mapped) ViewgenContext context = CreateViewgenContext(entity, ViewTarget.QueryView, identifiers); QueryRewriter queryRewriter = GenerateViewsForExtentAndType(type, context, identifiers, views, mode); } catch (InternalMappingException exception) { // All exceptions have mapping errors in them Debug.Assert(exception.ErrorLog.Count > 0, "Incorrectly created mapping exception"); errorLog.Merge(exception.ErrorLog); } return errorLog; } // requires: schema refers to C-side or S-side schema for the cells // inside this. if schema.IsQueryView is true, the left side of cells refers // to the C side (and vice-versa for the right side) // effects: Generates the relevant views for the schema side and // returns them. If allowMissingAttributes is true and attributes // are missing on the schema side, substitutes them with NULL // Modifies views to contain the generated views for different // extents specified by cells and the the schemaContext private ErrorLog GenerateDirectionalViews(ViewTarget viewTarget, CqlIdentifiers identifiers, ViewSet views) { bool isQueryView = viewTarget == ViewTarget.QueryView; // Create an object that partition cells by extent KeyToListMap | extentCellMap = GroupCellsByExtent(m_cellGroup, viewTarget); // Keep track of the mapping exceptions that we have generated ErrorLog errorLog = new ErrorLog(); // Generate views for each extent foreach (EntitySetBase extent in extentCellMap.Keys) { if (m_config.IsViewTracing) { Helpers.StringTraceLine(String.Empty); Helpers.StringTraceLine(String.Empty); Helpers.FormatTraceLine("================= Generating {0} View for: {1} ===========================", isQueryView ? "Query" : "Update", extent.Name); Helpers.StringTraceLine(String.Empty); Helpers.StringTraceLine(String.Empty); } try { // (1) view generation (checks that extents are fully mapped) QueryRewriter queryRewriter = GenerateDirectionalViewsForExtent(viewTarget, extent, identifiers, views); // (2) validation for update views if (viewTarget == ViewTarget.UpdateView && m_config.IsValidationEnabled) { if (m_config.IsViewTracing) { Helpers.StringTraceLine(String.Empty); Helpers.StringTraceLine(String.Empty); Helpers.FormatTraceLine("----------------- Validation for generated update view for: {0} -----------------", extent.Name); Helpers.StringTraceLine(String.Empty); Helpers.StringTraceLine(String.Empty); } RewritingValidator validator = new RewritingValidator(queryRewriter.ViewgenContext, queryRewriter.BasicView); validator.Validate(); } } catch (InternalMappingException exception) { // All exceptions have mapping errors in them Debug.Assert(exception.ErrorLog.Count > 0, "Incorrectly created mapping exception"); errorLog.Merge(exception.ErrorLog); } } return errorLog; } // effects: Generates a view for an extent "extent" that belongs to // schema "schema". extentCells are the cells for this extent. // Adds the view corrsponding to the extent to "views" private QueryRewriter GenerateDirectionalViewsForExtent(ViewTarget viewTarget, EntitySetBase extent, CqlIdentifiers identifiers, ViewSet views) { // First normalize the cells in terms of multiconstants, etc // and then generate the view for the extent ViewgenContext context = CreateViewgenContext(extent, viewTarget, identifiers); QueryRewriter queryRewriter = null; if (m_config.GenerateViewsForEachType) { // generate views for each OFTYPE(Extent, Type) combination foreach (EdmType type in MetadataHelper.GetTypeAndSubtypesOf(extent.ElementType, m_entityContainerMapping.StorageMappingItemCollection.EdmItemCollection, false /*includeAbstractTypes*/)) { if (m_config.IsViewTracing && false == type.Equals(extent.ElementType)) { Helpers.FormatTraceLine("CQL View for {0} and type {1}", extent.Name, type.Name); } queryRewriter = GenerateViewsForExtentAndType(type, context, identifiers, views, ViewGenerationMode.OfTypeViews); } } else { // generate the view for Extent only queryRewriter = GenerateViewsForExtentAndType(extent.ElementType, context, identifiers, views, ViewGenerationMode.OfTypeViews); } if (viewTarget == ViewTarget.QueryView) { m_config.SetTimeForFinishedActivity(PerfType.QueryViews); } else { m_config.SetTimeForFinishedActivity(PerfType.UpdateViews); } // cache this rewriter (and context inside it) for future use in FK checking m_queryRewriterCache[extent] = queryRewriter; return queryRewriter; } // effects: Returns a context corresponding to extent (if one does not exist, creates one) private ViewgenContext CreateViewgenContext(EntitySetBase extent, ViewTarget viewTarget, CqlIdentifiers identifiers) { QueryRewriter queryRewriter; if (!m_queryRewriterCache.TryGetValue(extent, out queryRewriter)) { // collect the cells that belong to this extent (just a few of them since we segment the mapping first) var cellsForExtent = m_cellGroup.Where(c => c.GetLeftQuery(viewTarget).Extent == extent); return new ViewgenContext(viewTarget, extent, cellsForExtent, identifiers, m_config, m_queryDomainMap, m_updateDomainMap, m_entityContainerMapping); } else { return queryRewriter.ViewgenContext; } } private QueryRewriter GenerateViewsForExtentAndType(EdmType generatedType, ViewgenContext context, CqlIdentifiers identifiers, ViewSet views, ViewGenerationMode mode) { Debug.Assert(mode != ViewGenerationMode.GenerateAllViews, "By definition this method can not handle generating views for all extents"); QueryRewriter queryRewriter = new QueryRewriter(generatedType, context, mode); queryRewriter.GenerateViewComponents(); // Get the basic view CellTreeNode basicView = queryRewriter.BasicView; if (m_config.IsNormalTracing) { Helpers.StringTrace("Basic View: "); Helpers.StringTraceLine(basicView.ToString()); } CellTreeNode simplifiedView = GenerateSimplifiedView(basicView, queryRewriter.UsedCells); if (m_config.IsNormalTracing) { Helpers.StringTraceLine(String.Empty); Helpers.StringTrace("Simplified View: "); Helpers.StringTraceLine(simplifiedView.ToString()); } CqlGenerator cqlGen = new CqlGenerator(simplifiedView, queryRewriter.CaseStatements, identifiers, context.MemberMaps.ProjectedSlotMap, queryRewriter.UsedCells.Count, queryRewriter.TopLevelWhereClause); string viewString = cqlGen.GenerateCql(); GeneratedView generatedView = new GeneratedView(context.Extent, generatedType, viewString, m_entityContainerMapping.StorageMappingItemCollection, m_config); views.Add(context.Extent, generatedView); return queryRewriter; } private CellTreeNode GenerateSimplifiedView(CellTreeNode basicView, List usedCells) { Debug.Assert(false == basicView.IsEmptyRightFragmentQuery, "Basic view is empty?"); // create 'joined' variables, one for each cell // We know (say) that out of the 10 cells that we were given, only 7 (say) were // needed to construct the view for this extent. int numBoolVars = usedCells.Count; // We need the boolean expressions in Simplify. Precisely ont boolean expression is set to // true in each cell query for (int i = 0; i < numBoolVars; i++) { // In the ith cell, set its boolean to be true (i.e., ith boolean) usedCells[i].RightCellQuery.InitializeBoolExpressions(numBoolVars, i); } CellTreeNode simplifiedView = CellTreeSimplifier.MergeNodes(basicView); return simplifiedView; } private void CheckForeignKeyConstraints(ErrorLog errorLog) { foreach (ForeignConstraint constraint in m_foreignKeyConstraints) { QueryRewriter childRewriter = null; QueryRewriter parentRewriter = null; m_queryRewriterCache.TryGetValue(constraint.ChildTable, out childRewriter); m_queryRewriterCache.TryGetValue(constraint.ParentTable, out parentRewriter); constraint.CheckConstraint(m_cellGroup, childRewriter, parentRewriter, errorLog, m_config); } } // 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 GroupCellsByExtent(IEnumerable cells, ViewTarget viewTarget) { // Partition cells by extent -- extent is the top node in // the tree. Even for compositions for now? CHANGE_[....]_FEATURE_COMPOSITION KeyToListMap | extentCellMap = new KeyToListMap (EqualityComparer .Default); foreach (Cell cell in cells) { // Get the cell query and determine its extent CellQuery cellQuery = cell.GetLeftQuery(viewTarget); extentCellMap.Add(cellQuery.Extent, cell); } return extentCellMap; } #endregion #region String Methods internal override void ToCompactString(StringBuilder builder) { Cell.CellsToBuilder(builder, m_cellGroup); } #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- GiveFeedbackEventArgs.cs
- LowerCaseStringConverter.cs
- MatrixTransform3D.cs
- MDIControlStrip.cs
- EntityDataReader.cs
- CommittableTransaction.cs
- SetterBaseCollection.cs
- ArraySortHelper.cs
- BuildManager.cs
- SafeSecurityHandles.cs
- SmtpReplyReaderFactory.cs
- ReadOnlyTernaryTree.cs
- IndexedString.cs
- CatalogPart.cs
- InputLanguageEventArgs.cs
- BitmapData.cs
- TraceContextRecord.cs
- MachinePropertyVariants.cs
- SourceElementsCollection.cs
- EmptyStringExpandableObjectConverter.cs
- MonikerBuilder.cs
- VersionedStreamOwner.cs
- MemberRelationshipService.cs
- NavigationProgressEventArgs.cs
- RequestValidator.cs
- Privilege.cs
- DocobjHost.cs
- AlphabetConverter.cs
- Point3DIndependentAnimationStorage.cs
- DescriptionCreator.cs
- IntSecurity.cs
- DynamicDocumentPaginator.cs
- IImplicitResourceProvider.cs
- ProfileManager.cs
- Brushes.cs
- FileIOPermission.cs
- VisualStyleElement.cs
- CellParaClient.cs
- WebPart.cs
- AppSettingsReader.cs
- ListMarkerSourceInfo.cs
- PolyBezierSegment.cs
- StandardRuntimeEnumValidator.cs
- ISessionStateStore.cs
- FileDataSourceCache.cs
- Expander.cs
- Brush.cs
- WorkflowInstanceSuspendedRecord.cs
- NotifyInputEventArgs.cs
- PolyBezierSegment.cs
- ToolStripSettings.cs
- EmptyQuery.cs
- X509SubjectKeyIdentifierClause.cs
- ServiceTimeoutsBehavior.cs
- AnimationClockResource.cs
- CultureInfoConverter.cs
- DisplayNameAttribute.cs
- XsltQilFactory.cs
- COMException.cs
- SelectionProviderWrapper.cs
- BuildProvider.cs
- ApplicationFileParser.cs
- MatrixAnimationUsingKeyFrames.cs
- TreeNodeStyleCollection.cs
- GridView.cs
- AsyncPostBackTrigger.cs
- DelayedRegex.cs
- ErrorsHelper.cs
- SystemIcons.cs
- SingleAnimationBase.cs
- AppDomainManager.cs
- FilePrompt.cs
- StorageEntityTypeMapping.cs
- ListViewItemMouseHoverEvent.cs
- OverflowException.cs
- EnumerableCollectionView.cs
- WebPartDeleteVerb.cs
- DefaultConfirmation.cs
- MenuItemBinding.cs
- UnknownWrapper.cs
- Misc.cs
- UIElement.cs
- Vars.cs
- SerialStream.cs
- BitmapDownload.cs
- ToolZone.cs
- AutoResetEvent.cs
- SystemIPGlobalStatistics.cs
- PkcsMisc.cs
- CollectionView.cs
- Touch.cs
- HttpCapabilitiesEvaluator.cs
- ItemCheckedEvent.cs
- TextEditorLists.cs
- ResetableIterator.cs
- ByteStreamGeometryContext.cs
- PropertyConverter.cs
- SurrogateEncoder.cs
- FixedTextPointer.cs
- HtmlEncodedRawTextWriter.cs