From a9622c06db76e1364634b371044efd1ad656bc62 Mon Sep 17 00:00:00 2001 From: Luc Genetier <69138830+LucGenetier@users.noreply.github.com> Date: Tue, 9 Jul 2024 23:00:48 +0200 Subject: [PATCH] Add OrderBy (#2530) ODataParameters: Update OrderBy DelegationParameters: Add GetOrderBy() --- .../Obsolete/ODataParameters.cs | 24 +++---- .../Public/CdpTableValue.cs | 7 ++- .../Public/Values/DelegationParameters.cs | 56 +++++++++++++---- .../ODataParametersTests.cs | 63 +++++++++++++------ 4 files changed, 105 insertions(+), 45 deletions(-) diff --git a/src/libraries/Microsoft.PowerFx.Connectors/Obsolete/ODataParameters.cs b/src/libraries/Microsoft.PowerFx.Connectors/Obsolete/ODataParameters.cs index 727b6a017..e97254221 100644 --- a/src/libraries/Microsoft.PowerFx.Connectors/Obsolete/ODataParameters.cs +++ b/src/libraries/Microsoft.PowerFx.Connectors/Obsolete/ODataParameters.cs @@ -1,14 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -using System; using System.Collections.Generic; -using System.Collections.Specialized; -using System.Globalization; using System.Linq; using System.Text; -using System.Web; -using Microsoft.PowerFx.Types; +using System.Web; namespace Microsoft.PowerFx.Connectors { @@ -38,7 +34,7 @@ namespace Microsoft.PowerFx.Connectors public int Levels { get; init; } = 0; // $orderby - public string OrderBy { get; init; } = null; + public IList<(string, bool)> OrderBy { get; init; } = null; // $schemaversion public string SchemaVersion { get; init; } = null; @@ -113,7 +109,11 @@ namespace Microsoft.PowerFx.Connectors d2 = ","; } - } + } + else if (value is IList<(string col, bool asc)> orderByList && orderByList.Any()) + { + sb.Append(string.Join(",", orderByList.Select(x => $"{x.col}{(x.asc ? string.Empty : " desc")}"))); + } else { encoded = HttpUtility.UrlEncode(value.ToString()); @@ -160,17 +160,17 @@ namespace Microsoft.PowerFx.Connectors query["$format"] = Format; } - if (Index != 0) + if (Index > 0) { query["$index"] = Index; } - if (Levels != 0) + if (Levels > 0) { query["$levels"] = Levels; } - if (!string.IsNullOrEmpty(OrderBy)) + if (OrderBy != null && OrderBy.Any()) { query["$orderby"] = OrderBy; } @@ -190,12 +190,12 @@ namespace Microsoft.PowerFx.Connectors query["$select"] = Select; } - if (Skip != 0) + if (Skip > 0) { query["$skip"] = Skip; } - if (Top != 0) + if (Top > 0) { query["$top"] = Top; } diff --git a/src/libraries/Microsoft.PowerFx.Connectors/Public/CdpTableValue.cs b/src/libraries/Microsoft.PowerFx.Connectors/Public/CdpTableValue.cs index fa00de13a..fd2aa627d 100644 --- a/src/libraries/Microsoft.PowerFx.Connectors/Public/CdpTableValue.cs +++ b/src/libraries/Microsoft.PowerFx.Connectors/Public/CdpTableValue.cs @@ -76,14 +76,17 @@ namespace Microsoft.PowerFx.Connectors DelegationParameterFeatures allowedFeatures = DelegationParameterFeatures.Filter | DelegationParameterFeatures.Top | - DelegationParameterFeatures.Columns; + DelegationParameterFeatures.Columns | // $select + DelegationParameterFeatures.Sort; // $orderby + parameters.EnsureOnlyFeatures(allowedFeatures); ODataParameters op = new ODataParameters() { Filter = parameters.GetOdataFilter(), Top = parameters.Top.GetValueOrDefault(), - Select = parameters.GetColumns() + Select = parameters.GetColumns(), + OrderBy = parameters.GetOrderBy() }; return op; diff --git a/src/libraries/Microsoft.PowerFx.Core/Public/Values/DelegationParameters.cs b/src/libraries/Microsoft.PowerFx.Core/Public/Values/DelegationParameters.cs index 9bedbe6ce..d6a23d5dc 100644 --- a/src/libraries/Microsoft.PowerFx.Core/Public/Values/DelegationParameters.cs +++ b/src/libraries/Microsoft.PowerFx.Core/Public/Values/DelegationParameters.cs @@ -3,16 +3,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics.Contracts; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.PowerFx.Core.IR; -using Microsoft.PowerFx.Core.Localization; -using Microsoft.PowerFx.Core.Utils; -using Microsoft.PowerFx.Functions; namespace Microsoft.PowerFx.Types { @@ -44,6 +34,12 @@ namespace Microsoft.PowerFx.Types } } + /// + /// Returns the list of (column name, ascending/descending) where ascending=true. + /// + /// + public abstract IList<(string, bool)> GetOrderBy(); + public abstract string GetOdataFilter(); // 0 columns means return all columns. @@ -53,8 +49,6 @@ namespace Microsoft.PowerFx.Types } public int? Top { get; set; } - - // Other odata fetchers? } /// @@ -64,9 +58,47 @@ namespace Microsoft.PowerFx.Types [Flags] public enum DelegationParameterFeatures { + // $filter Filter = 1 << 0, + + // $top Top = 1 << 1, + + // $select Columns = 1 << 2, + + // $orderBy Sort = 1 << 3, + + /* + To be implemented later when needed + + // $compute + Compute = 1 << 4, + + // $count + Count = 1 << 5, + + // $expand + Expand = 1 << 6, + + // $format + Format = 1 << 7, + + // $index + Index = 1 << 8, + + // $levels + Levels = 1 << 9, + + // $schemaversion + SchemaVersion = 1 << 10, + + // $search + Search = 1 << 11, + + // $skip + Skip = 1 << 12 + */ } } diff --git a/src/tests/Microsoft.PowerFx.Connectors.Tests.Shared/ODataParametersTests.cs b/src/tests/Microsoft.PowerFx.Connectors.Tests.Shared/ODataParametersTests.cs index 2b23ddbf3..16f250f00 100644 --- a/src/tests/Microsoft.PowerFx.Connectors.Tests.Shared/ODataParametersTests.cs +++ b/src/tests/Microsoft.PowerFx.Connectors.Tests.Shared/ODataParametersTests.cs @@ -3,18 +3,9 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Operations; using Microsoft.PowerFx.Connectors; -using Microsoft.PowerFx.Connectors.Tests; -using Microsoft.PowerFx.Core.Tests; using Microsoft.PowerFx.Types; using Xunit; -using Xunit.Abstractions; namespace Microsoft.PowerFx.Tests { @@ -130,24 +121,58 @@ namespace Microsoft.PowerFx.Tests Assert.Equal("$filter=score+gt+5&$top=10", str); } + [Fact] + public void TestToOdataParametersFilterTopOrderByAsc() + { + var delegation = new TestDelegationParameters() + { + _columns = null, + _features = DelegationParameterFeatures.Columns | DelegationParameterFeatures.Filter | DelegationParameterFeatures.Top | DelegationParameterFeatures.Sort, + _filter = "score gt 5", + _orderBy = new List<(string, bool)>() { ("score", true) }, + Top = 10 + }; + + var od = delegation.ToOdataParameters(); + + var str = od.ToQueryString(); + + Assert.Equal("$filter=score+gt+5&$orderby=score&$top=10", str); + } + + [Fact] + public void TestToOdataParametersFilterTopOrderByDesc() + { + var delegation = new TestDelegationParameters() + { + _columns = null, + _features = DelegationParameterFeatures.Columns | DelegationParameterFeatures.Filter | DelegationParameterFeatures.Top | DelegationParameterFeatures.Sort, + _filter = "score gt 5", + _orderBy = new List<(string, bool)>() { ("score", false) }, + Top = 10 + }; + + var od = delegation.ToOdataParameters(); + + var str = od.ToQueryString(); + + Assert.Equal("$filter=score+gt+5&$orderby=score desc&$top=10", str); + } + private class TestDelegationParameters : DelegationParameters { public string[] _columns; public string _filter; public DelegationParameterFeatures _features; + public List<(string, bool)> _orderBy; - public override DelegationParameterFeatures Features => - _features; + public override DelegationParameterFeatures Features => _features; - public override IReadOnlyCollection GetColumns() - { - return _columns; - } + public override IReadOnlyCollection GetColumns() => _columns; - public override string GetOdataFilter() - { - return _filter; - } + public override string GetOdataFilter() => _filter; + + public override IList<(string, bool)> GetOrderBy() => _orderBy; } } }