public static Expression Bind(FilterQueryNode filterNode, Type filterType, IEdmModel model, bool handleNullPropagation) { if (filterNode == null) { throw Error.ArgumentNull("filterNode"); } if (filterType == null) { throw Error.ArgumentNull("filterType"); } if (model == null) { throw Error.ArgumentNull("model"); } FilterBinder binder = new FilterBinder(model, handleNullPropagation); Expression filter = binder.BindFilterQueryNode(filterNode); Type expectedFilterType = typeof(Func <,>).MakeGenericType(filterType, typeof(bool)); if (filter.Type != expectedFilterType) { throw Error.InvalidOperation(SRResources.CannotCastFilter, filter.Type.FullName, expectedFilterType.FullName); } return(filter); }
public static Expression Bind(FilterQueryNode filterNode, Type filterType, IEdmModel model, IAssembliesResolver assembliesResolver, ODataQuerySettings querySettings) { if (filterNode == null) { throw Error.ArgumentNull("filterNode"); } if (filterType == null) { throw Error.ArgumentNull("filterType"); } if (model == null) { throw Error.ArgumentNull("model"); } if (assembliesResolver == null) { throw Error.ArgumentNull("assembliesResolver"); } FilterBinder binder = new FilterBinder(model, assembliesResolver, querySettings); Expression filter = binder.BindFilterQueryNode(filterNode); Type expectedFilterType = typeof(Func <,>).MakeGenericType(filterType, typeof(bool)); if (filter.Type != expectedFilterType) { throw Error.InvalidOperation(SRResources.CannotCastFilter, filter.Type.FullName, expectedFilterType.FullName); } return(filter); }
private Expression BindFilterQueryNode(FilterQueryNode filterNode) { Type filterType = EdmLibHelpers.GetClrType(filterNode.ItemType, _model, _assembliesResolver); ParameterExpression filterParameter = Expression.Parameter(filterType, filterNode.Parameter.Name); _lambdaParameters = new Dictionary <string, ParameterExpression>(); _lambdaParameters.Add(filterNode.Parameter.Name, filterParameter); Expression body = Bind(filterNode.Expression); body = ApplyNullPropagationForFilterBody(body); Expression filterExpression = Expression.Lambda(body, filterParameter); if (_parametersStack.Count != 0) { _lambdaParameters = _parametersStack.Pop(); } else { _lambdaParameters = null; } return(filterExpression); }
/// <summary> /// Apply the filter query to the given IQueryable. /// </summary> /// <remarks> /// The <see cref="ODataQuerySettings.HandleNullPropagation"/> property specifies /// how this method should handle null propagation. /// </remarks> /// <param name="query">The IQueryable that we are applying filter query against.</param> /// <param name="querySettings">Specifies if we need to handle null propagation. Pass false if the underlying query provider handles null propagation. Otherwise pass true.</param> /// <param name="assembliesResolver">The <see cref="IAssembliesResolver"/> to use.</param> /// <returns>The query that the filter query has been applied to.</returns> public IQueryable ApplyTo(IQueryable query, ODataQuerySettings querySettings, IAssembliesResolver assembliesResolver) { if (query == null) { throw Error.ArgumentNull("query"); } if (querySettings == null) { throw Error.ArgumentNull("querySettings"); } if (assembliesResolver == null) { throw Error.ArgumentNull("assembliesResolver"); } FilterQueryNode node = QueryNode; Contract.Assert(node != null); Expression filter = FilterBinder.Bind(node, Context.EntityClrType, Context.Model, assembliesResolver, querySettings); query = ExpressionHelpers.Where(query, filter, Context.EntityClrType); return(query); }
/// <summary> /// Apply the filter query to the given IQueryable. /// </summary> /// <param name="query">The IQueryable that we are applying filter query against.</param> /// <param name="handleNullPropagation">Specifies if we need to handle null propagation. Pass false if the underlying query provider handles null propagation. Otherwise pass true.</param> /// <returns>The query that the filter query has been applied to.</returns> public IQueryable ApplyTo(IQueryable query, bool handleNullPropagation) { FilterQueryNode node = QueryNode; Contract.Assert(node != null); Expression filter = FilterBinder.Bind(node, Context.EntityClrType, Context.Model, handleNullPropagation); query = ExpressionHelpers.Where(query, filter, Context.EntityClrType); return(query); }
/// <summary> /// Processes the filter of the query (if any). /// </summary> /// <param name="query">The query tree constructed so far.</param> /// <param name="filter">The filter to bind.</param> /// <returns>If no filter is specified, returns the <paramref name="query"/> unchanged. If a filter is specified it returns the combined query including the filter.</returns> private QueryNode ProcessFilter(QueryNode query, QueryToken filter) { ExceptionUtils.CheckArgumentNotNull(query, "query"); if (filter != null) { CollectionQueryNode entityCollection = query.AsEntityCollectionNode(); if (entityCollection == null) { throw new ODataException(Strings.MetadataBinder_FilterNotApplicable); } this.parameter = new ParameterQueryNode() { ParameterType = entityCollection.ItemType }; QueryNode expressionNode = this.Bind(filter); SingleValueQueryNode expressionResultNode = expressionNode as SingleValueQueryNode; if (expressionResultNode == null || (expressionResultNode.TypeReference != null && !expressionResultNode.TypeReference.IsODataPrimitiveTypeKind())) { throw new ODataException(Strings.MetadataBinder_FilterExpressionNotSingleValue); } // The type may be null here if the query statically represents the null literal // TODO: once we support open types/properties a 'null' type will mean 'we don't know the type'. Review. IEdmTypeReference expressionResultType = expressionResultNode.TypeReference; if (expressionResultType != null) { IEdmPrimitiveTypeReference primitiveExpressionResultType = expressionResultType.AsPrimitiveOrNull(); if (primitiveExpressionResultType == null || primitiveExpressionResultType.PrimitiveKind() != EdmPrimitiveTypeKind.Boolean) { throw new ODataException(Strings.MetadataBinder_FilterExpressionNotSingleValue); } } query = new FilterQueryNode() { Collection = entityCollection, Parameter = this.parameter, Expression = expressionResultNode }; this.parameter = null; } return query; }
public static Expression <Func <TEntityType, bool> > Bind <TEntityType>(FilterQueryNode filterNode, IEdmModel model, IAssembliesResolver assembliesResolver, ODataQuerySettings querySettings) { return(Bind(filterNode, typeof(TEntityType), model, assembliesResolver, querySettings) as Expression <Func <TEntityType, bool> >); }
/// <summary> /// Translates a filter node. /// </summary> /// <param name="filterNode">The filter node to translate.</param> /// <returns>Expression which evaluates to the result after the filter operation.</returns> protected virtual Expression TranslateFilter(FilterQueryNode filterNode) { ExceptionUtils.CheckArgumentNotNull(filterNode, "filterNode"); ExceptionUtils.CheckArgumentNotNull(filterNode.ItemType, "filterNode.ItemType"); ExceptionUtils.CheckArgumentNotNull(filterNode.Collection, "filterNode.Collection"); ExceptionUtils.CheckArgumentNotNull(filterNode.Collection.ItemType, "filterNode.Collection.ItemType"); ExceptionUtils.CheckArgumentNotNull(filterNode.Expression, "filterNode.Expression"); ExceptionUtils.CheckArgumentNotNull(filterNode.Parameter, "filterNode.Parameter"); ExceptionUtils.CheckArgumentNotNull(filterNode.Parameter.TypeReference, "filterNode.Parameter.Type"); ParameterExpression parameter = Expression.Parameter(filterNode.Parameter.TypeReference.GetInstanceType(this.model), "it"); Expression collectionExpression = this.Translate(filterNode.Collection); // TODO: If we should support Filter 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_FilterCollectionOfWrongType(collectionExpression.Type, expectedCollectionType)); } this.parameterNodeDefinitions.Push(new KeyValuePair<ParameterQueryNode, Expression>(filterNode.Parameter, parameter)); Expression body = this.Translate(filterNode.Expression); Debug.Assert(this.parameterNodeDefinitions.Peek().Key == filterNode.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(); // TODO: Deal with open expressions if (body == nullLiteralExpression) { // lifting rules say that a null literal is interpreted as 'false' when treated as boolean. body = falseLiteralExpression; } else if (body.Type == typeof(bool?)) { Expression test = Expression.Equal(body, Expression.Constant(null, typeof(bool?))); body = Expression.Condition(test, falseLiteralExpression, Expression.Property(body, "Value")); } if (body.Type != typeof(bool)) { throw new ODataException(Strings.QueryExpressionTranslator_FilterExpressionOfWrongType(body.Type)); } return Expression.Call( typeof(Queryable), WhereMethodName, new Type[] { parameter.Type }, collectionExpression, Expression.Quote(Expression.Lambda(body, parameter))); }
private void ProcessFilter(FilterQueryNode filterQuery) { var filterSparqlExpression = ProcessNode(filterQuery.Expression); _sparqlModel.CurrentGraphPattern.AddFilterExpression(filterSparqlExpression.ToString()); }
/// <summary> /// Processes the filter of the query (if any). /// </summary> /// <param name="query">The query tree constructed so far.</param> /// <param name="filter">The filter to bind.</param> /// <returns>If no filter is specified, returns the <paramref name="query"/> unchanged. If a filter is specified it returns the combined query including the filter.</returns> private QueryNode ProcessFilter(QueryNode query, QueryToken filter) { ExceptionUtils.CheckArgumentNotNull(query, "query"); if (filter != null) { CollectionQueryNode entityCollection = query.AsEntityCollectionNode(); if (entityCollection == null) { throw new ODataException(Strings.MetadataBinder_FilterNotApplicable); } this.parameter = new ParameterQueryNode() { ParameterResourceType = entityCollection.ItemType }; QueryNode expressionNode = this.Bind(filter); SingleValueQueryNode expressionResultNode = expressionNode as SingleValueQueryNode; if (expressionResultNode == null || (expressionResultNode.ResourceType != null && expressionResultNode.ResourceType.ResourceTypeKind != ResourceTypeKind.Primitive)) { throw new ODataException(Strings.MetadataBinder_FilterExpressionNotSingleValue); } // The resource type may be null here if the query statically represents the null literal // TODO: once we support open types/properties a 'null' resource type will mean 'we don't know the type'. Review. if (expressionResultNode.ResourceType != null && !this.ResourceTypesEqual(expressionResultNode.ResourceType, PrimitiveTypeUtils.BoolResourceType) && !this.ResourceTypesEqual(expressionResultNode.ResourceType, PrimitiveTypeUtils.NullableBoolResourceType)) { throw new ODataException(Strings.MetadataBinder_FilterExpressionNotSingleValue); } query = new FilterQueryNode() { Collection = entityCollection, Parameter = this.parameter, Expression = expressionResultNode }; this.parameter = null; } return query; }
public static Expression <Func <TEntityType, bool> > Bind <TEntityType>(FilterQueryNode filterNode, IEdmModel model, bool handleNullPropagation) { return(Bind(filterNode, typeof(TEntityType), model, handleNullPropagation) as Expression <Func <TEntityType, bool> >); }
private void ProcessFilter(FilterQueryNode filterQuery) { var filterSparqlExpression = ProcessNode(filterQuery.Expression); _sparqlModel.CurrentGraphPattern.AddFilterExpression(filterSparqlExpression.ToString()); }