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
- RTLAwareMessageBox.cs
- WorkflowRuntimeServiceElementCollection.cs
- ObfuscateAssemblyAttribute.cs
- DirectoryInfo.cs
- PropertyValue.cs
- CompoundFileStreamReference.cs
- WebServiceErrorEvent.cs
- AddInAttribute.cs
- WebBrowser.cs
- EdmTypeAttribute.cs
- ObjectDataSourceSelectingEventArgs.cs
- CommentEmitter.cs
- XmlNodeChangedEventArgs.cs
- SystemKeyConverter.cs
- TemplateBindingExtension.cs
- HTMLTagNameToTypeMapper.cs
- ValueConversionAttribute.cs
- FacetValueContainer.cs
- InlineCollection.cs
- ColorMap.cs
- RangeContentEnumerator.cs
- ScriptReferenceEventArgs.cs
- BoolLiteral.cs
- ApplicationCommands.cs
- CharUnicodeInfo.cs
- GeometryConverter.cs
- SrgsNameValueTag.cs
- SecurityKeyType.cs
- StylusDevice.cs
- InputLanguage.cs
- SerializationEventsCache.cs
- ConfigurationSchemaErrors.cs
- WebPartChrome.cs
- AnnotationStore.cs
- TargetConverter.cs
- StatusBarPanelClickEvent.cs
- Delay.cs
- DateTimeFormat.cs
- MultiPageTextView.cs
- CodeDelegateInvokeExpression.cs
- _AutoWebProxyScriptWrapper.cs
- _OSSOCK.cs
- FormatSettings.cs
- LastQueryOperator.cs
- DataSourceCache.cs
- ThreadAttributes.cs
- PartManifestEntry.cs
- SelectionPatternIdentifiers.cs
- ExpanderAutomationPeer.cs
- BitStack.cs
- TreeNodeStyle.cs
- QueryableDataSource.cs
- PointConverter.cs
- DbProviderFactories.cs
- Range.cs
- ValidatorCompatibilityHelper.cs
- sqlnorm.cs
- CodeSnippetStatement.cs
- UmAlQuraCalendar.cs
- BamlRecords.cs
- DBCommandBuilder.cs
- SyndicationSerializer.cs
- FamilyCollection.cs
- NestedContainer.cs
- Trustee.cs
- BufferCache.cs
- ServiceHttpHandlerFactory.cs
- CodeMethodInvokeExpression.cs
- WebPartConnectionsConfigureVerb.cs
- ComponentEditorPage.cs
- AdjustableArrowCap.cs
- TrackPointCollection.cs
- OptimizedTemplateContentHelper.cs
- NetworkInformationException.cs
- DataSourceCache.cs
- Point3DAnimation.cs
- CompilerHelpers.cs
- ListItemCollection.cs
- ConfigXmlDocument.cs
- HtmlEmptyTagControlBuilder.cs
- OperationAbortedException.cs
- EnvelopedPkcs7.cs
- HtmlInputPassword.cs
- SystemNetworkInterface.cs
- TabControl.cs
- PaintValueEventArgs.cs
- precedingsibling.cs
- IndicFontClient.cs
- Int16KeyFrameCollection.cs
- DurationConverter.cs
- OSEnvironmentHelper.cs
- ToolStripSettings.cs
- CurrentTimeZone.cs
- MultipartContentParser.cs
- ProfilePropertySettings.cs
- PolyLineSegment.cs
- HierarchicalDataTemplate.cs
- ClientFormsIdentity.cs
- storepermissionattribute.cs
- DataServiceStreamProviderWrapper.cs