Skip to content

Commit

Permalink
Add $compute query option class
Browse files Browse the repository at this point in the history
  • Loading branch information
xuzhg committed Dec 14, 2021
1 parent 43ada8b commit 970484b
Show file tree
Hide file tree
Showing 11 changed files with 357 additions and 9 deletions.
51 changes: 51 additions & 0 deletions src/Microsoft.AspNetCore.OData/Microsoft.AspNetCore.OData.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7639,6 +7639,11 @@
A value that corresponds to allowing the $apply query option.
</summary>
</member>
<member name="F:Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Compute">
<summary>
A value that corresponds to allowing the $compute query option.
</summary>
</member>
<member name="F:Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Supported">
<summary>
A value that corresponds to the default query options supported.
Expand Down Expand Up @@ -9704,6 +9709,11 @@
Gets the <see cref="T:Microsoft.AspNetCore.OData.Query.ApplyQueryOption"/>.
</summary>
</member>
<member name="P:Microsoft.AspNetCore.OData.Query.ODataQueryOptions.Compute">
<summary>
Gets the <see cref="T:Microsoft.AspNetCore.OData.Query.ComputeQueryOption"/>.
</summary>
</member>
<member name="P:Microsoft.AspNetCore.OData.Query.ODataQueryOptions.Filter">
<summary>
Gets the <see cref="T:Microsoft.AspNetCore.OData.Query.FilterQueryOption"/>.
Expand Down Expand Up @@ -10343,6 +10353,42 @@
<param name="querySettings">The <see cref="T:Microsoft.AspNetCore.OData.Query.ODataQuerySettings"/> that contains all the query application related settings.</param>
<returns>The new <see cref="T:System.Linq.IQueryable"/> after the filter query has been applied to.</returns>
</member>
<member name="T:Microsoft.AspNetCore.OData.Query.ComputeQueryOption">
<summary>
This defines a $compute OData query option for querying.
The $compute system query option allows clients to define computed properties that can be used in a $select or within a $filter or $orderby expression.
Computed properties SHOULD be included as dynamic properties in the result and MUST be included if $select is specified with the computed property name, or star (*).
</summary>
</member>
<member name="M:Microsoft.AspNetCore.OData.Query.ComputeQueryOption.#ctor(System.String,Microsoft.AspNetCore.OData.Query.ODataQueryContext,Microsoft.OData.UriParser.ODataQueryOptionParser)">
<summary>
Initialize a new instance of <see cref="T:Microsoft.AspNetCore.OData.Query.ComputeQueryOption"/> based on the raw $compute value and
an EdmModel from <see cref="T:Microsoft.AspNetCore.OData.Query.ODataQueryContext"/>.
</summary>
<param name="rawValue">The raw value for $filter query. It can be null or empty.</param>
<param name="context">The <see cref="T:Microsoft.AspNetCore.OData.Query.ODataQueryContext"/> which contains the <see cref="T:Microsoft.OData.Edm.IEdmModel"/> and some type information</param>
<param name="queryOptionParser">The <see cref="T:Microsoft.OData.UriParser.ODataQueryOptionParser"/> which is used to parse the query option.</param>
</member>
<member name="P:Microsoft.AspNetCore.OData.Query.ComputeQueryOption.Context">
<summary>
Gets the given <see cref="T:Microsoft.AspNetCore.OData.Query.ODataQueryContext"/>.
</summary>
</member>
<member name="P:Microsoft.AspNetCore.OData.Query.ComputeQueryOption.ResultClrType">
<summary>
ClrType for result of transformations
</summary>
</member>
<member name="P:Microsoft.AspNetCore.OData.Query.ComputeQueryOption.ComputeClause">
<summary>
Gets the parsed <see cref="P:Microsoft.AspNetCore.OData.Query.ComputeQueryOption.ComputeClause"/> for this query option.
</summary>
</member>
<member name="P:Microsoft.AspNetCore.OData.Query.ComputeQueryOption.RawValue">
<summary>
Gets the raw $compute value.
</summary>
</member>
<member name="T:Microsoft.AspNetCore.OData.Query.CountQueryOption">
<summary>
Represents the value of the $count query option and exposes a way to retrieve the number of entities that satisfy a query.
Expand Down Expand Up @@ -10546,6 +10592,11 @@
Gets the raw $apply query value from the incoming request Uri if exists.
</summary>
</member>
<member name="P:Microsoft.AspNetCore.OData.Query.ODataRawQueryOptions.Compute">
<summary>
Gets the raw $compute query value from the incoming request Uri if exists.
</summary>
</member>
<member name="P:Microsoft.AspNetCore.OData.Query.ODataRawQueryOptions.OrderBy">
<summary>
Gets the raw $orderby query value from the incoming request Uri if exists.
Expand Down
11 changes: 10 additions & 1 deletion src/Microsoft.AspNetCore.OData/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,7 @@ Microsoft.AspNetCore.OData.Query.AllowedLogicalOperators.Or = 1 -> Microsoft.Asp
Microsoft.AspNetCore.OData.Query.AllowedQueryOptions
Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.All = Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.DeltaToken | Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Supported -> Microsoft.AspNetCore.OData.Query.AllowedQueryOptions
Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Apply = 1024 -> Microsoft.AspNetCore.OData.Query.AllowedQueryOptions
Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Compute = 2048 -> Microsoft.AspNetCore.OData.Query.AllowedQueryOptions
Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Count = 64 -> Microsoft.AspNetCore.OData.Query.AllowedQueryOptions
Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.DeltaToken = 512 -> Microsoft.AspNetCore.OData.Query.AllowedQueryOptions
Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Expand = 2 -> Microsoft.AspNetCore.OData.Query.AllowedQueryOptions
Expand All @@ -744,7 +745,7 @@ Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.OrderBy = 8 -> Microsoft.As
Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Select = 4 -> Microsoft.AspNetCore.OData.Query.AllowedQueryOptions
Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Skip = 32 -> Microsoft.AspNetCore.OData.Query.AllowedQueryOptions
Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.SkipToken = 256 -> Microsoft.AspNetCore.OData.Query.AllowedQueryOptions
Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Supported = Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Filter | Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Expand | Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Select | Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.OrderBy | Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Top | Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Skip | Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Count | Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Format | Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.SkipToken | Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Apply -> Microsoft.AspNetCore.OData.Query.AllowedQueryOptions
Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Supported = Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Filter | Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Expand | Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Select | Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.OrderBy | Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Top | Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Skip | Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Count | Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Format | Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.SkipToken | Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Apply | Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Compute -> Microsoft.AspNetCore.OData.Query.AllowedQueryOptions
Microsoft.AspNetCore.OData.Query.AllowedQueryOptions.Top = 16 -> Microsoft.AspNetCore.OData.Query.AllowedQueryOptions
Microsoft.AspNetCore.OData.Query.ApplyQueryOption
Microsoft.AspNetCore.OData.Query.ApplyQueryOption.ApplyClause.get -> Microsoft.OData.UriParser.Aggregation.ApplyClause
Expand All @@ -753,6 +754,12 @@ Microsoft.AspNetCore.OData.Query.ApplyQueryOption.ApplyTo(System.Linq.IQueryable
Microsoft.AspNetCore.OData.Query.ApplyQueryOption.Context.get -> Microsoft.AspNetCore.OData.Query.ODataQueryContext
Microsoft.AspNetCore.OData.Query.ApplyQueryOption.RawValue.get -> string
Microsoft.AspNetCore.OData.Query.ApplyQueryOption.ResultClrType.get -> System.Type
Microsoft.AspNetCore.OData.Query.ComputeQueryOption
Microsoft.AspNetCore.OData.Query.ComputeQueryOption.ComputeClause.get -> Microsoft.OData.UriParser.ComputeClause
Microsoft.AspNetCore.OData.Query.ComputeQueryOption.ComputeQueryOption(string rawValue, Microsoft.AspNetCore.OData.Query.ODataQueryContext context, Microsoft.OData.UriParser.ODataQueryOptionParser queryOptionParser) -> void
Microsoft.AspNetCore.OData.Query.ComputeQueryOption.Context.get -> Microsoft.AspNetCore.OData.Query.ODataQueryContext
Microsoft.AspNetCore.OData.Query.ComputeQueryOption.RawValue.get -> string
Microsoft.AspNetCore.OData.Query.ComputeQueryOption.ResultClrType.get -> System.Type
Microsoft.AspNetCore.OData.Query.Container.IPropertyMapper
Microsoft.AspNetCore.OData.Query.Container.IPropertyMapper.MapProperty(string propertyName) -> string
Microsoft.AspNetCore.OData.Query.Container.ITruncatedCollection
Expand Down Expand Up @@ -922,6 +929,7 @@ Microsoft.AspNetCore.OData.Query.ODataQueryContext.Path.get -> Microsoft.OData.U
Microsoft.AspNetCore.OData.Query.ODataQueryContext.RequestContainer.get -> System.IServiceProvider
Microsoft.AspNetCore.OData.Query.ODataQueryOptions
Microsoft.AspNetCore.OData.Query.ODataQueryOptions.Apply.get -> Microsoft.AspNetCore.OData.Query.ApplyQueryOption
Microsoft.AspNetCore.OData.Query.ODataQueryOptions.Compute.get -> Microsoft.AspNetCore.OData.Query.ComputeQueryOption
Microsoft.AspNetCore.OData.Query.ODataQueryOptions.Context.get -> Microsoft.AspNetCore.OData.Query.ODataQueryContext
Microsoft.AspNetCore.OData.Query.ODataQueryOptions.Count.get -> Microsoft.AspNetCore.OData.Query.CountQueryOption
Microsoft.AspNetCore.OData.Query.ODataQueryOptions.Filter.get -> Microsoft.AspNetCore.OData.Query.FilterQueryOption
Expand Down Expand Up @@ -963,6 +971,7 @@ Microsoft.AspNetCore.OData.Query.ODataQuerySettings.TimeZone.get -> System.TimeZ
Microsoft.AspNetCore.OData.Query.ODataQuerySettings.TimeZone.set -> void
Microsoft.AspNetCore.OData.Query.ODataRawQueryOptions
Microsoft.AspNetCore.OData.Query.ODataRawQueryOptions.Apply.get -> string
Microsoft.AspNetCore.OData.Query.ODataRawQueryOptions.Compute.get -> string
Microsoft.AspNetCore.OData.Query.ODataRawQueryOptions.Count.get -> string
Microsoft.AspNetCore.OData.Query.ODataRawQueryOptions.DeltaToken.get -> string
Microsoft.AspNetCore.OData.Query.ODataRawQueryOptions.Expand.get -> string
Expand Down
9 changes: 7 additions & 2 deletions src/Microsoft.AspNetCore.OData/Query/AllowedQueryOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,19 @@ public enum AllowedQueryOptions
/// </summary>
Apply = 0x400,

/// <summary>
/// A value that corresponds to allowing the $compute query option.
/// </summary>
Compute = 0x800,

/// <summary>
/// A value that corresponds to the default query options supported.
/// </summary>
Supported = Filter | OrderBy | Top | Skip | SkipToken | Count | Select | Expand | Format | Apply,
Supported = Filter | OrderBy | Top | Skip | SkipToken | Count | Select | Expand | Format | Apply | Compute,

/// <summary>
/// A value that corresponds to allowing all query options.
/// </summary>
All = Filter | Expand | Select | OrderBy | Top | Skip | Count | Format | SkipToken | DeltaToken | Apply
All = Filter | Expand | Select | OrderBy | Top | Skip | Count | Format | SkipToken | DeltaToken | Apply | Compute
}
}
10 changes: 10 additions & 0 deletions src/Microsoft.AspNetCore.OData/Query/ODataQueryOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ public ODataQueryOptions(ODataQueryContext context, HttpRequest request)
/// </summary>
public ApplyQueryOption Apply { get; private set; }

/// <summary>
/// Gets the <see cref="ComputeQueryOption"/>.
/// </summary>
public ComputeQueryOption Compute { get; private set; }

/// <summary>
/// Gets the <see cref="FilterQueryOption"/>.
/// </summary>
Expand Down Expand Up @@ -973,6 +978,11 @@ private void BuildQueryOptions(IDictionary<string, string> queryParameters)
RawValues.Apply = kvp.Value;
Apply = new ApplyQueryOption(kvp.Value, Context, _queryOptionParser);
break;
case "$compute":
ThrowIfEmpty(kvp.Value, "$compute");
RawValues.Compute = kvp.Value;
Compute = new ComputeQueryOption(kvp.Value, Context, _queryOptionParser);
break;
default:
// we don't throw if we can't recognize the query
break;
Expand Down
110 changes: 110 additions & 0 deletions src/Microsoft.AspNetCore.OData/Query/Query/ComputeQueryOption.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
//-----------------------------------------------------------------------------
// <copyright file="ComputeQueryOption.cs" company=".NET Foundation">
// Copyright (c) .NET Foundation and Contributors. All rights reserved.
// See License.txt in the project root for license information.
// </copyright>
//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using Microsoft.OData.Edm;
using Microsoft.OData.UriParser;

namespace Microsoft.AspNetCore.OData.Query
{
/// <summary>
/// This defines a $compute OData query option for querying.
/// The $compute system query option allows clients to define computed properties that can be used in a $select or within a $filter or $orderby expression.
/// Computed properties SHOULD be included as dynamic properties in the result and MUST be included if $select is specified with the computed property name, or star (*).
/// </summary>
public class ComputeQueryOption
{
private ComputeClause _computeClause;
private ODataQueryOptionParser _queryOptionParser;

/// <summary>
/// Initialize a new instance of <see cref="ComputeQueryOption"/> based on the raw $compute value and
/// an EdmModel from <see cref="ODataQueryContext"/>.
/// </summary>
/// <param name="rawValue">The raw value for $filter query. It can be null or empty.</param>
/// <param name="context">The <see cref="ODataQueryContext"/> which contains the <see cref="IEdmModel"/> and some type information</param>
/// <param name="queryOptionParser">The <see cref="ODataQueryOptionParser"/> which is used to parse the query option.</param>
public ComputeQueryOption(string rawValue, ODataQueryContext context, ODataQueryOptionParser queryOptionParser)
{
if (string.IsNullOrEmpty(rawValue))
{
throw Error.ArgumentNullOrEmpty(nameof(rawValue));
}

if (context == null)
{
throw Error.ArgumentNull(nameof(context));
}

if (queryOptionParser == null)
{
throw Error.ArgumentNull(nameof(queryOptionParser));
}

Context = context;
RawValue = rawValue;
_queryOptionParser = queryOptionParser;
ResultClrType = Context.ElementClrType;
}

// This constructor is intended for unit testing only.
internal ComputeQueryOption(string rawValue, ODataQueryContext context)
{
if (string.IsNullOrEmpty(rawValue))
{
throw Error.ArgumentNullOrEmpty(nameof(rawValue));
}

if (context == null)
{
throw Error.ArgumentNull(nameof(context));
}

Context = context;
RawValue = rawValue;

_queryOptionParser = new ODataQueryOptionParser(
context.Model,
context.ElementType,
context.NavigationSource,
new Dictionary<string, string> { { "$compute", rawValue } },
context.RequestContainer);
}

/// <summary>
/// Gets the given <see cref="ODataQueryContext"/>.
/// </summary>
public ODataQueryContext Context { get; }

/// <summary>
/// ClrType for result of transformations
/// </summary>
public Type ResultClrType { get; }

/// <summary>
/// Gets the parsed <see cref="ComputeClause"/> for this query option.
/// </summary>
public ComputeClause ComputeClause
{
get
{
if (_computeClause == null)
{
_computeClause = _queryOptionParser.ParseCompute();
}

return _computeClause;
}
}

/// <summary>
/// Gets the raw $compute value.
/// </summary>
public string RawValue { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ public class ODataRawQueryOptions
/// </summary>
public string Apply { get; internal set; }

/// <summary>
/// Gets the raw $compute query value from the incoming request Uri if exists.
/// </summary>
public string Compute { get; internal set; }

/// <summary>
/// Gets the raw $orderby query value from the incoming request Uri if exists.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ public virtual void Validate(ODataQueryOptions options, ODataValidationSettings
}

// Validate each query options
if (options.Compute != null)
{
if (options.Compute.ComputeClause != null)
{
ValidateQueryOptionAllowed(AllowedQueryOptions.Compute, validationSettings.AllowedQueryOptions);
}
}

if (options.Apply != null)
{
if (options.Apply.ApplyClause != null)
Expand Down
Loading

0 comments on commit 970484b

Please sign in to comment.