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); }
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)); }
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); }
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); }
/// <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); }
/// <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))); }
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; }