// <summary> // Creates generated view object for the combination of the <paramref name="extent" /> and the <paramref name="type" />. // This constructor is used for regular cell-based view generation. // </summary> internal static GeneratedView CreateGeneratedView( EntitySetBase extent, EdmType type, DbQueryCommandTree commandTree, string eSQL, StorageMappingItemCollection mappingItemCollection, ConfigViewGenerator config) { // If config.GenerateEsql is specified, eSQL must be non-null. // If config.GenerateEsql is false, commandTree is non-null except the case when loading pre-compiled eSQL views. Debug.Assert(!config.GenerateEsql || !String.IsNullOrEmpty(eSQL), "eSQL must be specified"); DiscriminatorMap discriminatorMap = null; if (commandTree != null) { commandTree = ViewSimplifier.SimplifyView(extent, commandTree); // See if the view matches the "discriminated" pattern (allows simplification of generated store commands) if (extent.BuiltInTypeKind == BuiltInTypeKind.EntitySet) { if (DiscriminatorMap.TryCreateDiscriminatorMap((EntitySet)extent, commandTree.Query, out discriminatorMap)) { Debug.Assert(discriminatorMap != null, "discriminatorMap == null after it has been created"); } } } return(new GeneratedView(extent, type, commandTree, eSQL, discriminatorMap, mappingItemCollection, config)); }
private GeneratedView( EntitySetBase extent, EdmType type, DbQueryCommandTree commandTree, string eSQL, DiscriminatorMap discriminatorMap, StorageMappingItemCollection mappingItemCollection, ConfigViewGenerator config) { // At least one of the commandTree or eSQL must be specified. // Both are specified in the case of user-defined views. Debug.Assert(commandTree != null || !String.IsNullOrEmpty(eSQL), "commandTree or eSQL must be specified"); m_extent = extent; m_type = type; m_commandTree = commandTree; m_eSQL = eSQL; m_discriminatorMap = discriminatorMap; m_mappingItemCollection = mappingItemCollection; m_config = config; if (m_config.IsViewTracing) { var trace = new StringBuilder(1024); ToCompactString(trace); Helpers.FormatTraceLine("CQL view for {0}", trace.ToString()); } }
/// <summary> /// Creates generated view object for the combination of the <paramref name="extent" /> and the <paramref name="type" />. /// This constructor is used for regular cell-based view generation. /// </summary> internal static GeneratedView CreateGeneratedView( EntitySetBase extent, EdmType type, DbQueryCommandTree commandTree, string eSQL, StorageMappingItemCollection mappingItemCollection, ConfigViewGenerator config) { // If config.GenerateEsql is specified, eSQL must be non-null. // If config.GenerateEsql is false, commandTree is non-null except the case when loading pre-compiled eSQL views. Debug.Assert(!config.GenerateEsql || !String.IsNullOrEmpty(eSQL), "eSQL must be specified"); DiscriminatorMap discriminatorMap = null; if (commandTree != null) { commandTree = ViewSimplifier.SimplifyView(extent, commandTree); // See if the view matches the "discriminated" pattern (allows simplification of generated store commands) if (extent.BuiltInTypeKind == BuiltInTypeKind.EntitySet) { if (DiscriminatorMap.TryCreateDiscriminatorMap((EntitySet)extent, commandTree.Query, out discriminatorMap)) { Debug.Assert(discriminatorMap != null, "discriminatorMap == null after it has been created"); } } } return new GeneratedView(extent, type, commandTree, eSQL, discriminatorMap, mappingItemCollection, config); }
internal ViewGenerator( Set <Cell> cellGroup, ConfigViewGenerator config, List <ForeignConstraint> foreignKeyConstraints, EntityContainerMapping entityContainerMapping) { this.m_cellGroup = cellGroup; this.m_config = config; this.m_queryRewriterCache = new Dictionary <EntitySetBase, QueryRewriter>(); this.m_foreignKeyConstraints = foreignKeyConstraints; this.m_entityContainerMapping = entityContainerMapping; Dictionary <EntityType, Set <EntityType> > inheritanceGraph = MetadataHelper.BuildUndirectedGraphOfTypes(entityContainerMapping.StorageMappingItemCollection.EdmItemCollection); this.SetConfiguration(entityContainerMapping); this.m_queryDomainMap = new MemberDomainMap(ViewTarget.QueryView, this.m_config.IsValidationEnabled, (IEnumerable <Cell>)cellGroup, entityContainerMapping.StorageMappingItemCollection.EdmItemCollection, this.m_config, inheritanceGraph); this.m_updateDomainMap = new MemberDomainMap(ViewTarget.UpdateView, this.m_config.IsValidationEnabled, (IEnumerable <Cell>)cellGroup, entityContainerMapping.StorageMappingItemCollection.EdmItemCollection, this.m_config, inheritanceGraph); MemberDomainMap.PropagateUpdateDomainToQueryDomain((IEnumerable <Cell>)cellGroup, this.m_queryDomainMap, this.m_updateDomainMap); ViewGenerator.UpdateWhereClauseForEachCell((IEnumerable <Cell>)cellGroup, this.m_queryDomainMap, this.m_updateDomainMap, this.m_config); MemberDomainMap openDomain1 = this.m_queryDomainMap.GetOpenDomain(); MemberDomainMap openDomain2 = this.m_updateDomainMap.GetOpenDomain(); foreach (Cell cell in cellGroup) { cell.CQuery.WhereClause.FixDomainMap(openDomain1); cell.SQuery.WhereClause.FixDomainMap(openDomain2); cell.CQuery.WhereClause.ExpensiveSimplify(); cell.SQuery.WhereClause.ExpensiveSimplify(); cell.CQuery.WhereClause.FixDomainMap(this.m_queryDomainMap); cell.SQuery.WhereClause.FixDomainMap(this.m_updateDomainMap); } }
private GeneratedView( EntitySetBase extent, EdmType type, DbQueryCommandTree commandTree, string eSQL, DiscriminatorMap discriminatorMap, StorageMappingItemCollection mappingItemCollection, ConfigViewGenerator config) { this.m_extent = extent; this.m_type = type; this.m_commandTree = commandTree; this.m_eSQL = eSQL; this.m_discriminatorMap = discriminatorMap; this.m_mappingItemCollection = mappingItemCollection; this.m_config = config; if (!this.m_config.IsViewTracing) { return; } StringBuilder builder = new StringBuilder(1024); this.ToCompactString(builder); Helpers.FormatTraceLine("CQL view for {0}", (object)builder.ToString()); }
/// <summary> /// Creates generated view object for the combination of the <paramref name="extent" /> and the <paramref name="type" />. /// This constructor is used for FK association sets only. /// </summary> internal static GeneratedView CreateGeneratedViewForFKAssociationSet( EntitySetBase extent, EdmType type, DbQueryCommandTree commandTree, StorageMappingItemCollection mappingItemCollection, ConfigViewGenerator config) { return new GeneratedView(extent, type, commandTree, null, null, mappingItemCollection, config); }
// <summary> // Creates generated view object for the combination of the <paramref name="extent" /> and the <paramref name="type" />. // This constructor is used for FK association sets only. // </summary> internal static GeneratedView CreateGeneratedViewForFKAssociationSet( EntitySetBase extent, EdmType type, DbQueryCommandTree commandTree, StorageMappingItemCollection mappingItemCollection, ConfigViewGenerator config) { return(new GeneratedView(extent, type, commandTree, null, null, mappingItemCollection, config)); }
internal static ViewGenResults GenerateViewsFromMapping( EntityContainerMapping containerMapping, ConfigViewGenerator config) { CellCreator cellCreator = new CellCreator(containerMapping); List <Cell> cells = cellCreator.GenerateCells(); CqlIdentifiers identifiers = cellCreator.Identifiers; return(ViewgenGatekeeper.GenerateViewsFromCells(cells, config, identifiers, containerMapping)); }
internal ViewgenContext( ViewTarget viewTarget, EntitySetBase extent, IList <Cell> extentCells, CqlIdentifiers identifiers, ConfigViewGenerator config, MemberDomainMap queryDomainMap, MemberDomainMap updateDomainMap, EntityContainerMapping entityContainerMapping) { foreach (Cell extentCell in (IEnumerable <Cell>)extentCells) { ; } this.m_extent = extent; this.m_viewTarget = viewTarget; this.m_config = config; this.m_edmItemCollection = entityContainerMapping.StorageMappingItemCollection.EdmItemCollection; this.m_entityContainerMapping = entityContainerMapping; this.m_identifiers = identifiers; updateDomainMap = updateDomainMap.MakeCopy(); MemberDomainMap domainMap = viewTarget == ViewTarget.QueryView ? queryDomainMap : updateDomainMap; this.m_memberMaps = new MemberMaps(viewTarget, MemberProjectionIndex.Create(extent, this.m_edmItemCollection), queryDomainMap, updateDomainMap); FragmentQueryKBChaseSupport kb1 = new FragmentQueryKBChaseSupport(); kb1.CreateVariableConstraints(extent, domainMap, this.m_edmItemCollection); this.m_leftFragmentQP = new FragmentQueryProcessor(kb1); this.m_rewritingCache = new Dictionary <FragmentQuery, Tile <FragmentQuery> >(FragmentQuery.GetEqualityComparer(this.m_leftFragmentQP)); if (!this.CreateLeftCellWrappers(extentCells, viewTarget)) { return; } FragmentQueryKBChaseSupport kb2 = new FragmentQueryKBChaseSupport(); MemberDomainMap memberDomainMap = viewTarget == ViewTarget.QueryView ? updateDomainMap : queryDomainMap; foreach (LeftCellWrapper cellWrapper in this.m_cellWrappers) { EntitySetBase rightExtent = cellWrapper.RightExtent; kb2.CreateVariableConstraints(rightExtent, memberDomainMap, this.m_edmItemCollection); kb2.CreateAssociationConstraints(rightExtent, memberDomainMap, this.m_edmItemCollection); } if (this.m_viewTarget == ViewTarget.UpdateView) { this.CreateConstraintsForForeignKeyAssociationsAffectingThisWrapper((FragmentQueryKB)kb2, memberDomainMap); } this.m_rightFragmentQP = new FragmentQueryProcessor(kb2); if (this.m_viewTarget == ViewTarget.QueryView) { this.CheckConcurrencyControlTokens(); } this.m_cellWrappers.Sort(LeftCellWrapper.Comparer); }
// effects: Creates a view generator object that can be used to generate views // based on usedCells (projectedSlotMap are useful for deciphering the fields) internal BasicViewGenerator( MemberProjectionIndex projectedSlotMap, List<LeftCellWrapper> usedCells, FragmentQuery activeDomain, ViewgenContext context, MemberDomainMap domainMap, ErrorLog errorLog, ConfigViewGenerator config) { Debug.Assert(usedCells.Count > 0, "No used cells"); m_projectedSlotMap = projectedSlotMap; m_usedCells = usedCells; m_viewgenContext = context; m_activeDomain = activeDomain; m_errorLog = errorLog; m_config = config; m_domainMap = domainMap; }
// effects: Creates a view generator object that can be used to generate views // based on usedCells (projectedSlotMap are useful for deciphering the fields) internal BasicViewGenerator( MemberProjectionIndex projectedSlotMap, List <LeftCellWrapper> usedCells, FragmentQuery activeDomain, ViewgenContext context, MemberDomainMap domainMap, ErrorLog errorLog, ConfigViewGenerator config) { Debug.Assert(usedCells.Count > 0, "No used cells"); m_projectedSlotMap = projectedSlotMap; m_usedCells = usedCells; m_viewgenContext = context; m_activeDomain = activeDomain; m_errorLog = errorLog; m_config = config; m_domainMap = domainMap; }
/// <summary> /// Entry point for View Generation /// </summary> /// <param name="containerMapping"> </param> /// <param name="workSpace"> </param> /// <param name="config"> </param> /// <returns> Generated Views for EntitySets </returns> internal static ViewGenResults GenerateViewsFromMapping(StorageEntityContainerMapping containerMapping, ConfigViewGenerator config) { DebugCheck.NotNull(containerMapping); DebugCheck.NotNull(config); Debug.Assert(containerMapping.HasViews, "Precondition Violated: No mapping exists to generate views for!"); //Create Cells from StorageEntityContainerMapping var cellCreator = new CellCreator(containerMapping); var cells = cellCreator.GenerateCells(); var identifiers = cellCreator.Identifiers; return GenerateViewsFromCells(cells, config, identifiers, containerMapping); }
private static void UpdateWhereClauseForEachCell( IEnumerable <Cell> extentCells, MemberDomainMap queryDomainMap, MemberDomainMap updateDomainMap, ConfigViewGenerator config) { foreach (Cell extentCell in extentCells) { extentCell.CQuery.UpdateWhereClause(queryDomainMap); extentCell.SQuery.UpdateWhereClause(updateDomainMap); } queryDomainMap.ReduceEnumerableDomainToEnumeratedValues(config); updateDomainMap.ReduceEnumerableDomainToEnumeratedValues(config); }
// 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 <ForeignConstraint> foreignKeyConstraints, EntityContainerMapping entityContainerMapping) { m_cellGroup = cellGroup; m_config = config; m_queryRewriterCache = new Dictionary <EntitySetBase, QueryRewriter>(); m_foreignKeyConstraints = foreignKeyConstraints; m_entityContainerMapping = entityContainerMapping; var 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 "possibleValues" 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 var queryOpenDomain = m_queryDomainMap.GetOpenDomain(); var updateOpenDomain = m_updateDomainMap.GetOpenDomain(); // Make sure the WHERE clauses of the cells reflect the changes foreach (var 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); } }
// 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 <Cell> extentCells, MemberDomainMap queryDomainMap, MemberDomainMap updateDomainMap, ConfigViewGenerator config) { foreach (var cell in extentCells) { cell.CQuery.UpdateWhereClause(queryDomainMap); cell.SQuery.UpdateWhereClause(updateDomainMap); } // Fix enumerable domains - currently it is only applicable to boolean type. Note that it is // not applicable to enumerated types since we allow any value of the underlying type of the enum type. queryDomainMap.ReduceEnumerableDomainToEnumeratedValues(config); updateDomainMap.ReduceEnumerableDomainToEnumeratedValues(config); }
// 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<ForeignConstraint> foreignKeyConstraints, StorageEntityContainerMapping entityContainerMapping) { m_cellGroup = cellGroup; m_config = config; m_queryRewriterCache = new Dictionary<EntitySetBase, QueryRewriter>(); m_foreignKeyConstraints = foreignKeyConstraints; m_entityContainerMapping = entityContainerMapping; var 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 var queryOpenDomain = m_queryDomainMap.GetOpenDomain(); var updateOpenDomain = m_updateDomainMap.GetOpenDomain(); // Make sure the WHERE clauses of the cells reflect the changes foreach (var 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); } }
internal BasicViewGenerator( MemberProjectionIndex projectedSlotMap, List <LeftCellWrapper> usedCells, FragmentQuery activeDomain, ViewgenContext context, MemberDomainMap domainMap, ErrorLog errorLog, ConfigViewGenerator config) { this.m_projectedSlotMap = projectedSlotMap; this.m_usedCells = usedCells; this.m_viewgenContext = context; this.m_activeDomain = activeDomain; this.m_errorLog = errorLog; this.m_config = config; this.m_domainMap = domainMap; }
private static bool TryParseView( string eSQL, bool isUserSpecified, EntitySetBase extent, StorageMappingItemCollection mappingItemCollection, ConfigViewGenerator config, out DbQueryCommandTree commandTree, out DiscriminatorMap discriminatorMap, out Exception parserException) { commandTree = (DbQueryCommandTree)null; discriminatorMap = (DiscriminatorMap)null; parserException = (Exception)null; config.StartSingleWatch(PerfType.ViewParsing); try { ParserOptions.CompilationMode compilationMode = ParserOptions.CompilationMode.RestrictedViewGenerationMode; if (isUserSpecified) { compilationMode = ParserOptions.CompilationMode.UserViewGenerationMode; } commandTree = (DbQueryCommandTree)ExternalCalls.CompileView(eSQL, mappingItemCollection, compilationMode); commandTree = ViewSimplifier.SimplifyView(extent, commandTree); if (extent.BuiltInTypeKind == BuiltInTypeKind.EntitySet) { DiscriminatorMap.TryCreateDiscriminatorMap((EntitySet)extent, commandTree.Query, out discriminatorMap); } } catch (Exception ex) { if (ex.IsCatchableExceptionType()) { parserException = ex; } else { throw; } } finally { config.StopSingleWatch(PerfType.ViewParsing); } return(parserException == null); }
internal static bool TryParseUserSpecifiedView( EntitySetBaseMapping setMapping, EntityTypeBase type, string eSQL, bool includeSubtypes, StorageMappingItemCollection mappingItemCollection, ConfigViewGenerator config, IList <EdmSchemaError> errors, out GeneratedView generatedView) { bool flag = false; DbQueryCommandTree commandTree; DiscriminatorMap discriminatorMap; Exception parserException; if (!GeneratedView.TryParseView(eSQL, true, setMapping.Set, mappingItemCollection, config, out commandTree, out discriminatorMap, out parserException)) { EdmSchemaError edmSchemaError = new EdmSchemaError(Strings.Mapping_Invalid_QueryView2((object)setMapping.Set.Name, (object)parserException.Message), 2068, EdmSchemaErrorSeverity.Error, setMapping.EntityContainerMapping.SourceLocation, setMapping.StartLineNumber, setMapping.StartLinePosition, parserException); errors.Add(edmSchemaError); flag = true; } else { foreach (EdmSchemaError edmSchemaError in ViewValidator.ValidateQueryView(commandTree, setMapping, type, includeSubtypes)) { errors.Add(edmSchemaError); flag = true; } CollectionType edmType = commandTree.Query.ResultType.EdmType as CollectionType; if (edmType == null || !setMapping.Set.ElementType.IsAssignableFrom(edmType.TypeUsage.EdmType)) { EdmSchemaError edmSchemaError = new EdmSchemaError(Strings.Mapping_Invalid_QueryView_Type((object)setMapping.Set.Name), 2069, EdmSchemaErrorSeverity.Error, setMapping.EntityContainerMapping.SourceLocation, setMapping.StartLineNumber, setMapping.StartLinePosition); errors.Add(edmSchemaError); flag = true; } } if (!flag) { generatedView = new GeneratedView(setMapping.Set, (EdmType)type, commandTree, eSQL, discriminatorMap, mappingItemCollection, config); return(true); } generatedView = (GeneratedView)null; return(false); }
/// <summary> /// Entry point for View Generation /// </summary> /// <param name="containerMapping"></param> /// <param name="workSpace"></param> /// <param name="config"></param> /// <returns>Generated Views for EntitySets</returns> internal static ViewGenResults GenerateViewsFromMapping(StorageEntityContainerMapping containerMapping, ConfigViewGenerator config) { Contract.Requires(containerMapping != null); Contract.Requires(config != null); Debug.Assert(containerMapping.HasViews, "Precondition Violated: No mapping exists to generate views for!"); #if DEBUG if (config.IsNormalTracing) { containerMapping.Print(0); } #endif //Create Cells from StorageEntityContainerMapping var cellCreator = new CellCreator(containerMapping); var cells = cellCreator.GenerateCells(); var identifiers = cellCreator.Identifiers; return GenerateViewsFromCells(cells, config, identifiers, containerMapping); }
internal static GeneratedView CreateGeneratedView( EntitySetBase extent, EdmType type, DbQueryCommandTree commandTree, string eSQL, StorageMappingItemCollection mappingItemCollection, ConfigViewGenerator config) { DiscriminatorMap discriminatorMap = (DiscriminatorMap)null; if (commandTree != null) { commandTree = ViewSimplifier.SimplifyView(extent, commandTree); if (extent.BuiltInTypeKind == BuiltInTypeKind.EntitySet) { DiscriminatorMap.TryCreateDiscriminatorMap((EntitySet)extent, commandTree.Query, out discriminatorMap); } } return(new GeneratedView(extent, type, commandTree, eSQL, discriminatorMap, mappingItemCollection, config)); }
private static ViewGenResults GenerateViewsFromCells( List <Cell> cells, ConfigViewGenerator config, CqlIdentifiers identifiers, EntityContainerMapping containerMapping) { EntityContainer storageEntityContainer = containerMapping.StorageEntityContainer; ViewGenResults viewGenResults = new ViewGenResults(); ErrorLog errorLog1 = ViewgenGatekeeper.EnsureAllCSpaceContainerSetsAreMapped((IEnumerable <Cell>)cells, containerMapping); if (errorLog1.Count > 0) { viewGenResults.AddErrors(errorLog1); Helpers.StringTraceLine(viewGenResults.ErrorsToString()); return(viewGenResults); } List <ForeignConstraint> foreignConstraints = ForeignConstraint.GetForeignConstraints(storageEntityContainer); foreach (Set <Cell> groupRelatedCell in new CellPartitioner((IEnumerable <Cell>)cells, (IEnumerable <ForeignConstraint>)foreignConstraints).GroupRelatedCells()) { ViewGenerator viewGenerator = (ViewGenerator)null; ErrorLog errorLog2 = new ErrorLog(); try { viewGenerator = new ViewGenerator(groupRelatedCell, config, foreignConstraints, containerMapping); } catch (InternalMappingException ex) { errorLog2 = ex.ErrorLog; } if (errorLog2.Count == 0) { errorLog2 = viewGenerator.GenerateAllBidirectionalViews(viewGenResults.Views, identifiers); } if (errorLog2.Count != 0) { viewGenResults.AddErrors(errorLog2); } } return(viewGenResults); }
private GeneratedView( EntitySetBase extent, EdmType type, DbQueryCommandTree commandTree, string eSQL, DiscriminatorMap discriminatorMap, StorageMappingItemCollection mappingItemCollection, ConfigViewGenerator config) { // At least one of the commandTree or eSQL must be specified. // Both are specified in the case of user-defined views. Debug.Assert(commandTree != null || !String.IsNullOrEmpty(eSQL), "commandTree or eSQL must be specified"); m_extent = extent; m_type = type; m_commandTree = commandTree; m_eSQL = eSQL; m_discriminatorMap = discriminatorMap; m_mappingItemCollection = mappingItemCollection; m_config = config; if (m_config.IsViewTracing) { var trace = new StringBuilder(1024); ToCompactString(trace); Helpers.FormatTraceLine("CQL view for {0}", trace.ToString()); } }
/// <summary> /// Given an extent and its corresponding view, invokes the parser to check if the view definition is syntactically correct. /// Iff parsing succeeds: <paramref name="commandTree" /> and <paramref name="discriminatorMap" /> are set to the parse result and method returns true, /// otherwise if parser has thrown a catchable exception, it is returned via <paramref name="parserException" /> parameter, /// otherwise exception is re-thrown. /// </summary> private static bool TryParseView( string eSQL, bool isUserSpecified, EntitySetBase extent, StorageMappingItemCollection mappingItemCollection, ConfigViewGenerator config, out DbQueryCommandTree commandTree, out DiscriminatorMap discriminatorMap, out Exception parserException) { commandTree = null; discriminatorMap = null; parserException = null; // We do not catch any internal exceptions any more config.StartSingleWatch(PerfType.ViewParsing); try { // If it is a user specified view, allow all queries. Otherwise parse the view in the restricted mode. var compilationMode = ParserOptions.CompilationMode.RestrictedViewGenerationMode; if (isUserSpecified) { compilationMode = ParserOptions.CompilationMode.UserViewGenerationMode; } Debug.Assert(!String.IsNullOrEmpty(eSQL), "eSQL query is not specified"); commandTree = (DbQueryCommandTree)ExternalCalls.CompileView(eSQL, mappingItemCollection, compilationMode); // For non user-specified views, perform simplification. if (!isUserSpecified) { commandTree = ViewSimplifier.SimplifyView(extent, commandTree); } // See if the view matches the "discriminated" pattern (allows simplification of generated store commands) if (extent.BuiltInTypeKind == BuiltInTypeKind.EntitySet) { if (DiscriminatorMap.TryCreateDiscriminatorMap((EntitySet)extent, commandTree.Query, out discriminatorMap)) { Debug.Assert(discriminatorMap != null, "discriminatorMap == null after it has been created"); } } } catch (Exception e) { // Catching all the exception types since Query parser seems to be throwing veriety of // exceptions - EntityException, ArgumentException, ArgumentNullException etc. if (e.IsCatchableExceptionType()) { parserException = e; } else { throw; } } finally { config.StopSingleWatch(PerfType.ViewParsing); } Debug.Assert(commandTree != null || parserException != null, "Either commandTree or parserException is expected."); // Note: m_commandTree might have been initialized by a previous call to this method, so in consequent calls it might occur that // both m_commandTree and parserException are not null - this would mean that the last parse attempt failed, but m_commandTree value is // preserved from the previous call. return parserException == null; }
// <summary> // Given an extent and its corresponding view, invokes the parser to check if the view definition is syntactically correct. // Iff parsing succeeds: <paramref name="commandTree" /> and <paramref name="discriminatorMap" /> are set to the parse result and method returns true, // otherwise if parser has thrown a catchable exception, it is returned via <paramref name="parserException" /> parameter, // otherwise exception is re-thrown. // </summary> private static bool TryParseView( string eSQL, bool isUserSpecified, EntitySetBase extent, StorageMappingItemCollection mappingItemCollection, ConfigViewGenerator config, out DbQueryCommandTree commandTree, out DiscriminatorMap discriminatorMap, out Exception parserException) { commandTree = null; discriminatorMap = null; parserException = null; // We do not catch any internal exceptions any more config.StartSingleWatch(PerfType.ViewParsing); try { // If it is a user specified view, allow all queries. Otherwise parse the view in the restricted mode. var compilationMode = ParserOptions.CompilationMode.RestrictedViewGenerationMode; if (isUserSpecified) { compilationMode = ParserOptions.CompilationMode.UserViewGenerationMode; } Debug.Assert(!String.IsNullOrEmpty(eSQL), "eSQL query is not specified"); commandTree = (DbQueryCommandTree)ExternalCalls.CompileView(eSQL, mappingItemCollection, compilationMode); commandTree = ViewSimplifier.SimplifyView(extent, commandTree); // See if the view matches the "discriminated" pattern (allows simplification of generated store commands) if (extent.BuiltInTypeKind == BuiltInTypeKind.EntitySet) { if (DiscriminatorMap.TryCreateDiscriminatorMap((EntitySet)extent, commandTree.Query, out discriminatorMap)) { Debug.Assert(discriminatorMap != null, "discriminatorMap == null after it has been created"); } } } catch (Exception e) { // Catching all the exception types since Query parser seems to be throwing a variety of // exceptions - EntityException, ArgumentException, ArgumentNullException etc. if (e.IsCatchableExceptionType()) { parserException = e; } else { throw; } } finally { config.StopSingleWatch(PerfType.ViewParsing); } Debug.Assert(commandTree != null || parserException != null, "Either commandTree or parserException is expected."); // Note: m_commandTree might have been initialized by a previous call to this method, so in consequent calls it might occur that // both m_commandTree and parserException are not null - this would mean that the last parse attempt failed, but m_commandTree value is // preserved from the previous call. return(parserException == null); }
/// <summary> /// Creates generated view object for the combination of the <paramref name="setMapping" />.Set and the /// <paramref /// name="type" /> /// . /// This constructor is used for user-defined query views only. /// </summary> internal static bool TryParseUserSpecifiedView( StorageSetMapping setMapping, EntityTypeBase type, string eSQL, bool includeSubtypes, StorageMappingItemCollection mappingItemCollection, ConfigViewGenerator config, /*out*/ IList<EdmSchemaError> errors, out GeneratedView generatedView) { var failed = false; DbQueryCommandTree commandTree; DiscriminatorMap discriminatorMap; Exception parserException; if ( !TryParseView( eSQL, true, setMapping.Set, mappingItemCollection, config, out commandTree, out discriminatorMap, out parserException)) { var error = new EdmSchemaError( Strings.Mapping_Invalid_QueryView2(setMapping.Set.Name, parserException.Message), (int)StorageMappingErrorCode.InvalidQueryView, EdmSchemaErrorSeverity.Error, setMapping.EntityContainerMapping.SourceLocation, setMapping.StartLineNumber, setMapping.StartLinePosition, parserException); errors.Add(error); failed = true; } else { Debug.Assert(commandTree != null, "commandTree not set after parsing the view"); // Verify that all expressions appearing in the view are supported. foreach (var error in ViewValidator.ValidateQueryView(commandTree, setMapping, type, includeSubtypes)) { errors.Add(error); failed = true; } // Verify that the result type of the query view is assignable to the element type of the entityset var queryResultType = (commandTree.Query.ResultType.EdmType) as CollectionType; if ((queryResultType == null) || (!setMapping.Set.ElementType.IsAssignableFrom(queryResultType.TypeUsage.EdmType))) { var error = new EdmSchemaError( Strings.Mapping_Invalid_QueryView_Type(setMapping.Set.Name), (int)StorageMappingErrorCode.InvalidQueryViewResultType, EdmSchemaErrorSeverity.Error, setMapping.EntityContainerMapping.SourceLocation, setMapping.StartLineNumber, setMapping.StartLinePosition); errors.Add(error); failed = true; } } if (!failed) { generatedView = new GeneratedView(setMapping.Set, type, commandTree, eSQL, discriminatorMap, mappingItemCollection, config); return true; } else { generatedView = null; return false; } }
/// <summary> /// Entry point for Type specific generation of Query Views /// </summary> internal static ViewGenResults GenerateTypeSpecificQueryView( StorageEntityContainerMapping containerMapping, ConfigViewGenerator config, EntitySetBase entity, EntityTypeBase type, bool includeSubtypes, out bool success) { DebugCheck.NotNull(containerMapping); DebugCheck.NotNull(config); DebugCheck.NotNull(entity); DebugCheck.NotNull(type); Debug.Assert(!type.Abstract, "Can not generate OfType/OfTypeOnly query view for and abstract type"); if (config.IsNormalTracing) { Helpers.StringTraceLine(""); Helpers.StringTraceLine( "<<<<<<<< Generating Query View for Entity [" + entity.Name + "] OfType" + (includeSubtypes ? "" : "Only") + "(" + type.Name + ") >>>>>>>"); } if (containerMapping.GetEntitySetMapping(entity.Name).QueryView != null) { //Type-specific QV does not exist in the cache, but // there is a EntitySet QV. So we can't generate the view (no mapping exists for this EntitySet) // and we rely on Query to call us again to get the EntitySet View. success = false; return(null); } //Compute Cell Groups or get it from Memoizer var args = new InputForComputingCellGroups(containerMapping, config); var result = containerMapping.GetCellgroups(args); success = result.Success; if (!success) { return(null); } var foreignKeyConstraints = result.ForeignKeyConstraints; // Get a Clone of cell groups from cache since cells are modified during viewgen, and we dont want the cached copy to change var cellGroups = result.CellGroups.Select(setOfcells => new CellGroup(setOfcells.Select(cell => new Cell(cell)))).ToList(); var cells = result.Cells; var identifiers = result.Identifiers; var viewGenResults = new ViewGenResults(); var tmpLog = EnsureAllCSpaceContainerSetsAreMapped(cells, containerMapping); if (tmpLog.Count > 0) { viewGenResults.AddErrors(tmpLog); Helpers.StringTraceLine(viewGenResults.ErrorsToString()); success = true; //atleast we tried successfully return(viewGenResults); } foreach (var cellGroup in cellGroups) { if (!DoesCellGroupContainEntitySet(cellGroup, entity)) { continue; } ViewGenerator viewGenerator = null; var groupErrorLog = new ErrorLog(); try { viewGenerator = new ViewGenerator(cellGroup, config, foreignKeyConstraints, containerMapping); } catch (InternalMappingException exception) { // All exceptions have mapping errors in them Debug.Assert(exception.ErrorLog.Count > 0, "Incorrectly created mapping exception"); groupErrorLog = exception.ErrorLog; } if (groupErrorLog.Count > 0) { break; } Debug.Assert(viewGenerator != null); //make sure there is no exception thrown that does not add error to log var mode = includeSubtypes ? ViewGenMode.OfTypeViews : ViewGenMode.OfTypeOnlyViews; groupErrorLog = viewGenerator.GenerateQueryViewForSingleExtent(viewGenResults.Views, identifiers, entity, type, mode); if (groupErrorLog.Count != 0) { viewGenResults.AddErrors(groupErrorLog); } } success = true; return(viewGenResults); }
internal ViewgenContext( ViewTarget viewTarget, EntitySetBase extent, IList <Cell> extentCells, CqlIdentifiers identifiers, ConfigViewGenerator config, MemberDomainMap queryDomainMap, MemberDomainMap updateDomainMap, StorageEntityContainerMapping entityContainerMapping) { foreach (var cell in extentCells) { Debug.Assert(extent.Equals(cell.GetLeftQuery(viewTarget).Extent)); Debug.Assert(cell.CQuery.NumProjectedSlots == cell.SQuery.NumProjectedSlots); } m_extent = extent; m_viewTarget = viewTarget; m_config = config; m_edmItemCollection = entityContainerMapping.StorageMappingItemCollection.EdmItemCollection; m_entityContainerMapping = entityContainerMapping; m_identifiers = identifiers; // create a copy of updateDomainMap so generation of query views later on is not affected // it is modified in QueryRewriter.AdjustMemberDomainsForUpdateViews updateDomainMap = updateDomainMap.MakeCopy(); // Create a signature generator that handles all the // multiconstant work and generating the signatures var domainMap = viewTarget == ViewTarget.QueryView ? queryDomainMap : updateDomainMap; m_memberMaps = new MemberMaps( viewTarget, MemberProjectionIndex.Create(extent, m_edmItemCollection), queryDomainMap, updateDomainMap); // Create left fragment KB: includes constraints for the extent to be constructed var leftKB = new FragmentQueryKBChaseSupport(); leftKB.CreateVariableConstraints(extent, domainMap, m_edmItemCollection); m_leftFragmentQP = new FragmentQueryProcessor(leftKB); m_rewritingCache = new Dictionary <FragmentQuery, Tile <FragmentQuery> >( FragmentQuery.GetEqualityComparer(m_leftFragmentQP)); // Now using the signatures, create new cells such that // "extent's" query (C or S) is described in terms of multiconstants if (!CreateLeftCellWrappers(extentCells, viewTarget)) { return; } // Create right fragment KB: includes constraints for all extents and association roles of right queries var rightKB = new FragmentQueryKBChaseSupport(); var rightDomainMap = viewTarget == ViewTarget.QueryView ? updateDomainMap : queryDomainMap; foreach (var leftCellWrapper in m_cellWrappers) { var rightExtent = leftCellWrapper.RightExtent; rightKB.CreateVariableConstraints(rightExtent, rightDomainMap, m_edmItemCollection); rightKB.CreateAssociationConstraints(rightExtent, rightDomainMap, m_edmItemCollection); } if (m_viewTarget == ViewTarget.UpdateView) { CreateConstraintsForForeignKeyAssociationsAffectingThisWrapper(rightKB, rightDomainMap); } m_rightFragmentQP = new FragmentQueryProcessor(rightKB); // Check for concurrency control tokens if (m_viewTarget == ViewTarget.QueryView) { CheckConcurrencyControlTokens(); } // For backward compatibility - // order wrappers by increasing domain size, decreasing number of attributes m_cellWrappers.Sort(LeftCellWrapper.Comparer); }
internal static ViewGenResults GenerateTypeSpecificQueryView( EntityContainerMapping containerMapping, ConfigViewGenerator config, EntitySetBase entity, EntityTypeBase type, bool includeSubtypes, out bool success) { if (config.IsNormalTracing) { Helpers.StringTraceLine(""); Helpers.StringTraceLine("<<<<<<<< Generating Query View for Entity [" + entity.Name + "] OfType" + (includeSubtypes ? "" : "Only") + "(" + type.Name + ") >>>>>>>"); } if (containerMapping.GetEntitySetMapping(entity.Name).QueryView != null) { success = false; return((ViewGenResults)null); } InputForComputingCellGroups args = new InputForComputingCellGroups(containerMapping, config); OutputFromComputeCellGroups cellgroups = containerMapping.GetCellgroups(args); success = cellgroups.Success; if (!success) { return((ViewGenResults)null); } List <ForeignConstraint> foreignKeyConstraints = cellgroups.ForeignKeyConstraints; List <Set <Cell> > list = cellgroups.CellGroups.Select <Set <Cell>, Set <Cell> >((Func <Set <Cell>, Set <Cell> >)(setOfcells => new Set <Cell>(setOfcells.Select <Cell, Cell>((Func <Cell, Cell>)(cell => new Cell(cell)))))).ToList <Set <Cell> >(); List <Cell> cells = cellgroups.Cells; CqlIdentifiers identifiers = cellgroups.Identifiers; ViewGenResults viewGenResults = new ViewGenResults(); ErrorLog errorLog1 = ViewgenGatekeeper.EnsureAllCSpaceContainerSetsAreMapped((IEnumerable <Cell>)cells, containerMapping); if (errorLog1.Count > 0) { viewGenResults.AddErrors(errorLog1); Helpers.StringTraceLine(viewGenResults.ErrorsToString()); success = true; return(viewGenResults); } foreach (Set <Cell> set in list) { if (ViewgenGatekeeper.DoesCellGroupContainEntitySet(set, entity)) { ViewGenerator viewGenerator = (ViewGenerator)null; ErrorLog errorLog2 = new ErrorLog(); try { viewGenerator = new ViewGenerator(set, config, foreignKeyConstraints, containerMapping); } catch (InternalMappingException ex) { errorLog2 = ex.ErrorLog; } if (errorLog2.Count <= 0) { ViewGenMode mode = includeSubtypes ? ViewGenMode.OfTypeViews : ViewGenMode.OfTypeOnlyViews; ErrorLog viewForSingleExtent = viewGenerator.GenerateQueryViewForSingleExtent(viewGenResults.Views, identifiers, entity, type, mode); if (viewForSingleExtent.Count != 0) { viewGenResults.AddErrors(viewForSingleExtent); } } else { break; } } } success = true; return(viewGenResults); }
// requires: cells are not normalized, i.e., no slot is null in the cell queries // effects: Constructs a validator object that is capable of // validating all the schema cells together internal CellGroupValidator(IEnumerable<Cell> cells, ConfigViewGenerator config) { m_cells = cells; m_config = config; m_errorLog = new ErrorLog(); }
internal ViewgenContext( ViewTarget viewTarget, EntitySetBase extent, IList<Cell> extentCells, CqlIdentifiers identifiers, ConfigViewGenerator config, MemberDomainMap queryDomainMap, MemberDomainMap updateDomainMap, EntityContainerMapping entityContainerMapping) { foreach (var cell in extentCells) { Debug.Assert(extent.Equals(cell.GetLeftQuery(viewTarget).Extent)); Debug.Assert(cell.CQuery.NumProjectedSlots == cell.SQuery.NumProjectedSlots); } m_extent = extent; m_viewTarget = viewTarget; m_config = config; m_edmItemCollection = entityContainerMapping.StorageMappingItemCollection.EdmItemCollection; m_entityContainerMapping = entityContainerMapping; m_identifiers = identifiers; // create a copy of updateDomainMap so generation of query views later on is not affected // it is modified in QueryRewriter.AdjustMemberDomainsForUpdateViews updateDomainMap = updateDomainMap.MakeCopy(); // Create a signature generator that handles all the // multiconstant work and generating the signatures var domainMap = viewTarget == ViewTarget.QueryView ? queryDomainMap : updateDomainMap; m_memberMaps = new MemberMaps( viewTarget, MemberProjectionIndex.Create(extent, m_edmItemCollection), queryDomainMap, updateDomainMap); // Create left fragment KB: includes constraints for the extent to be constructed var leftKB = new FragmentQueryKBChaseSupport(); leftKB.CreateVariableConstraints(extent, domainMap, m_edmItemCollection); m_leftFragmentQP = new FragmentQueryProcessor(leftKB); m_rewritingCache = new Dictionary<FragmentQuery, Tile<FragmentQuery>>( FragmentQuery.GetEqualityComparer(m_leftFragmentQP)); // Now using the signatures, create new cells such that // "extent's" query (C or S) is described in terms of multiconstants if (!CreateLeftCellWrappers(extentCells, viewTarget)) { return; } // Create right fragment KB: includes constraints for all extents and association roles of right queries var rightKB = new FragmentQueryKBChaseSupport(); var rightDomainMap = viewTarget == ViewTarget.QueryView ? updateDomainMap : queryDomainMap; foreach (var leftCellWrapper in m_cellWrappers) { var rightExtent = leftCellWrapper.RightExtent; rightKB.CreateVariableConstraints(rightExtent, rightDomainMap, m_edmItemCollection); rightKB.CreateAssociationConstraints(rightExtent, rightDomainMap, m_edmItemCollection); } if (m_viewTarget == ViewTarget.UpdateView) { CreateConstraintsForForeignKeyAssociationsAffectingThisWrapper(rightKB, rightDomainMap); } m_rightFragmentQP = new FragmentQueryProcessor(rightKB); // Check for concurrency control tokens if (m_viewTarget == ViewTarget.QueryView) { CheckConcurrencyControlTokens(); } // For backward compatibility - // order wrappers by increasing domain size, decreasing number of attributes m_cellWrappers.Sort(LeftCellWrapper.Comparer); }
// effects: Given a list of cells in the schema, generates the query and // update mapping views for OFTYPE(Extent, Type) combinations in this schema // container. Returns a list of generated query and update views. // If it is false and some columns in a table are unmapped, an // exception is raised private static ViewGenResults GenerateViewsFromCells( List <Cell> cells, ConfigViewGenerator config, CqlIdentifiers identifiers, StorageEntityContainerMapping containerMapping) { DebugCheck.NotNull(cells); DebugCheck.NotNull(config); Debug.Assert(cells.Count > 0, "There must be at least one cell in the container mapping"); // Go through each table and determine their foreign key constraints var container = containerMapping.StorageEntityContainer; Debug.Assert(container != null); var viewGenResults = new ViewGenResults(); var tmpLog = EnsureAllCSpaceContainerSetsAreMapped(cells, containerMapping); if (tmpLog.Count > 0) { viewGenResults.AddErrors(tmpLog); Helpers.StringTraceLine(viewGenResults.ErrorsToString()); return(viewGenResults); } var foreignKeyConstraints = ForeignConstraint.GetForeignConstraints(container); var partitioner = new CellPartitioner(cells, foreignKeyConstraints); var cellGroups = partitioner.GroupRelatedCells(); foreach (var cellGroup in cellGroups) { ViewGenerator viewGenerator = null; var groupErrorLog = new ErrorLog(); try { viewGenerator = new ViewGenerator(cellGroup, config, foreignKeyConstraints, containerMapping); } catch (InternalMappingException exception) { // All exceptions have mapping errors in them Debug.Assert(exception.ErrorLog.Count > 0, "Incorrectly created mapping exception"); groupErrorLog = exception.ErrorLog; } if (groupErrorLog.Count == 0) { Debug.Assert(viewGenerator != null); groupErrorLog = viewGenerator.GenerateAllBidirectionalViews(viewGenResults.Views, identifiers); } if (groupErrorLog.Count != 0) { viewGenResults.AddErrors(groupErrorLog); } } // We used to print the errors here. Now we trace them as they are being thrown //if (viewGenResults.HasErrors && config.IsViewTracing) { // Helpers.StringTraceLine(viewGenResults.ErrorsToString()); //} return(viewGenResults); }
// <summary> // Creates generated view object for the combination of the <paramref name="setMapping" />.Set and the // <paramref // name="type" /> // . // This constructor is used for user-defined query views only. // </summary> internal static bool TryParseUserSpecifiedView( EntitySetBaseMapping setMapping, EntityTypeBase type, string eSQL, bool includeSubtypes, StorageMappingItemCollection mappingItemCollection, ConfigViewGenerator config, /*out*/ IList <EdmSchemaError> errors, out GeneratedView generatedView) { var failed = false; DbQueryCommandTree commandTree; DiscriminatorMap discriminatorMap; Exception parserException; if ( !TryParseView( eSQL, true, setMapping.Set, mappingItemCollection, config, out commandTree, out discriminatorMap, out parserException)) { var error = new EdmSchemaError( Strings.Mapping_Invalid_QueryView2(setMapping.Set.Name, parserException.Message), (int)MappingErrorCode.InvalidQueryView, EdmSchemaErrorSeverity.Error, setMapping.EntityContainerMapping.SourceLocation, setMapping.StartLineNumber, setMapping.StartLinePosition, parserException); errors.Add(error); failed = true; } else { Debug.Assert(commandTree != null, "commandTree not set after parsing the view"); // Verify that all expressions appearing in the view are supported. foreach (var error in ViewValidator.ValidateQueryView(commandTree, setMapping, type, includeSubtypes)) { errors.Add(error); failed = true; } // Verify that the result type of the query view is assignable to the element type of the entityset var queryResultType = (commandTree.Query.ResultType.EdmType) as CollectionType; if ((queryResultType == null) || (!setMapping.Set.ElementType.IsAssignableFrom(queryResultType.TypeUsage.EdmType))) { var error = new EdmSchemaError( Strings.Mapping_Invalid_QueryView_Type(setMapping.Set.Name), (int)MappingErrorCode.InvalidQueryViewResultType, EdmSchemaErrorSeverity.Error, setMapping.EntityContainerMapping.SourceLocation, setMapping.StartLineNumber, setMapping.StartLinePosition); errors.Add(error); failed = true; } } if (!failed) { generatedView = new GeneratedView(setMapping.Set, type, commandTree, eSQL, discriminatorMap, mappingItemCollection, config); return(true); } else { generatedView = null; return(false); } }
// 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<Cell> extentCells, MemberDomainMap queryDomainMap, MemberDomainMap updateDomainMap, ConfigViewGenerator config) { foreach (var cell in extentCells) { cell.CQuery.UpdateWhereClause(queryDomainMap); cell.SQuery.UpdateWhereClause(updateDomainMap); } // Fix enumerable domains - currently it is only applicable to boolean type. Note that it is // not applicable to enumerated types since we allow any value of the underlying type of the enum type. queryDomainMap.ReduceEnumerableDomainToEnumeratedValues(config); updateDomainMap.ReduceEnumerableDomainToEnumeratedValues(config); }
// effects: Given a list of cells in the schema, generates the query and // update mapping views for OFTYPE(Extent, Type) combinations in this schema // container. Returns a list of generated query and update views. // If it is false and some columns in a table are unmapped, an // exception is raised private static ViewGenResults GenerateViewsFromCells( List<Cell> cells, ConfigViewGenerator config, CqlIdentifiers identifiers, EntityContainerMapping containerMapping) { DebugCheck.NotNull(cells); DebugCheck.NotNull(config); Debug.Assert(cells.Count > 0, "There must be at least one cell in the container mapping"); // Go through each table and determine their foreign key constraints var container = containerMapping.StorageEntityContainer; Debug.Assert(container != null); var viewGenResults = new ViewGenResults(); var tmpLog = EnsureAllCSpaceContainerSetsAreMapped(cells, containerMapping); if (tmpLog.Count > 0) { viewGenResults.AddErrors(tmpLog); Helpers.StringTraceLine(viewGenResults.ErrorsToString()); return viewGenResults; } var foreignKeyConstraints = ForeignConstraint.GetForeignConstraints(container); var partitioner = new CellPartitioner(cells, foreignKeyConstraints); var cellGroups = partitioner.GroupRelatedCells(); foreach (var cellGroup in cellGroups) { ViewGenerator viewGenerator = null; var groupErrorLog = new ErrorLog(); try { viewGenerator = new ViewGenerator(cellGroup, config, foreignKeyConstraints, containerMapping); } catch (InternalMappingException exception) { // All exceptions have mapping errors in them Debug.Assert(exception.ErrorLog.Count > 0, "Incorrectly created mapping exception"); groupErrorLog = exception.ErrorLog; } if (groupErrorLog.Count == 0) { Debug.Assert(viewGenerator != null); groupErrorLog = viewGenerator.GenerateAllBidirectionalViews(viewGenResults.Views, identifiers); } if (groupErrorLog.Count != 0) { viewGenResults.AddErrors(groupErrorLog); } } // We used to print the errors here. Now we trace them as they are being thrown //if (viewGenResults.HasErrors && config.IsViewTracing) { // Helpers.StringTraceLine(viewGenResults.ErrorsToString()); //} return viewGenResults; }
// <summary> // Entry point for Type specific generation of Query Views // </summary> internal static ViewGenResults GenerateTypeSpecificQueryView( EntityContainerMapping containerMapping, ConfigViewGenerator config, EntitySetBase entity, EntityTypeBase type, bool includeSubtypes, out bool success) { DebugCheck.NotNull(containerMapping); DebugCheck.NotNull(config); DebugCheck.NotNull(entity); DebugCheck.NotNull(type); Debug.Assert(!type.Abstract, "Can not generate OfType/OfTypeOnly query view for and abstract type"); if (config.IsNormalTracing) { Helpers.StringTraceLine(""); Helpers.StringTraceLine( "<<<<<<<< Generating Query View for Entity [" + entity.Name + "] OfType" + (includeSubtypes ? "" : "Only") + "(" + type.Name + ") >>>>>>>"); } if (containerMapping.GetEntitySetMapping(entity.Name).QueryView != null) { //Type-specific QV does not exist in the cache, but // there is a EntitySet QV. So we can't generate the view (no mapping exists for this EntitySet) // and we rely on Query to call us again to get the EntitySet View. success = false; return null; } //Compute Cell Groups or get it from Memoizer var args = new InputForComputingCellGroups(containerMapping, config); var result = containerMapping.GetCellgroups(args); success = result.Success; if (!success) { return null; } var foreignKeyConstraints = result.ForeignKeyConstraints; // Get a Clone of cell groups from cache since cells are modified during viewgen, and we dont want the cached copy to change var cellGroups = result.CellGroups.Select(setOfcells => new CellGroup(setOfcells.Select(cell => new Cell(cell)))).ToList(); var cells = result.Cells; var identifiers = result.Identifiers; var viewGenResults = new ViewGenResults(); var tmpLog = EnsureAllCSpaceContainerSetsAreMapped(cells, containerMapping); if (tmpLog.Count > 0) { viewGenResults.AddErrors(tmpLog); Helpers.StringTraceLine(viewGenResults.ErrorsToString()); success = true; //atleast we tried successfully return viewGenResults; } foreach (var cellGroup in cellGroups) { if (!DoesCellGroupContainEntitySet(cellGroup, entity)) { continue; } ViewGenerator viewGenerator = null; var groupErrorLog = new ErrorLog(); try { viewGenerator = new ViewGenerator(cellGroup, config, foreignKeyConstraints, containerMapping); } catch (InternalMappingException exception) { // All exceptions have mapping errors in them Debug.Assert(exception.ErrorLog.Count > 0, "Incorrectly created mapping exception"); groupErrorLog = exception.ErrorLog; } if (groupErrorLog.Count > 0) { break; } Debug.Assert(viewGenerator != null); //make sure there is no exception thrown that does not add error to log var mode = includeSubtypes ? ViewGenMode.OfTypeViews : ViewGenMode.OfTypeOnlyViews; groupErrorLog = viewGenerator.GenerateQueryViewForSingleExtent(viewGenResults.Views, identifiers, entity, type, mode); if (groupErrorLog.Count != 0) { viewGenResults.AddErrors(groupErrorLog); } } success = true; return viewGenResults; }
// <summary> // This method compiles all the user defined query views in the <paramref name="entityContainerMapping" />. // </summary> private static void CompileUserDefinedQueryViews( EntityContainerMapping entityContainerMapping, Dictionary<EntitySetBase, GeneratedView> userDefinedQueryViewsDict, Dictionary<OfTypeQVCacheKey, GeneratedView> userDefinedQueryViewsOfTypeDict, IList<EdmSchemaError> errors) { var config = new ConfigViewGenerator(); foreach (var 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 (var 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); } } } } } }
// requires: cells are not normalized, i.e., no slot is null in the cell queries // effects: Constructs a validator object that is capable of // validating all the schema cells together internal CellGroupValidator(IEnumerable <Cell> cells, ConfigViewGenerator config) { m_cells = cells; m_config = config; m_errorLog = new ErrorLog(); }
/// <summary> /// Entry point for View Generation /// </summary> /// <param name="containerMapping"> </param> /// <param name="workSpace"> </param> /// <param name="config"> </param> /// <returns> Generated Views for EntitySets </returns> internal static ViewGenResults GenerateViewsFromMapping(StorageEntityContainerMapping containerMapping, ConfigViewGenerator config) { DebugCheck.NotNull(containerMapping); DebugCheck.NotNull(config); Debug.Assert(containerMapping.HasViews, "Precondition Violated: No mapping exists to generate views for!"); //Create Cells from StorageEntityContainerMapping var cellCreator = new CellCreator(containerMapping); var cells = cellCreator.GenerateCells(); var identifiers = cellCreator.Identifiers; return(GenerateViewsFromCells(cells, config, identifiers, containerMapping)); }