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());
            }
        }
Beispiel #14
0
 /// <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;
        }
 /// <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);
 }