예제 #1
0
        public OrderByPropertyNode(Stack <OrderByQueryNode> nodes)
        {
            if (nodes == null)
            {
                throw Error.ArgumentNull("nodes");
            }

            if (nodes.Count == 0)
            {
                throw new ODataException(SRResources.OrderByNodeNotFound);
            }

            OrderByQueryNode        currentNode = nodes.Pop();
            PropertyAccessQueryNode property    = currentNode.Expression as PropertyAccessQueryNode;

            if (property == null)
            {
                throw new ODataException(SRResources.OrderByPropertyNotFound);
            }

            Property  = property.Property;
            Direction = currentNode.Direction;

            if (nodes.Count > 0)
            {
                ThenBy = new OrderByPropertyNode(nodes);
            }
        }
 public static OrderByPropertyNode Create(OrderByQueryNode node)
 {
     Stack<OrderByQueryNode> nodes = new Stack<OrderByQueryNode>();
     OrderByQueryNode currentNode = node;
     while (currentNode != null)
     {
         nodes.Push(currentNode);
         currentNode = currentNode.Collection as OrderByQueryNode;
     }
     return new OrderByPropertyNode(nodes);
 }
예제 #3
0
        public static OrderByPropertyNode Create(OrderByQueryNode node)
        {
            Stack <OrderByQueryNode> nodes       = new Stack <OrderByQueryNode>();
            OrderByQueryNode         currentNode = node;

            while (currentNode != null)
            {
                nodes.Push(currentNode);
                currentNode = currentNode.Collection as OrderByQueryNode;
            }
            return(new OrderByPropertyNode(nodes));
        }
예제 #4
0
        private object ProcessNode(OrderByQueryNode orderByQuery)
        {
            // TODO: This currently assumes a single property lookup
            var ret        = ProcessNode(orderByQuery.Collection);
            var expression = ProcessNode(orderByQuery.Expression).ToString();

            if (expression.StartsWith("?"))
            {
                _sparqlModel.Ordering = new SparqlVariableOrdering(expression.TrimStart('?'),
                                                                   orderByQuery.Direction == OrderByDirection.Descending);
            }
            else
            {
                throw new Exception("No handling for SPARQL expression ordering yet");
            }
            return(ret);
        }
예제 #5
0
        public void CreateCollection_From_OrderByQueryNode_Succeeds()
        {
            // Arrange
            Mock <IEdmTypeReference> mockTypeReference1 = new Mock <IEdmTypeReference>();
            Mock <IEdmTypeReference> mockTypeReference2 = new Mock <IEdmTypeReference>();
            Mock <IEdmProperty>      mockProperty1      = new Mock <IEdmProperty>();

            mockProperty1.SetupGet <IEdmTypeReference>(p => p.Type).Returns(mockTypeReference1.Object);
            Mock <IEdmProperty> mockProperty2 = new Mock <IEdmProperty>();

            mockProperty1.SetupGet <IEdmTypeReference>(p => p.Type).Returns(mockTypeReference2.Object);
            PropertyAccessQueryNode propertyAccessQueryNode1 = new PropertyAccessQueryNode()
            {
                Property = mockProperty1.Object,
            };
            PropertyAccessQueryNode propertyAccessQueryNode2 = new PropertyAccessQueryNode()
            {
                Property = mockProperty2.Object,
            };

            OrderByQueryNode queryNode1 = new OrderByQueryNode()
            {
                Direction  = OrderByDirection.Descending,
                Collection = null,
                Expression = propertyAccessQueryNode1
            };

            OrderByQueryNode queryNode2 = new OrderByQueryNode()
            {
                Direction  = OrderByDirection.Ascending,
                Collection = queryNode1,
                Expression = propertyAccessQueryNode2
            };

            // Act
            ICollection <OrderByPropertyNode> nodes = OrderByPropertyNode.CreateCollection(queryNode2);

            // Assert
            Assert.Equal(2, nodes.Count);
            Assert.ReferenceEquals(mockProperty1.Object, nodes.First().Property);
            Assert.Equal(OrderByDirection.Descending, nodes.First().Direction);

            Assert.ReferenceEquals(mockProperty2.Object, nodes.Last().Property);
            Assert.Equal(OrderByDirection.Ascending, nodes.Last().Direction);
        }
        /// <summary>
        /// Creates a collection of <see cref="OrderByPropertyNode"/>
        /// instances from a linked list of <see cref="OrderByQueryNode"/>
        /// instances.
        /// </summary>
        /// <remarks>The order of the items in the <see cref="OrderByQueryNode"/>
        /// linked list will be reversed in the <see cref="OrderByPropertyNode"/>
        /// collection.</remarks>
        /// <param name="node">The head of the <see cref="OrderByQueryNode"/>
        /// linked list.</param>
        /// <returns>The collection of new <see cref="OrderByPropertyNode"/> instances.</returns>
        public static ICollection<OrderByPropertyNode> CreateCollection(OrderByQueryNode node)
        {
            LinkedList<OrderByPropertyNode> result = new LinkedList<OrderByPropertyNode>();
            for (OrderByQueryNode currentNode = node; 
                 currentNode != null; 
                 currentNode = currentNode.Collection as OrderByQueryNode)
            {
                PropertyAccessQueryNode property = currentNode.Expression as PropertyAccessQueryNode;

                if (property == null)
                {
                    throw new ODataException(SRResources.OrderByPropertyNotFound);
                }
                result.AddFirst(new OrderByPropertyNode(property.Property, currentNode.Direction));
            }

            return result;
        }
        public void CreateCollection_From_OrderByQueryNode_Succeeds()
        {
            // Arrange
            Mock<IEdmTypeReference> mockTypeReference1 = new Mock<IEdmTypeReference>();
            Mock<IEdmTypeReference> mockTypeReference2 = new Mock<IEdmTypeReference>();
            Mock<IEdmProperty> mockProperty1 = new Mock<IEdmProperty>();
            mockProperty1.SetupGet<IEdmTypeReference>(p => p.Type).Returns(mockTypeReference1.Object);
            Mock<IEdmProperty> mockProperty2 = new Mock<IEdmProperty>();
            mockProperty1.SetupGet<IEdmTypeReference>(p => p.Type).Returns(mockTypeReference2.Object);
            PropertyAccessQueryNode propertyAccessQueryNode1 = new PropertyAccessQueryNode()
            {
                Property = mockProperty1.Object,
            };
            PropertyAccessQueryNode propertyAccessQueryNode2 = new PropertyAccessQueryNode()
            {
                Property = mockProperty2.Object,
            };

            OrderByQueryNode queryNode1 = new OrderByQueryNode()
            {
                Direction = OrderByDirection.Descending,
                Collection = null,
                Expression = propertyAccessQueryNode1
            };

            OrderByQueryNode queryNode2 = new OrderByQueryNode()
            {
                Direction = OrderByDirection.Ascending,
                Collection = queryNode1,
                Expression = propertyAccessQueryNode2
            };

            // Act
            ICollection<OrderByPropertyNode> nodes = OrderByPropertyNode.CreateCollection(queryNode2);

            // Assert
            Assert.Equal(2, nodes.Count);
            Assert.ReferenceEquals(mockProperty1.Object, nodes.First().Property);
            Assert.Equal(OrderByDirection.Descending, nodes.First().Direction);

            Assert.ReferenceEquals(mockProperty2.Object, nodes.Last().Property);
            Assert.Equal(OrderByDirection.Ascending, nodes.Last().Direction);
        }
예제 #8
0
        /// <summary>
        /// Creates a collection of <see cref="OrderByPropertyNode"/>
        /// instances from a linked list of <see cref="OrderByQueryNode"/>
        /// instances.
        /// </summary>
        /// <remarks>The order of the items in the <see cref="OrderByQueryNode"/>
        /// linked list will be reversed in the <see cref="OrderByPropertyNode"/>
        /// collection.</remarks>
        /// <param name="node">The head of the <see cref="OrderByQueryNode"/>
        /// linked list.</param>
        /// <returns>The collection of new <see cref="OrderByPropertyNode"/> instances.</returns>
        public static ICollection <OrderByPropertyNode> CreateCollection(OrderByQueryNode node)
        {
            LinkedList <OrderByPropertyNode> result = new LinkedList <OrderByPropertyNode>();

            for (OrderByQueryNode currentNode = node;
                 currentNode != null;
                 currentNode = currentNode.Collection as OrderByQueryNode)
            {
                PropertyAccessQueryNode property = currentNode.Expression as PropertyAccessQueryNode;

                if (property == null)
                {
                    throw new ODataException(SRResources.OrderByPropertyNotFound);
                }
                result.AddFirst(new OrderByPropertyNode(property.Property, currentNode.Direction));
            }

            return(result);
        }
예제 #9
0
        /// <summary>
        /// Processes the specified order-by token.
        /// </summary>
        /// <param name="query">The query tree constructed so far.</param>
        /// <param name="orderByToken">The order-by token to bind.</param>
        /// <returns>Returns the combined query including the ordering.</returns>
        private QueryNode ProcessSingleOrderBy(QueryNode query, OrderByQueryToken orderByToken)
        {
            Debug.Assert(query != null, "query != null");
            ExceptionUtils.CheckArgumentNotNull(orderByToken, "orderByToken");

            CollectionQueryNode entityCollection = query.AsEntityCollectionNode();
            if (entityCollection == null)
            {
                throw new ODataException(Strings.MetadataBinder_OrderByNotApplicable);
            }

            this.parameter = new ParameterQueryNode() { ParameterType = entityCollection.ItemType };

            QueryNode expressionNode = this.Bind(orderByToken.Expression);

            // TODO: shall we really restrict order-by expressions to primitive types?
            SingleValueQueryNode expressionResultNode = expressionNode as SingleValueQueryNode;
            if (expressionResultNode == null ||
                (expressionResultNode.TypeReference != null && !expressionResultNode.TypeReference.IsODataPrimitiveTypeKind()))
            {
                throw new ODataException(Strings.MetadataBinder_OrderByExpressionNotSingleValue);
            }

            query = new OrderByQueryNode()
            {
                Collection = entityCollection,
                Direction = orderByToken.Direction,
                Parameter = this.parameter,
                Expression = expressionResultNode
            };

            this.parameter = null;

            return query;
        }
        /// <summary>
        /// Translates an orderby node.
        /// </summary>
        /// <param name="orderByNode">The orderby node to translate.</param>
        /// <returns>Expression which evaluates to the result after the order operation.</returns>
        protected virtual Expression TranslateOrderBy(OrderByQueryNode orderByNode)
        {
            ExceptionUtils.CheckArgumentNotNull(orderByNode, "orderByNode");
            ExceptionUtils.CheckArgumentNotNull(orderByNode.ItemType, "orderByNode.ItemType");
            ExceptionUtils.CheckArgumentNotNull(orderByNode.Collection, "orderByNode.Collection");
            ExceptionUtils.CheckArgumentNotNull(orderByNode.Collection.ItemType, "orderByNode.Collection.ItemType");
            ExceptionUtils.CheckArgumentNotNull(orderByNode.Expression, "orderByNode.Expression");
            ExceptionUtils.CheckArgumentNotNull(orderByNode.Parameter, "orderByNode.Parameter");
            ExceptionUtils.CheckArgumentNotNull(orderByNode.Parameter.TypeReference, "orderByNode.Parameter.Type");

            ParameterExpression parameter = Expression.Parameter(orderByNode.Parameter.TypeReference.GetInstanceType(this.model), "element");
            Expression collectionExpression = this.Translate(orderByNode.Collection);

            // TODO: If we should support OrderBy on IEnumerable, then we need to add support here
            Type expectedCollectionType = typeof(IQueryable<>).MakeGenericType(parameter.Type);
            if (!expectedCollectionType.IsAssignableFrom(collectionExpression.Type))
            {
                throw new ODataException(Strings.QueryExpressionTranslator_OrderByCollectionOfWrongType(collectionExpression.Type, expectedCollectionType));
            }

            this.parameterNodeDefinitions.Push(new KeyValuePair<ParameterQueryNode, Expression>(orderByNode.Parameter, parameter));
            Expression body = this.Translate(orderByNode.Expression);
            Debug.Assert(this.parameterNodeDefinitions.Peek().Key == orderByNode.Parameter, "The parameter definition stack was not balanced correctly.");
            Debug.Assert(this.parameterNodeDefinitions.Peek().Value == parameter, "The parameter definition stack was not balanced correctly.");
            this.parameterNodeDefinitions.Pop();

            // If the collectionExpression is already another OrderBy or ThenBy we need to use a ThenBy
            string methodName = orderByNode.Direction == OrderByDirection.Ascending ? OrderByMethodName : OrderByDescendingMethodName;
            if (collectionExpression.NodeType == ExpressionType.Call)
            {
                MethodCallExpression collectionMethodCallExpression = (MethodCallExpression)collectionExpression;
                if (collectionMethodCallExpression.Method.DeclaringType == typeof(Queryable) &&
                    collectionMethodCallExpression.Method.Name == OrderByMethodName ||
                    collectionMethodCallExpression.Method.Name == OrderByDescendingMethodName ||
                    collectionMethodCallExpression.Method.Name == ThenByMethodName ||
                    collectionMethodCallExpression.Method.Name == ThenByDescendingMethodName)
                {
                    methodName = orderByNode.Direction == OrderByDirection.Ascending ? ThenByMethodName : ThenByDescendingMethodName;
                }
            }

            return Expression.Call(
                typeof(Queryable),
                methodName,
                new Type[] { parameter.Type, body.Type },
                collectionExpression,
                Expression.Quote(Expression.Lambda(body, parameter)));
        }
예제 #11
0
 private object ProcessNode(OrderByQueryNode orderByQuery)
 {
     // TODO: This currently assumes a single property lookup
     var ret = ProcessNode(orderByQuery.Collection);
     var expression = ProcessNode(orderByQuery.Expression).ToString();
     if (expression.StartsWith("?"))
     {
         _sparqlModel.Ordering = new SparqlVariableOrdering(expression.TrimStart('?'),
                                                            orderByQuery.Direction == OrderByDirection.Descending);
     }
     else
     {
         throw new Exception("No handling for SPARQL expression ordering yet");
     }
     return ret;
 }