/// <summary> /// Parses a <paramref name="filter"/> clause on the given <paramref name="elementType"/>, binding /// the text into semantic nodes using the provided model. /// </summary> /// <param name="filter">String representation of the filter expression.</param> /// <param name="configuration">The configuration used for binding.</param> /// <param name="elementType">Type that the filter clause refers to.</param> /// <param name="navigationSource">Navigation source that the elements being filtered are from.</param> /// <returns>A <see cref="FilterClause"/> representing the metadata bound filter expression.</returns> private FilterClause ParseFilterImplementation(string filter, ODataUriParserConfiguration configuration, IEdmType elementType, IEdmNavigationSource navigationSource) { ExceptionUtils.CheckArgumentNotNull(configuration, "configuration"); ExceptionUtils.CheckArgumentNotNull(elementType, "elementType"); ExceptionUtils.CheckArgumentNotNull(filter, "filter"); // Get the syntactic representation of the filter expression UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(configuration.Settings.FilterLimit, configuration.EnableCaseInsensitiveUriFunctionIdentifier); QueryToken filterToken = expressionParser.ParseFilter(filter); // Bind it to metadata BindingState state = new BindingState(configuration); state.ImplicitRangeVariable = NodeFactory.CreateImplicitRangeVariable(elementType.ToTypeReference(), navigationSource); state.RangeVariables.Push(state.ImplicitRangeVariable); if (applyClause != null) { state.AggregatedPropertyNames = applyClause.GetLastAggregatedPropertyNames(); } MetadataBinder binder = new MetadataBinder(state); FilterBinder filterBinder = new FilterBinder(binder.Bind, state); FilterClause boundNode = filterBinder.BindFilter(filterToken); return(boundNode); }
public void ShouldCatchMissingColon() { var expressionParser = new UriQueryExpressionParser(800); try { var tok = expressionParser.ParseFilter("any(ol ol/SomeBool)"); } catch (ODataException ex) { Debug.Assert(ex.ToString().StartsWith("Microsoft.OData.Core.ODataException: ')' or ',' expected"),ex.ToString()); } }
public void ShouldHandleEmptyArgument() { var expressionParser = new UriQueryExpressionParser(800); var tok = expressionParser.ParseFilter("any()"); tok.Should().BeOfType<FunctionCallQueryToken>(); var anyTok = tok.As<FunctionCallQueryToken>(); anyTok.Kind.Should().Be(QueryTokenKind.FunctionCall); anyTok.Name.Should().Be("any"); anyTok.Arguments.Count().Should().Be(0); }
public void ShouldCatchMissingColon() { var expressionParser = new UriQueryExpressionParser(800); try { var tok = expressionParser.ParseFilter("any(ol ol/SomeBool)"); } catch (ODataException ex) { Debug.Assert(ex.ToString().StartsWith("Microsoft.OData.Core.ODataException: ')' or ',' expected"), ex.ToString()); } }
public void ShouldHandleEmptyArgument() { var expressionParser = new UriQueryExpressionParser(800); var tok = expressionParser.ParseFilter("any()"); tok.Should().BeOfType <FunctionCallQueryToken>(); var anyTok = tok.As <FunctionCallQueryToken>(); anyTok.Kind.Should().Be(QueryTokenKind.FunctionCall); anyTok.Name.Should().Be("any"); anyTok.Arguments.Count().Should().Be(0); }
public static IQueryable <T> Apply <T>(IQueryable <T> data, IEnumerable <PropertyInfo> properties, string parameter) { var parser = new UriQueryExpressionParser(10); var token = parser.ParseFilter(parameter); var param = Expression.Parameter(typeof(T)); var visitor = new ExpressionQueryTokenVisitor(param, properties); var expr = token.Accept(visitor); var lambda = Expression.Lambda <Func <T, bool> >(expr, param); return(data.AsQueryable().Where(lambda)); }
public void ShouldMapStructure() { var expressionParser = new UriQueryExpressionParser(800); var tok = expressionParser.ParseFilter("any(ol: ol/Ratings gt 42)"); tok.Should().BeOfType<FunctionCallQueryToken>(); var anyTok = tok.As<FunctionCallQueryToken>(); anyTok.Kind.Should().Be(QueryTokenKind.FunctionCall); anyTok.Name.Should().Be("any"); anyTok.Arguments.Count().Should().Be(2); anyTok.Arguments.ElementAt(0).As<PropertyAccessQueryToken>().Name.Should().Be("ol"); var binTok = anyTok.Arguments.ElementAt(1).As<BinaryOperatorQueryToken>(); binTok.OperatorKind.Should().Be(BinaryOperatorKind.GreaterThan); binTok.Left.As<PropertyAccessQueryToken>().Name.Should().Be("Ratings"); binTok.Left.As<PropertyAccessQueryToken>().Parent.As<PropertyAccessQueryToken>().Name.Should().Be("ol"); binTok.Right.As<LiteralQueryToken>().Value.Should().Be(42); }
/// <summary> /// Parses a <paramref name="query"/> clause on the given <paramref name="elementType"/>, binding /// the text into semantic nodes using the provided model. /// </summary> /// <param name="query">String representation of the filter expression.</param> /// <param name="configuration">The configuration used for binding.</param> /// <param name="elementType">Type that the filter clause refers to.</param> /// <param name="navigationSource">Navigation source that the elements being filtered are from.</param> /// <returns>A <see cref="FilterClause"/> representing the metadata bound filter expression.</returns> internal static ExpressionClause ParseExpressionImplementation(string query, ODataUriParserConfiguration configuration, IEdmType elementType, IEdmNavigationSource navigationSource) { ExceptionUtils.CheckArgumentNotNull(configuration, "configuration"); ExceptionUtils.CheckArgumentNotNull(elementType, "elementType"); ExceptionUtils.CheckArgumentNotNull(query, "query"); // Get the syntactic representation of the filter expression UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(configuration.Settings.FilterLimit); QueryToken expressionToken = expressionParser.ParseFilter(query); // Bind it to metadata BindingState state = new BindingState(configuration); state.ImplicitRangeVariable = NodeFactory.CreateImplicitRangeVariable(elementType.ToTypeReference(), navigationSource); state.RangeVariables.Push(state.ImplicitRangeVariable); MetadataBinder binder = new MetadataBinder(state); FilterBinder filterBinder = new FilterBinder(binder.Bind, state); ExpressionClause boundNode = filterBinder.BindProperyExpression(expressionToken); return(boundNode); }
public void ShouldMapStructure() { var expressionParser = new UriQueryExpressionParser(800); var tok = expressionParser.ParseFilter("any(ol: ol/Ratings gt 42)"); tok.Should().BeOfType <FunctionCallQueryToken>(); var anyTok = tok.As <FunctionCallQueryToken>(); anyTok.Kind.Should().Be(QueryTokenKind.FunctionCall); anyTok.Name.Should().Be("any"); anyTok.Arguments.Count().Should().Be(2); anyTok.Arguments.ElementAt(0).As <PropertyAccessQueryToken>().Name.Should().Be("ol"); var binTok = anyTok.Arguments.ElementAt(1).As <BinaryOperatorQueryToken>(); binTok.OperatorKind.Should().Be(BinaryOperatorKind.GreaterThan); binTok.Left.As <PropertyAccessQueryToken>().Name.Should().Be("Ratings"); binTok.Left.As <PropertyAccessQueryToken>().Parent.As <PropertyAccessQueryToken>().Name.Should().Be("ol"); binTok.Right.As <LiteralQueryToken>().Value.Should().Be(42); }
/// <summary> /// Parses the <paramref name="queryUri"/> and returns a new instance of <see cref="SyntacticTree"/> /// describing the query specified by the uri. /// </summary> /// <param name="queryUri">The absolute URI which holds the query to parse. This must be a path relative to the <paramref name="serviceBaseUri"/>.</param> /// <param name="serviceBaseUri">The base URI of the service.</param> /// <param name="maxDepth">The maximum depth of any single query part. Security setting to guard against DoS attacks causing stack overflows and such.</param> /// <returns>A new instance of <see cref="SyntacticTree"/> which represents the query specified in the <paramref name="queryUri"/>.</returns> public static SyntacticTree ParseUri(Uri queryUri, Uri serviceBaseUri, int maxDepth) { ExceptionUtils.CheckArgumentNotNull(queryUri, "queryUri"); if (!queryUri.IsAbsoluteUri) { throw new ArgumentException(Strings.SyntacticTree_UriMustBeAbsolute(queryUri), "queryUri"); } ExceptionUtils.CheckArgumentNotNull(serviceBaseUri, "serviceBaseUri"); if (!serviceBaseUri.IsAbsoluteUri) { throw new ArgumentException(Strings.SyntacticTree_UriMustBeAbsolute(serviceBaseUri), "serviceBaseUri"); } if (maxDepth <= 0) { throw new ArgumentException(Strings.SyntacticTree_MaxDepthInvalid, "maxDepth"); } UriPathParser pathParser = new UriPathParser(maxDepth); var path = pathParser.ParsePathIntoSegments(queryUri, serviceBaseUri); // COMPAT 32: Differencies in query options parsing in WCF DS // // We allow non-system $ query options in the lexical space. // We allow multiple instances of a custom or non-system $ query option in the lexical space. // TODO: we need to decide whether we want to allow multiple system $ query options with the same name (OIPI suggests that this is valid); we currently don't. List <CustomQueryOptionToken> queryOptions = UriUtils.ParseQueryOptions(queryUri); IDictionary <string, string> parameterAliases = queryOptions.GetParameterAliases(); QueryToken filter = null; string filterQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.FilterQueryOption); if (filterQuery != null) { UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(maxDepth); filter = expressionParser.ParseFilter(filterQuery); } IEnumerable <OrderByToken> orderByTokens = null; string orderByQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.OrderByQueryOption); if (orderByQuery != null) { UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(maxDepth); orderByTokens = expressionParser.ParseOrderBy(orderByQuery); } SelectToken select = null; string selectQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.SelectQueryOption); if (selectQuery != null) { SelectExpandParser selectParser = new SelectExpandParser(selectQuery, ODataUriParserSettings.DefaultSelectExpandLimit); select = selectParser.ParseSelect(); } ExpandToken expand = null; string expandQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.ExpandQueryOption); if (expandQuery != null) { SelectExpandParser expandParser = new SelectExpandParser(expandQuery, ODataUriParserSettings.DefaultSelectExpandLimit); expand = expandParser.ParseExpand(); } int? skip = null; string skipQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.SkipQueryOption); if (skipQuery != null) { int skipValue; if (!UriPrimitiveTypeParser.TryUriStringToNonNegativeInteger(skipQuery, out skipValue)) { throw new ODataException(Strings.SyntacticTree_InvalidSkipQueryOptionValue(skipQuery)); } skip = skipValue; } int? top = null; string topQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.TopQueryOption); if (topQuery != null) { int topValue; if (!UriPrimitiveTypeParser.TryUriStringToNonNegativeInteger(topQuery, out topValue)) { throw new ODataException(Strings.SyntacticTree_InvalidTopQueryOptionValue(topQuery)); } top = topValue; } string countQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.CountQueryOption); bool? count = ParseQueryCount(countQuery); string format = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.FormatQueryOption); return(new SyntacticTree( parameterAliases, path, filter, orderByTokens, select, expand, skip, top, count, format, queryOptions.Count == 0 ? null : new ReadOnlyCollection <CustomQueryOptionToken>(queryOptions))); }
/// <summary> /// Parses the <paramref name="queryUri"/> and returns a new instance of <see cref="SyntacticTree"/> /// describing the query specified by the uri. /// </summary> /// <param name="queryUri">The absolute URI which holds the query to parse. This must be a path relative to the <paramref name="serviceBaseUri"/>.</param> /// <param name="serviceBaseUri">The base URI of the service.</param> /// <param name="maxDepth">The maximum depth of any single query part. Security setting to guard against DoS attacks causing stack overflows and such.</param> /// <returns>A new instance of <see cref="SyntacticTree"/> which represents the query specified in the <paramref name="queryUri"/>.</returns> public static SyntacticTree ParseUri(Uri queryUri, Uri serviceBaseUri, int maxDepth) { ExceptionUtils.CheckArgumentNotNull(queryUri, "queryUri"); if (!queryUri.IsAbsoluteUri) { throw new ArgumentException(Strings.SyntacticTree_UriMustBeAbsolute(queryUri), "queryUri"); } ExceptionUtils.CheckArgumentNotNull(serviceBaseUri, "serviceBaseUri"); if (!serviceBaseUri.IsAbsoluteUri) { throw new ArgumentException(Strings.SyntacticTree_UriMustBeAbsolute(serviceBaseUri), "serviceBaseUri"); } if (maxDepth <= 0) { throw new ArgumentException(Strings.SyntacticTree_MaxDepthInvalid, "maxDepth"); } UriPathParser pathParser = new UriPathParser(maxDepth); var path = pathParser.ParsePathIntoSegments(queryUri, serviceBaseUri); List <CustomQueryOptionToken> queryOptions = UriUtils.ParseQueryOptions(queryUri); IDictionary <string, string> parameterAliases = queryOptions.GetParameterAliases(); QueryToken filter = null; string filterQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.FilterQueryOption); if (filterQuery != null) { UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(maxDepth); filter = expressionParser.ParseFilter(filterQuery); } IEnumerable <OrderByToken> orderByTokens = null; string orderByQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.OrderByQueryOption); if (orderByQuery != null) { UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(maxDepth); orderByTokens = expressionParser.ParseOrderBy(orderByQuery); } SelectToken select = null; string selectQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.SelectQueryOption); if (selectQuery != null) { SelectExpandParser selectParser = new SelectExpandParser(selectQuery, ODataUriParserSettings.DefaultSelectExpandLimit); select = selectParser.ParseSelect(); } ExpandToken expand = null; string expandQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.ExpandQueryOption); if (expandQuery != null) { SelectExpandParser expandParser = new SelectExpandParser(expandQuery, ODataUriParserSettings.DefaultSelectExpandLimit); expand = expandParser.ParseExpand(); } int? skip = null; string skipQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.SkipQueryOption); if (skipQuery != null) { int skipValue; if (!UriPrimitiveTypeParser.TryUriStringToNonNegativeInteger(skipQuery, out skipValue)) { throw new ODataException(Strings.SyntacticTree_InvalidSkipQueryOptionValue(skipQuery)); } skip = skipValue; } int? top = null; string topQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.TopQueryOption); if (topQuery != null) { int topValue; if (!UriPrimitiveTypeParser.TryUriStringToNonNegativeInteger(topQuery, out topValue)) { throw new ODataException(Strings.SyntacticTree_InvalidTopQueryOptionValue(topQuery)); } top = topValue; } string countQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.CountQueryOption); bool? count = QueryTokenUtils.ParseQueryCount(countQuery); string format = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.FormatQueryOption); return(new SyntacticTree( parameterAliases, path, filter, orderByTokens, select, expand, skip, top, count, format, queryOptions.Count == 0 ? null : new ReadOnlyCollection <CustomQueryOptionToken>(queryOptions))); }