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;
}
}
}