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: 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).ToList(); 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, ViewGenMode mode) { Debug.Assert(mode != ViewGenMode.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, m_entityContainerMapping.StorageMappingItemCollection); string eSQLView; DbQueryCommandTree commandTree; if (m_config.GenerateEsql) { eSQLView = cqlGen.GenerateEsql(); commandTree = null; } else { eSQLView = null; commandTree = cqlGen.GenerateCqt(); } GeneratedView generatedView = GeneratedView.CreateGeneratedView(context.Extent, generatedType, commandTree, eSQLView, m_entityContainerMapping.StorageMappingItemCollection, m_config); views.Add(context.Extent, generatedView); return(queryRewriter); }
/// <summary> /// Creates a union block with SELECT (<paramref name="slotInfos" />), FROM (<paramref name="children" />), WHERE (true), AS ( /// <paramref /// name="blockAliasNum" /> /// ). /// </summary> internal UnionCqlBlock(SlotInfo[] slotInfos, List <CqlBlock> children, CqlIdentifiers identifiers, int blockAliasNum) : base(slotInfos, children, BoolExpression.True, identifiers, blockAliasNum) { }
private ErrorLog GenerateQueryViewForExtentAndType(StorageEntityContainerMapping entityContainerMapping, CqlIdentifiers identifiers, ViewSet views, EntitySetBase entity, EntityTypeBase type, ViewGenMode mode) { Debug.Assert(mode != ViewGenMode.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 == ViewGenMode.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); }
// 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, ViewGenMode.OfTypeViews); } } else { // generate the view for Extent only queryRewriter = GenerateViewsForExtentAndType(extent.ElementType, context, identifiers, views, ViewGenMode.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: 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> // Initializes a <see cref="CqlBlock" /> with the SELECT (<paramref name="slotInfos" />), FROM ( // <paramref // name="children" /> // ), // WHERE (<paramref name="whereClause" />), AS (<paramref name="blockAliasNum" />). // </summary> protected CqlBlock( SlotInfo[] slotInfos, List <CqlBlock> children, BoolExpression whereClause, CqlIdentifiers identifiers, int blockAliasNum) { m_slots = new ReadOnlyCollection <SlotInfo>(slotInfos); m_children = new ReadOnlyCollection <CqlBlock>(children); m_whereClause = whereClause; m_blockAlias = identifiers.GetBlockAlias(blockAliasNum); }
// <summary> // Creates a <see cref="CqlBlock" /> containing the case statememt for the <paramref name="caseSlot" /> and projecting other slots as is from its child (input). CqlBlock with SELECT (slots), // </summary> // <param name="caseSlot"> // indicates which slot in <paramref name="slots" /> corresponds to the case statement being generated by this block // </param> internal CaseCqlBlock( SlotInfo[] slots, int caseSlot, CqlBlock child, BoolExpression whereClause, CqlIdentifiers identifiers, int blockAliasNum) : base(slots, new List <CqlBlock>(new[] { child }), whereClause, identifiers, blockAliasNum) { m_caseSlotInfo = slots[caseSlot]; }
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); }
/// <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) { EntityUtil.CheckArgumentNull(containerMapping, "containerMapping"); EntityUtil.CheckArgumentNull(config, "config"); EntityUtil.CheckArgumentNull(entity, "entity"); EntityUtil.CheckArgumentNull(type, "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 InputForComputingCellGroups args = new InputForComputingCellGroups(containerMapping, config); OutputFromComputeCellGroups result = containerMapping.GetCellgroups(args); success = result.Success; if (!success) { return(null); } List <ForeignConstraint> 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 List <CellGroup> cellGroups = cellGroups = result.CellGroups.Select(setOfcells => new CellGroup(setOfcells.Select(cell => new Cell(cell)))).ToList(); List <Cell> cells = result.Cells; CqlIdentifiers identifiers = result.Identifiers; ViewGenResults viewGenResults = new ViewGenResults(); ErrorLog tmpLog = EnsureAllCSpaceContainerSetsAreMapped(cells, config, containerMapping); if (tmpLog.Count > 0) { viewGenResults.AddErrors(tmpLog); Helpers.StringTraceLine(viewGenResults.ErrorsToString()); success = true; //atleast we tried successfully return(viewGenResults); } foreach (CellGroup cellGroup in cellGroups) { if (!DoesCellGroupContainEntitySet(cellGroup, entity)) { continue; } ViewGenerator viewGenerator = null; ErrorLog 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 ViewGenMode 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); }
// effects: Creates a cell creator object for an entity container's // mappings (specified in "maps") internal CellCreator(StorageEntityContainerMapping containerMapping) { m_containerMapping = containerMapping; m_identifiers = new CqlIdentifiers(); }
internal CellCreator(EntityContainerMapping containerMapping) { this.m_containerMapping = containerMapping; this.m_identifiers = new CqlIdentifiers(); }