private static Expression GetThenByCall(this Expression expression, OrderByClause orderByClause) { const string ThenBy = "ThenBy"; const string ThenByDescending = "ThenByDescending"; return(orderByClause.ThenBy == null ? GetMethodCall() : GetMethodCall().GetThenByCall(orderByClause.ThenBy)); Expression GetMethodCall() { return(orderByClause.Expression switch { CountNode countNode => expression.GetOrderByCountCall ( countNode.GetPropertyPath(), orderByClause.Direction == OrderByDirection.Ascending ? ThenBy : ThenByDescending ), SingleValuePropertyAccessNode propertyNode => expression.GetOrderByCall ( propertyNode.GetPropertyPath(), orderByClause.Direction == OrderByDirection.Ascending ? ThenBy : ThenByDescending ), _ => throw new ArgumentException($"Unsupported SingleValueNode value: {orderByClause.Expression.GetType()}"), }); }
/// <summary> /// Translates a <see cref="CountNode"/> into a corresponding <see cref="String"/>. /// </summary> /// <param name="node">The node to translate.</param> /// <returns>The translated String.</returns> public override String Visit(CountNode node) { ExceptionUtils.CheckArgumentNotNull(node, "node"); String source = this.TranslateNode(node.Source); return string.Concat(source, ExpressionConstants.SymbolForwardSlash, UriQueryConstants.CountSegment); }
public override Expression Visit(CountNode nodeIn) { var navigation = (CollectionNavigationNode)nodeIn.Source; MemberExpression property = Expression.Property(Parameter, navigation.NavigationProperty.Name); var typeArguments = new Type[] { OeExpressionHelper.GetCollectionItemType(property.Type) }; return(Expression.Call(typeof(Enumerable), nameof(Enumerable.Count), typeArguments, property)); }
/// <summary> /// Translate a CountNode. /// </summary> /// <param name="nodeIn">The node to be translated.</param> /// <returns>The translated node.</returns> public override QueryNode Visit(CountNode nodeIn) { if (nodeIn == null) { throw Error.ArgumentNull(nameof(nodeIn)); } return(new CountNode((CollectionNode)nodeIn.Source.Accept(this))); }
public override QueryNode Visit(CountNode nodeIn) { CollectionNode?source = nodeIn.Source == null ? null : (CollectionNode)Visit(nodeIn.Source); if (nodeIn.Source != source) { nodeIn = new CountNode(source); } return(nodeIn); }
protected virtual QueryNode VisitCount(CountNode node, AzureQueryOptimizerState state) { QueryNode queryNode1 = this.Visit(node.SourceNode, state); QueryNode queryNode2 = this.Visit(node.PredicateNode, state); if (queryNode2.NodeType == QueryNodeType.MatchAll) { return((QueryNode) new CountNode(queryNode1, queryNode2, node.IsLongCount)); } return((QueryNode) new CountNode(this.VisitAnd(new AndNode(queryNode1, queryNode2), state), (QueryNode) new MatchAllNode(), node.IsLongCount)); }
protected virtual QueryNode VisitCount(CountNode node, ElasticSearchQueryOptimizerState state) { QueryNode node2 = Visit(node.SourceNode, state); QueryNode node3 = Visit(node.PredicateNode, state); if (node3.NodeType == QueryNodeType.MatchAll) { return(new CountNode(node2, node3, node.IsLongCount)); } return(new CountNode(VisitAnd(new AndNode(node2, node3), state), new MatchAllNode(), node.IsLongCount)); }
/// <summary> /// Writes CountNode. /// </summary> /// <param name="node">Node to write to string</param> /// <returns>String representation of node.</returns> private static string ToString(CountNode node) { if (node != null) { return(tabHelper.Prefix + "CountNode" + tabHelper.Indent(() => tabHelper.Prefix + "Source = " + ToString(node.Source) )); } return(String.Empty); }
/// <summary> /// Visit a CountNode /// </summary> /// <param name="nodeIn">The node to visit</param> /// <returns>The translated expression</returns> public override Expression Visit(CountNode nodeIn) { this.CheckArgumentNull(nodeIn, "CountNode"); Type propType = null; Expression propExpr = null; // Element of collection could be primitive type or enum or complex or entity type if (nodeIn.Source.ItemType.IsPrimitive() || nodeIn.Source.ItemType.IsEnum()) { var collection = (CollectionPropertyAccessNode)nodeIn.Source; propExpr = Visit(collection); var def = collection.Property.Type.AsCollection(); propType = EdmClrTypeUtils.GetInstanceType(def.ElementType()); } else if ((nodeIn.Source.ItemType.IsComplex() && nodeIn.Source.Kind.Equals(QueryNodeKind.CollectionComplexNode))) { // This does not handle complex collection cast case, if it is a complex collection cast, the Kind will be CollectionComplexCast and node.Source is CollectionComplexCastNode var collection = (CollectionComplexNode)nodeIn.Source; propExpr = Visit(collection); var def = collection.Property.Type.AsCollection(); propType = EdmClrTypeUtils.GetInstanceType(def.ElementType()); } else if (nodeIn.Source.ItemType.IsEntity() && nodeIn.Source.Kind.Equals(QueryNodeKind.CollectionNavigationNode)) { // This does not handle entity collection cast case, if it is a entity collection cast, the Kind will be CollectionResourceCast and node.Source is CollectionResourceCastNode var collection = (CollectionNavigationNode)nodeIn.Source; propExpr = Visit(collection); var def = collection.NavigationProperty.Type.AsCollection(); propType = EdmClrTypeUtils.GetInstanceType(def.ElementType()); } else { // Should no such case as collection item is either primitive or enum or complex or entity. throw new NotSupportedException( string.Format( "Filter based on count of collection with item of type {0} is not supported yet.", nodeIn.Source.ItemType)); } // Per standard, collection can not be null, but could be an empty collection, so null is not considered here. var asQuerableMethod = _queryableAsQueryableMethod.MakeGenericMethod(propType); Expression asQuerableExpression = Expression.Call(null, asQuerableMethod, propExpr); var countMethod = _countMethod.MakeGenericMethod(propType); var countExpression = Expression.Call(null, countMethod, asQuerableExpression); return(countExpression); }
/// <summary> /// Override this method to restrict the '$count' inside the filter query. /// </summary> /// <param name="countNode">The count node to validate.</param> /// <param name="settings">The validation settings.</param> protected virtual void ValidateCountNode(CountNode countNode, ODataValidationSettings settings) { Contract.Assert(countNode != null); Contract.Assert(settings != null); ValidateQueryNode(countNode.Source, settings); if (countNode.FilterClause != null) { ValidateQueryNode(countNode.FilterClause.Expression, settings); } if (countNode.SearchClause != null) { ValidateQueryNode(countNode.SearchClause.Expression, settings); } }
/// <summary> /// Translates a <see cref="CountNode"/> into a corresponding <see cref="String"/>. /// </summary> /// <param name="node">The node to translate.</param> /// <returns>The translated String.</returns> public override String Visit(CountNode node) { ExceptionUtils.CheckArgumentNotNull(node, "node"); String source = this.TranslateNode(node.Source); source = string.Concat(source, ExpressionConstants.SymbolForwardSlash, UriQueryConstants.CountSegment); if (node.FilterOption != null) { source = string.Concat( source, ExpressionConstants.SymbolOpenParen, UriQueryConstants.FilterQueryOption, ExpressionConstants.SymbolEqual, this.TranslateNode(node.FilterOption.Expression), ExpressionConstants.SymbolClosedParen); } return(source); }
/// <summary> /// Initializes a new instance of the <see cref="OrderByPropertyNode"/> class. /// </summary> /// <param name="orderByClause">The orderby clause representing property access.</param> public OrderByCountNode(OrderByClause orderByClause) : base(orderByClause) { if (orderByClause == null) { throw Error.ArgumentNull("orderByClause"); } OrderByClause = orderByClause; Direction = orderByClause.Direction; CountNode propertyExpression = orderByClause.Expression as CountNode; if (propertyExpression == null) { throw new ODataException(SRResources.OrderByClauseNotSupported); } else { Property = (propertyExpression.Source as CollectionNavigationNode).NavigationProperty; } }
private Expression BindCountNode(CountNode node) { Expression source = Bind(node.Source); Expression countExpression = Expression.Constant(null, typeof(long?)); Type elementType; if (!TypeHelper.IsCollection(source.Type, out elementType)) { return(countExpression); } MethodInfo countMethod; if (typeof(IQueryable).IsAssignableFrom(source.Type)) { countMethod = ExpressionHelperMethods.QueryableCountGeneric.MakeGenericMethod(elementType); } else { countMethod = ExpressionHelperMethods.EnumerableCountGeneric.MakeGenericMethod(elementType); } // call Count() method. countExpression = Expression.Call(null, countMethod, new[] { source }); if (QuerySettings.HandleNullPropagation == HandleNullPropagationOption.True) { // source == null ? null : countExpression return(Expression.Condition( test: Expression.Equal(source, Expression.Constant(null)), ifTrue: Expression.Constant(null, typeof(long?)), ifFalse: ExpressionHelpers.ToNullable(countExpression))); } else { return(countExpression); } }
/// <summary> /// Override this method to restrict the '$count' inside the filter query. /// </summary> /// <param name="countNode"></param> /// <param name="settings"></param> public virtual void ValidateCountNode(CountNode countNode, ODataValidationSettings settings) { if (countNode == null) { throw Error.ArgumentNull("countNode"); } if (settings == null) { throw Error.ArgumentNull("settings"); } ValidateQueryNode(countNode.Source, settings); if (countNode.FilterClause != null) { ValidateQueryNode(countNode.FilterClause.Expression, settings); } if (countNode.SearchClause != null) { ValidateQueryNode(countNode.SearchClause.Expression, settings); } }
public override QueryNode Visit(CountNode nodeIn) { nodeIn.Source.Accept(this); return(nodeIn); }
/// <summary> /// Translate a CountNode. /// </summary> /// <param name="nodeIn">The node to be translated.</param> /// <returns>The translated node.</returns> public override QueryNode Visit(CountNode nodeIn) { return(new CountNode((CollectionNode)nodeIn.Source.Accept(this))); }
/// <summary> /// Visit a CountNode /// </summary> /// <param name="nodeIn">the node to visit</param> /// <returns>Defined by the implementer</returns> public virtual T Visit(CountNode nodeIn) { throw new NotImplementedException(); }
/// <summary> /// Translate a CountNode. /// </summary> /// <param name="nodeIn">The node to be translated.</param> /// <returns>The translated node.</returns> public override QueryNode Visit(CountNode nodeIn) { Contract.Assert(nodeIn != null); return(new CountNode((CollectionNode)nodeIn.Source.Accept(this))); }
private bool Visit(CountNode node1, CountNode node2) { return(node1.TypeReference.IsEqual(node2.TypeReference) && Compare(node1.Source, node2.Source)); }
/// <summary> /// Translate a CountNode. /// </summary> /// <param name="nodeIn">The node to be translated.</param> /// <returns>The translated node.</returns> public override QueryNode Visit(CountNode nodeIn) { return(new CountNode((CollectionNode)nodeIn.Source.Accept(this), nodeIn.FilterClause, nodeIn.SearchClause)); }
public override T Visit(CountNode nodeIn) { SkipDebuggerBreak(nodeIn); /* nodeIn.Source.Accept(this); */ return(Visited); }
public override int Visit(CountNode nodeIn) { var sourceNode = (CollectionNavigationNode)nodeIn.Source; return(sourceNode.NavigationProperty.Name.GetHashCode()); }
public override object Visit(CountNode nodeIn) { return(null); }
private Expression BindCountNode(CountNode node) { Expression source = Bind(node.Source); Expression countExpression = Expression.Constant(null, typeof(long?)); Type elementType; if (!TypeHelper.IsCollection(source.Type, out elementType)) { return(countExpression); } MethodInfo countMethod; if (typeof(IQueryable).IsAssignableFrom(source.Type)) { countMethod = ExpressionHelperMethods.QueryableCountGeneric.MakeGenericMethod(elementType); } else { countMethod = ExpressionHelperMethods.EnumerableCountGeneric.MakeGenericMethod(elementType); } MethodInfo whereMethod; if (typeof(IQueryable).IsAssignableFrom(source.Type)) { whereMethod = ExpressionHelperMethods.QueryableWhereGeneric.MakeGenericMethod(elementType); } else { whereMethod = ExpressionHelperMethods.EnumerableWhereGeneric.MakeGenericMethod(elementType); } // Bind the inner $filter clause within the $count segment. // e.g Books?$filter=Authors/$count($filter=Id gt 1) gt 1 Expression filterExpression = null; if (node.FilterClause != null) { filterExpression = BindFilterClause(this, node.FilterClause, elementType); // The source expression looks like: $it.Authors // So the generated source expression below will look like: $it.Authors.Where($it => $it.Id > 1) source = Expression.Call(null, whereMethod, new[] { source, filterExpression }); } // append LongCount() method. // The final countExpression with the nested $filter clause will look like: $it.Authors.Where($it => $it.Id > 1).LongCount() // The final countExpression without the nested $filter clause will look like: $it.Authors.LongCount() countExpression = Expression.Call(null, countMethod, new[] { source }); if (QuerySettings.HandleNullPropagation == HandleNullPropagationOption.True) { // source == null ? null : countExpression return(Expression.Condition( test: Expression.Equal(source, Expression.Constant(null)), ifTrue: Expression.Constant(null, typeof(long?)), ifFalse: ExpressionHelpers.ToNullable(countExpression))); } else { return(countExpression); } }
/// <summary> /// Visit a CountNode /// </summary> /// <param name="nodeIn">the node to visit</param> /// <returns>true, indicating that the node has been visited.</returns> public override bool Visit(CountNode nodeIn) { validate(nodeIn); return(true); }
protected virtual void StripCount(CountNode node, HashSet <QueryMethod> additionalQueryMethods) { additionalQueryMethods.Add(new CountMethod(node.IsLongCount)); }