public void Process(FetchRequestBase resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree, string sourceAlias, bool userInnerJoin = false)
        {
            var join = tree.TreeBuilder.Dot(
                tree.TreeBuilder.Ident(sourceAlias),
                tree.TreeBuilder.Ident(resultOperator.RelationMember.Name));

            string alias = queryModelVisitor.Model.GetNewName("_");

            if (userInnerJoin)
            {
                tree.AddFromClause(tree.TreeBuilder.FetchJoin(join, tree.TreeBuilder.Alias(alias)));
            }
            else
            {
                tree.AddFromClause(tree.TreeBuilder.LeftFetchJoin(join, tree.TreeBuilder.Alias(alias)));
            }

            tree.AddDistinctRootOperator();

            foreach (var innerFetch in resultOperator.InnerFetchRequests)
            {
                if (innerFetch is InnerFetchOneRequest || innerFetch is InnerFetchManyRequest)
                {
                    Process(innerFetch, queryModelVisitor, tree, alias, true);
                }
                else
                {
                    Process(innerFetch, queryModelVisitor, tree, alias);
                }
            }
        }
        private IRelationEndPointDefinition GetEagerFetchRelationEndPointDefinition(FetchRequestBase fetchRequest, ClassDefinition classDefinition)
        {
            var propertyInfo = fetchRequest.RelationMember as PropertyInfo;

            if (propertyInfo == null)
            {
                var message = string.Format(
                    "The member '{0}' is a '{1}', which cannot be fetched by this LINQ provider. Only properties can be fetched.",
                    fetchRequest.RelationMember.Name,
                    fetchRequest.RelationMember.MemberType);
                throw new NotSupportedException(message);
            }

            var propertyInfoAdapter = PropertyInfoAdapter.Create(propertyInfo);
            var endPoint            = classDefinition.ResolveRelationEndPoint(propertyInfoAdapter)
                                      ?? classDefinition.GetAllDerivedClasses()
                                      .Select(cd => cd.ResolveRelationEndPoint(propertyInfoAdapter))
                                      .FirstOrDefault(ep => ep != null);

            if (endPoint == null)
            {
                Assertion.IsNotNull(propertyInfo.DeclaringType);
                var message = string.Format(
                    "The property '{0}.{1}' is not a relation end point. Fetching it is not supported by this LINQ provider.",
                    propertyInfo.DeclaringType.FullName,
                    propertyInfo.Name);
                throw new NotSupportedException(message);
            }

            return(endPoint);
        }
 private void CheckFetchQueryModelBuilder(
     FetchQueryModelBuilder builder, FetchRequestBase expectedFetchRequest, QueryModel expectedQueryModel, int expectedResultOperatorPosition)
 {
     Assert.That(builder.FetchRequest, Is.SameAs(expectedFetchRequest));
     Assert.That(builder.SourceItemQueryModel, Is.SameAs(expectedQueryModel));
     Assert.That(builder.ResultOperatorPosition, Is.EqualTo(expectedResultOperatorPosition));
 }
Exemple #4
0
        public void Process(FetchRequestBase resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree, string sourceAlias)
        {
            var memberPath = tree.TreeBuilder.Dot(
                tree.TreeBuilder.Ident(sourceAlias),
                tree.TreeBuilder.Ident(resultOperator.RelationMember.Name));

            Process(resultOperator, queryModelVisitor, tree, memberPath, null);
        }
Exemple #5
0
        public void Process(FetchRequestBase resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree)
        {
            var querySource = QuerySourceLocator.FindQuerySource(
                queryModelVisitor.Model,
                resultOperator.RelationMember.DeclaringType);

            Process(resultOperator, queryModelVisitor, tree, querySource.ItemName);
        }
    /// <summary>
    /// Initializes a new instance of the <see cref="FetchQueryModelBuilder"/> class.
    /// </summary>
    /// <param name="fetchRequest">The fetch request.</param>
    /// <param name="queryModel">The query model for which the <paramref name="fetchRequest"/> was originally defined.</param>
    /// <param name="resultOperatorPosition">The result operator position where the <paramref name="fetchRequest"/> was originally located.
    /// The <see cref="FetchQueryModelBuilder"/> will include all result operators prior to this position into the fetch <see cref="SourceItemQueryModel"/>,
    /// but it will not include any result operators occurring after (or at) that position.</param>
    public FetchQueryModelBuilder (FetchRequestBase fetchRequest, QueryModel queryModel, int resultOperatorPosition)
    {
      ArgumentUtility.CheckNotNull ("fetchRequest", fetchRequest);
      ArgumentUtility.CheckNotNull ("queryModel", queryModel);

      FetchRequest = fetchRequest;
      SourceItemQueryModel = queryModel;
      ResultOperatorPosition = resultOperatorPosition;
    }
    /// <summary>
    /// Gets or adds an eager-fetch request to this <see cref="FetchRequestCollection"/>.
    /// </summary>
    /// <param name="fetchRequest">The <see cref="FetchRequestBase"/> to be added.</param>
    /// <returns>
    /// <paramref name="fetchRequest"/> or, if another <see cref="FetchRequestBase"/> for the same relation member already existed,
    /// the existing <see cref="FetchRequestBase"/>.
    /// </returns>
    public FetchRequestBase GetOrAddFetchRequest (FetchRequestBase fetchRequest)
    {
      ArgumentUtility.CheckNotNull ("fetchRequest", fetchRequest);

      FetchRequestBase existingFetchRequest;
      if (_fetchRequests.TryGetValue (fetchRequest.RelationMember, out existingFetchRequest))
        return existingFetchRequest;
      else
      {
        _fetchRequests.Add (fetchRequest.RelationMember, fetchRequest);
        return fetchRequest;
      }
    }
Exemple #8
0
        private void Process(FetchRequestBase resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree, HqlDot memberPath, IType propType)
        {
            if (resultOperator is FetchOneRequest)
            {
                if (propType == null)
                {
                    var metadata = queryModelVisitor.VisitorParameters.SessionFactory
                                   .GetClassMetadata(resultOperator.RelationMember.ReflectedType);
                    propType = metadata?.GetPropertyType(resultOperator.RelationMember.Name);
                }

                if (propType != null && !propType.IsAssociationType)
                {
                    tree.AddFromLastChildClause(tree.TreeBuilder.Fetch());
                    tree.AddFromLastChildClause(memberPath);

                    ComponentType componentType = null;
                    foreach (var innerFetch in resultOperator.InnerFetchRequests)
                    {
                        if (componentType == null)
                        {
                            componentType = propType as ComponentType;
                            if (componentType == null)
                            {
                                throw new InvalidOperationException(
                                          $"Property {innerFetch.RelationMember.Name} cannot be fetched from a non component type property {resultOperator.RelationMember.Name}.");
                            }
                        }

                        var subTypeIndex = componentType.GetPropertyIndex(innerFetch.RelationMember.Name);
                        memberPath = tree.TreeBuilder.Dot(
                            memberPath,
                            tree.TreeBuilder.Ident(innerFetch.RelationMember.Name));

                        Process(innerFetch, queryModelVisitor, tree, memberPath, componentType.Subtypes[subTypeIndex]);
                    }

                    return;
                }
            }

            var alias = queryModelVisitor.Model.GetNewName("_");

            tree.AddFromClause(tree.TreeBuilder.LeftFetchJoin(memberPath, tree.TreeBuilder.Alias(alias)));
            tree.AddDistinctRootOperator();

            foreach (var innerFetch in resultOperator.InnerFetchRequests)
            {
                Process(innerFetch, queryModelVisitor, tree, alias);
            }
        }
Exemple #9
0
        public void Process(FetchRequestBase resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree, string sourceAlias)
        {
            var join = tree.TreeBuilder.Dot(
                tree.TreeBuilder.Ident(sourceAlias),
                tree.TreeBuilder.Ident(resultOperator.RelationMember.Name));

            string alias = queryModelVisitor.Model.GetNewName("_");

            tree.AddFromClause(tree.TreeBuilder.LeftFetchJoin(join, tree.TreeBuilder.Alias(alias)));
            tree.AddDistinctRootOperator();

            foreach (var innerFetch in resultOperator.InnerFetchRequests)
            {
                Process(innerFetch, queryModelVisitor, tree, alias);
            }
        }
Exemple #10
0
        private void ProcessFetchRequest(FetchRequestBase fetchRequest, QueryModel queryModel)
        {
            var declaringType = fetchRequest.RelationMember.DeclaringType;

            // TODO:

            // INNER JOIN Vs LEFT JOIN (Perhaps use a FetchRequired for optimized INNER JOIN.
            // Look at Required flag on Entity.

            // AutoMapper can use entity prefix underscore to map related entities from fetch.

            // How to update the SELECT for the fetched entity = use a join test to see how it works.

            // Want something like below:

            const string sql = @"SELECT tc.[ContactID] as ContactID,
                tc.[ContactName] as ContactName
                ,tp.[PhoneId] AS TestPhones_PhoneId
                ,tp.[ContactId] AS TestPhones_ContactId
                ,tp.[Number] AS TestPhones_Number
                FROM TestContact tc
                INNER JOIN TestPhone tp ON tc.ContactId = tp.ContactId";
        }
Exemple #11
0
        public void Process(FetchRequestBase resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree)
        {
            var querySource = QuerySourceLocator.FindQuerySource(queryModelVisitor.Model, resultOperator.RelationMember.DeclaringType);

            Process(resultOperator, queryModelVisitor, tree, querySource.ItemName);
        }
        private void Process(
            FetchRequestBase resultOperator,
            QueryModelVisitor queryModelVisitor,
            IntermediateHqlTree tree,
            HqlDot memberPath,
            HqlTreeNode currentNode,
            IType propType)
        {
            string alias = null;

            if (resultOperator is FetchOneRequest)
            {
                if (propType == null)
                {
                    var metadata = queryModelVisitor.VisitorParameters.SessionFactory
                                   .GetClassMetadata(resultOperator.RelationMember.ReflectedType);
                    propType = metadata?.GetPropertyType(resultOperator.RelationMember.Name);
                }

                if (propType != null && !propType.IsAssociationType)
                {
                    if (currentNode == null)
                    {
                        currentNode = tree.GetFromRangeClause()
                                      ?? throw new InvalidOperationException($"Property {resultOperator.RelationMember.Name} cannot be fetched for this type of query.");
                    }

                    currentNode.AddChild(tree.TreeBuilder.Fetch());
                    currentNode.AddChild(memberPath);

                    ComponentType componentType = null;
                    foreach (var innerFetch in resultOperator.InnerFetchRequests)
                    {
                        if (componentType == null)
                        {
                            componentType = propType as ComponentType;
                            if (componentType == null)
                            {
                                throw new InvalidOperationException(
                                          $"Property {innerFetch.RelationMember.Name} cannot be fetched from a non component type property {resultOperator.RelationMember.Name}.");
                            }
                        }

                        var subTypeIndex = componentType.GetPropertyIndex(innerFetch.RelationMember.Name);
                        memberPath = tree.TreeBuilder.Dot(
                            memberPath,
                            tree.TreeBuilder.Ident(innerFetch.RelationMember.Name));

                        Process(innerFetch, queryModelVisitor, tree, memberPath, currentNode, componentType.Subtypes[subTypeIndex]);
                    }

                    return;
                }

                var relatedJoin = queryModelVisitor.RelatedJoinFetchRequests.FirstOrDefault(o => o.Value == resultOperator).Key;
                if (relatedJoin != null)
                {
                    alias = queryModelVisitor.VisitorParameters.QuerySourceNamer.GetName(relatedJoin);
                }
            }

            if (alias == null)
            {
                alias       = queryModelVisitor.Model.GetNewName("_");
                currentNode = tree.TreeBuilder.LeftFetchJoin(memberPath, tree.TreeBuilder.Alias(alias));
                tree.AddFromClause(currentNode);
            }

            tree.AddDistinctRootOperator();

            foreach (var innerFetch in resultOperator.InnerFetchRequests)
            {
                Process(innerFetch, queryModelVisitor, tree, currentNode, alias);
            }
        }
 public void Process(FetchRequestBase resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree, string sourceAlias)
 {
     Process(resultOperator, queryModelVisitor, tree, null, sourceAlias);
 }