public void Prepare_returns_a_new_instance() { var objectQueryExecutionPlanFactory = new ObjectQueryExecutionPlanFactory( Common.Internal.Materialization.MockHelper.CreateTranslator<object>()); var metadataWorkspace = new MetadataWorkspace(); var edmItemCollection = new EdmItemCollection(); metadataWorkspace.RegisterItemCollection(edmItemCollection); metadataWorkspace.RegisterItemCollection(new ObjectItemCollection()); var fakeSqlProviderManifest = new FakeSqlProviderServices().GetProviderManifest("2008"); var storeItemCollection = new StoreItemCollection(FakeSqlProviderFactory.Instance, fakeSqlProviderManifest, "2008"); metadataWorkspace.RegisterItemCollection(storeItemCollection); metadataWorkspace.RegisterItemCollection(new StorageMappingItemCollection(edmItemCollection, storeItemCollection, Enumerable.Empty<XmlReader>())); var fakeSqlConnection = new FakeSqlConnection(); fakeSqlConnection.ConnectionString = "foo"; var entityConnection = new EntityConnection(metadataWorkspace, fakeSqlConnection, false); var objectContext = new ObjectContext(entityConnection); var dbExpression = new DbNullExpression(TypeUsage.Create(fakeSqlProviderManifest.GetStoreTypes().First())); var dbQueryCommandTree = new DbQueryCommandTree(metadataWorkspace, DataSpace.CSpace, dbExpression, validate: false); var parameters = new List<Tuple<ObjectParameter, QueryParameterExpression>>(); var objectQueryExecutionPlan = objectQueryExecutionPlanFactory.Prepare(objectContext, dbQueryCommandTree, typeof(object), MergeOption.NoTracking, new Span(), parameters, aliasGenerator: null); Assert.NotNull(objectQueryExecutionPlan); }
/// <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 void GetAffectedEntitySets(System.Data.Entity.Core.Common.CommandTrees.DbCommandTree commandTree) { System.Data.Entity.Core.Common.CommandTrees.DbExpressionVisitor visitor = new FindAffectedEntitySetsVisitor(this.affectedEntitySets, this.functionsUsed); System.Data.Entity.Core.Common.CommandTrees.DbQueryCommandTree queryTree = commandTree as System.Data.Entity.Core.Common.CommandTrees.DbQueryCommandTree; if (queryTree != null) { queryTree.Query.Accept(visitor); return; } System.Data.Entity.Core.Common.CommandTrees.DbFunctionCommandTree fxnTree = commandTree as System.Data.Entity.Core.Common.CommandTrees.DbFunctionCommandTree; if (fxnTree != null) { this.IsStoredProcedure = true; return; } System.Data.Entity.Core.Common.CommandTrees.DbUpdateCommandTree updateTree = commandTree as System.Data.Entity.Core.Common.CommandTrees.DbUpdateCommandTree; if (updateTree != null) { this.IsModification = true; updateTree.Target.Expression.Accept(visitor); updateTree.Predicate.Accept(visitor); if (updateTree.Returning != null) { updateTree.Returning.Accept(visitor); } return; } System.Data.Entity.Core.Common.CommandTrees.DbInsertCommandTree insertTree = commandTree as System.Data.Entity.Core.Common.CommandTrees.DbInsertCommandTree; if (insertTree != null) { this.IsModification = true; insertTree.Target.Expression.Accept(visitor); if (insertTree.Returning != null) { insertTree.Returning.Accept(visitor); } return; } System.Data.Entity.Core.Common.CommandTrees.DbDeleteCommandTree deleteTree = commandTree as System.Data.Entity.Core.Common.CommandTrees.DbDeleteCommandTree; if (deleteTree != null) { this.IsModification = true; deleteTree.Target.Expression.Accept(visitor); if (deleteTree.Predicate != null) { deleteTree.Predicate.Accept(visitor); } return; } throw new NotSupportedException("Command tree type " + commandTree.GetType() + " is not supported."); }
/// <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); }
public virtual ObjectQueryExecutionPlan Prepare( ObjectContext context, DbQueryCommandTree tree, Type elementType, MergeOption mergeOption, bool streaming, Span span, IEnumerable<Tuple<ObjectParameter, QueryParameterExpression>> compiledQueryParameters, AliasGenerator aliasGenerator) { var treeResultType = tree.Query.ResultType; // Rewrite this tree for Span? DbExpression spannedQuery; SpanIndex spanInfo; if (ObjectSpanRewriter.TryRewrite(tree, span, mergeOption, aliasGenerator, out spannedQuery, out spanInfo)) { tree = DbQueryCommandTree.FromValidExpression( tree.MetadataWorkspace, tree.DataSpace, spannedQuery, tree.UseDatabaseNullSemantics); } else { spanInfo = null; } var entityDefinition = CreateCommandDefinition(context, tree); var shaperFactory = Translator.TranslateColumnMap( _translator, elementType, entityDefinition.CreateColumnMap(null), context.MetadataWorkspace, spanInfo, mergeOption, streaming, false); // attempt to determine entity information for this query (e.g. which entity type and which entity set) EntitySet singleEntitySet = null; // determine if the entity set is unambiguous given the entity type if (treeResultType.EdmType.BuiltInTypeKind == BuiltInTypeKind.CollectionType && entityDefinition.EntitySets != null) { foreach (var entitySet in entityDefinition.EntitySets) { if (entitySet != null && entitySet.ElementType.IsAssignableFrom(((CollectionType)treeResultType.EdmType).TypeUsage.EdmType)) { if (singleEntitySet == null) { // found a single match singleEntitySet = entitySet; } else { // there's more than one matching entity set singleEntitySet = null; break; } } } } return new ObjectQueryExecutionPlan( entityDefinition, shaperFactory, treeResultType, mergeOption, streaming, singleEntitySet, compiledQueryParameters); }
/// <summary> /// This method is called after a new DbCommandTree has been created. /// It collects only DbQueryCommandTrees. /// </summary> /// <param name="interceptionContext">Represents contextual information associated with calls into IDbCommandTreeInterceptor implementations.</param> public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext) { if (interceptionContext.Result.CommandTreeKind == DbCommandTreeKind.Query && interceptionContext.Result.DataSpace == DataSpace.SSpace) { if (interceptionContext.ObjectContexts.Contains(_objectContext, ReferenceEquals)) { DbQueryCommandTree = (DbQueryCommandTree)interceptionContext.Result; } } }
/// <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 static EntityCommandDefinition CreateCommandDefinition(ObjectContext context, DbQueryCommandTree tree) { var connection = context.Connection; // The connection is required to get to the CommandDefinition builder. if (connection == null) { throw new InvalidOperationException(Strings.ObjectQuery_InvalidConnection); } var services = DbProviderServices.GetProviderServices(connection); DbCommandDefinition definition; try { definition = services.CreateCommandDefinition(tree, context.InterceptionContext); } catch (EntityCommandCompilationException) { // If we're running against EntityCommand, we probably already caught the providers' // exception and wrapped it, we don't want to do that again, so we'll just rethrow // here instead. throw; } catch (Exception e) { // we should not be wrapping all exceptions if (e.IsCatchableExceptionType()) { // we don't wan't folks to have to know all the various types of exceptions that can // occur, so we just rethrow a CommandDefinitionException and make whatever we caught // the inner exception of it. throw new EntityCommandCompilationException(Strings.EntityClient_CommandDefinitionPreparationFailed, e); } throw; } if (definition == null) { throw new NotSupportedException(Strings.ADP_ProviderDoesNotSupportCommandTrees); } return (EntityCommandDefinition)definition; }
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; var 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); }
protected virtual void VisitQueryCommandTree(DbQueryCommandTree queryTree) { Contract.Requires(queryTree != null); VisitExpression(queryTree.Query); }
/// <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; } } } }
/// <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; }
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>Implements the visitor pattern for the query command tree.</summary> /// <param name="queryTree">The query command tree.</param> protected virtual void VisitQueryCommandTree(DbQueryCommandTree queryTree) { Check.NotNull(queryTree, "queryTree"); VisitExpression(queryTree.Query); }
// internal for testing internal static string CreateDefiningQuery(EntitySet entitySet, MetadataWorkspace workspace, DbProviderServices providerServices) { Debug.Assert(entitySet != null, "entitySet != null"); Debug.Assert(workspace != null, "workspace != null"); Debug.Assert(providerServices != null, "providerServices != null"); var inputBinding = entitySet.Scan().BindAs(entitySet.Name); var projectList = new List<KeyValuePair<string, DbExpression>>(entitySet.ElementType.Members.Count); foreach (var member in entitySet.ElementType.Members) { Debug.Assert(member.BuiltInTypeKind == BuiltInTypeKind.EdmProperty, "Every member must be a edmproperty"); var propertyInfo = (EdmProperty)member; projectList.Add( new KeyValuePair<string, DbExpression>( member.Name, inputBinding.Variable.Property(propertyInfo))); } var query = inputBinding.Project(DbExpressionBuilder.NewRow(projectList)); var dbCommandTree = new DbQueryCommandTree(workspace, DataSpace.SSpace, query); return providerServices.CreateCommandDefinition(dbCommandTree).CreateCommand().CommandText; }