/// <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 static bool TryRewrite(DbQueryCommandTree tree, Span span, MergeOption mergeOption, AliasGenerator aliasGenerator, out DbExpression newQuery, out SpanIndex spanInfo) { newQuery = null; spanInfo = null; ObjectSpanRewriter rewriter = null; bool requiresRelationshipSpan = Span.RequiresRelationshipSpan(mergeOption); // Potentially perform a rewrite for span. // Note that the public 'Span' property is NOT used to retrieve the Span instance // since this forces creation of a Span object that may not be required. if (span != null && span.SpanList.Count > 0) { rewriter = new ObjectFullSpanRewriter(tree, tree.Query, span, aliasGenerator); } else if (requiresRelationshipSpan) { rewriter = new ObjectSpanRewriter(tree, tree.Query, aliasGenerator); } if (rewriter != null) { rewriter.RelationshipSpan = requiresRelationshipSpan; newQuery = rewriter.RewriteQuery(); if (newQuery != null) { Debug.Assert(rewriter.SpanIndex != null || tree.Query.ResultType.EdmEquals(newQuery.ResultType), "Query was rewritten for Span but no SpanIndex was created?"); spanInfo = rewriter.SpanIndex; } } return (spanInfo != null); }
/// <summary> /// The only entry point. /// Rewrites the given tree by replacing expressions that are not directly supported on SQL Server 2000 /// with alterntive translations. /// </summary> /// <param name="originalTree">The tree to rewrite</param> /// <returns>The new tree</returns> internal static DbQueryCommandTree Rewrite(DbQueryCommandTree originalTree) { Debug.Assert(originalTree != null, "OriginalTree is null"); Sql8ExpressionRewriter rewriter = new Sql8ExpressionRewriter(originalTree.MetadataWorkspace); DbExpression newQuery = rewriter.VisitExpression(originalTree.Query); return DbQueryCommandTree.FromValidExpression(originalTree.MetadataWorkspace, originalTree.DataSpace, newQuery); }
/// <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> /// Converts the CTree into an ITree, and initializes the plan /// </summary> private void Initialize() { // Only support queries for now cqt.DbQueryCommandTree cqtree = m_ctree as cqt.DbQueryCommandTree; PlanCompiler.Assert(cqtree != null, "Unexpected command tree kind. Only query command tree is supported."); // Generate the ITree m_command = ITreeGenerator.Generate(cqtree); PlanCompiler.Assert(m_command != null, "Unable to generate internal tree from Command Tree"); }
/// <summary> /// The only entry point. /// Rewrites the given tree by replacing expressions that are not directly supported on SQL Server 2000 /// with alterntive translations. /// </summary> /// <param name="originalTree">The tree to rewrite</param> /// <returns>The new tree</returns> internal static DbQueryCommandTree Rewrite(DbQueryCommandTree originalTree) { Debug.Assert(originalTree != null, "OriginalTree is null"); var rewriter = new Sql8ExpressionRewriter(originalTree.MetadataWorkspace); var newQuery = rewriter.VisitExpression(originalTree.Query); #if DEBUG return new DbQueryCommandTree(originalTree.MetadataWorkspace, originalTree.DataSpace, newQuery); #else return new DbQueryCommandTree(originalTree.MetadataWorkspace, originalTree.DataSpace, newQuery, validate: false); #endif }
private DbQueryCommandTree Simplify(DbQueryCommandTree view) { var simplifier = PatternMatchRuleProcessor.Create( // determines if an expression is of the form outerProject(outerProjection(innerProject(innerNew))) PatternMatchRule.Create(Pattern_CollapseNestedProjection, ViewSimplifier.CollapseNestedProjection), // A case statement can potentially be simplified PatternMatchRule.Create(Pattern_Case, ViewSimplifier.SimplifyCaseStatement), // Nested TPH discriminator pattern can be converted to the expected TPH discriminator pattern PatternMatchRule.Create(Pattern_NestedTphDiscriminator, ViewSimplifier.SimplifyNestedTphDiscriminator), // Entity constructors may be augmented with FK-based related entity refs PatternMatchRule.Create(Pattern_EntityConstructor, this.AddFkRelatedEntityRefs) ); DbExpression queryExpression = view.Query; queryExpression = simplifier(queryExpression); view = DbQueryCommandTree.FromValidExpression(view.MetadataWorkspace, view.DataSpace, queryExpression); return view; }
/// <summary> /// Sets the expected column types for a given query command tree /// </summary> private void SetQueryExpectedTypes(DbQueryCommandTree tree, EFMySqlCommand cmd) { DbProjectExpression projectExpression = tree.Query as DbProjectExpression; if (projectExpression != null) { EdmType resultsType = projectExpression.Projection.ResultType.EdmType; StructuralType resultsAsStructuralType = resultsType as StructuralType; if (resultsAsStructuralType != null) { cmd.ColumnTypes = new PrimitiveType[resultsAsStructuralType.Members.Count]; for (int ordinal = 0; ordinal < resultsAsStructuralType.Members.Count; ordinal++) { EdmMember member = resultsAsStructuralType.Members[ordinal]; PrimitiveType primitiveType = member.TypeUsage.EdmType as PrimitiveType; cmd.ColumnTypes[ordinal] = primitiveType; } } } }
internal static DbQueryCommandTree SimplifyView(EntitySetBase extent, DbQueryCommandTree view) { ViewSimplifier vs = new ViewSimplifier(view.MetadataWorkspace, extent); view = vs.Simplify(view); return view; }
/// <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. ParserOptions.CompilationMode 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 (EntityUtil.IsCatchableExceptionType(e)) { 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; }
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) { StringBuilder trace = new StringBuilder(1024); this.ToCompactString(trace); Helpers.FormatTraceLine("CQL view for {0}", trace.ToString()); } }
protected virtual void VisitQueryCommandTree(DbQueryCommandTree queryTree) { EntityUtil.CheckArgumentNull(queryTree, "queryTree"); this.VisitExpression(queryTree.Query); }
public SqlSelectGenerator(DbQueryCommandTree commandTree) { _commandTree = commandTree; }
protected virtual void VisitQueryCommandTree(DbQueryCommandTree queryTree) { //Contract.Requires(queryTree != null); VisitExpression(queryTree.Query); }
/// <summary> /// Generates provider specific, read only SQL and updates entitySet DefiningQuery /// </summary> /// <param name="entitySet"></param> /// <param name="metadataWorkspace"></param> private void FixupViewEntitySetDefiningQuery(EntitySet entitySet, MetadataWorkspace metadataWorkspace) { DbExpressionBinding inputBinding = DbExpressionBuilder.BindAs(DbExpressionBuilder.Scan(entitySet), entitySet.Name); List<KeyValuePair<string, DbExpression>> projectList = new List<KeyValuePair<string, DbExpression>>(entitySet.ElementType.Members.Count); foreach (EdmMember member in entitySet.ElementType.Members) { Debug.Assert(member.BuiltInTypeKind == BuiltInTypeKind.EdmProperty, "Every member must be a edmproperty"); EdmProperty propertyInfo = (EdmProperty)member; projectList.Add(new KeyValuePair<string, DbExpression>(member.Name, DbExpressionBuilder.Property(inputBinding.Variable, propertyInfo))); } DbExpression query = inputBinding.Project(DbExpressionBuilder.NewRow(projectList)); DbQueryCommandTree dbCommandTree = new DbQueryCommandTree(metadataWorkspace, DataSpace.SSpace, query); // // get provider SQL and set entitySet DefiningQuery // entitySet.DefiningQuery = (DbProviderServices.GetProviderServices(_loader.EntityConnection.StoreProviderFactory) .CreateCommandDefinition(dbCommandTree)) .CreateCommand().CommandText; Debug.Assert(!String.IsNullOrEmpty(entitySet.DefiningQuery), "DefiningQuery must not be null or empty"); }