Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Get-DataverseRecord - Allow operators other than Equals in -filtervalues #29

Merged
merged 3 commits into from
Dec 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class GetDataverseRecordCmdlet : OrganizationServiceCmdlet

private const string PARAMSET_SIMPLE = "Simple";

[Parameter(ParameterSetName=PARAMSET_SIMPLE, Mandatory = true, Position = 0, HelpMessage = "Logical name of table for which to retrieve records")]
[Parameter(ParameterSetName = PARAMSET_SIMPLE, Mandatory = true, Position = 0, HelpMessage = "Logical name of table for which to retrieve records")]
[Alias("EntityName")]
public string TableName { get; set; }

Expand All @@ -47,7 +47,7 @@ public string FetchXml
set;
}

[Parameter(ParameterSetName = PARAMSET_SIMPLE, Mandatory = false, HelpMessage = "List of hashsets of column names, values to filter records by using an EQUALS condition (or ISNULL if null value). If more than one hashset is provided then they are logically combined using an OR condition. e.g. @{firstname=\"bob\", age=25}, @{firstname=\"sue\"} will find records where (firstname=bob AND age=25) OR (firstname=sue)")]
[Parameter(ParameterSetName = PARAMSET_SIMPLE, Mandatory = false, HelpMessage = "List of hashsets of @{\"columnnames(:operator)\"=\"value\"} to filter records by. If operator is not specified, uses an EQUALS condition (or ISNULL if null value). If more than one hashset is provided then they are logically combined using an OR condition. e.g. @{firstname=\"bob\", age=25}, @{firstname=\"sue\"} will find records where (firstname=bob AND age=25) OR (firstname=sue)")]
public Hashtable[] FilterValues
{
get;
Expand Down Expand Up @@ -270,14 +270,31 @@ private QueryExpression GetSimpleQuery()
FilterExpression includeFilterExpression = includesFilterExpression.AddFilter(LogicalOperator.And);
foreach (DictionaryEntry filterValue in filterValues)
{
if (filterValue.Value == null)
ConditionOperator op = filterValue.Value == null ? ConditionOperator.Null : ConditionOperator.Equal;

string[] keyBits = ((string)filterValue.Key).Split(':');
string fieldName = keyBits[0];
if (keyBits.Length == 2)
{
includeFilterExpression.AddCondition((string)filterValue.Key, ConditionOperator.Null);
try
{
op = (ConditionOperator)Enum.Parse(typeof(ConditionOperator), keyBits[1]);
} catch (ArgumentException e)
{
throw new InvalidDataException($"The key '{filterValue.Key}' is invalid. {e.Message}. Valid operators are {string.Join(", ", Enum.GetNames(typeof(ConditionOperator)))}");

}
} else if (keyBits.Length > 2)
{
throw new InvalidDataException($"The key '{filterValue.Key}' is invalid. Valid formats are 'fieldname' or 'fieldname:operator'");
}
else

if (filterValue.Value is Array array)
{
includeFilterExpression.AddCondition((string)filterValue.Key, ConditionOperator.Equal,
filterValue.Value);
includeFilterExpression.AddCondition(fieldName, op, (object[])array);
} else
{
includeFilterExpression.AddCondition(fieldName, op, filterValue.Value);
}
}
}
Expand Down
18 changes: 15 additions & 3 deletions Rnwood.Dataverse.Data.PowerShell/docs/Get-DataverseRecord.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,17 @@ Get-DataverseRecord -Connection <ServiceClient> [-VerboseRecordCount] [-RecordCo

### Example 1
```powershell
PS C:\> {{ Add example code here }}
PS C:\> Get-DataverseRecord -connection $connection -tablename contact
```

{{ Add example description here }}
Get all contacts returning all non-system columns.

### Example 2
```powershell
PS C:\> Get-DataverseRecord -connection $connection -tablename contact -columns firstname -filtervalues @{"firstname:Like"="Rob%"}
```

Get all contacts where firstname starts with 'Rob' and return the firstname column only.

## PARAMETERS

Expand Down Expand Up @@ -118,11 +125,16 @@ Accept wildcard characters: False
```

### -FilterValues
List of hashsets of fields names,values to filter records by using an EQUALS condition (or ISNULL if null value).
List of hashsets of @{"fieldname"="value"} or @{"fieldname:operator"="value"} to filter records by. If operator is not provided, uses an EQUALS condition (or ISNULL if null value).
If more than one hashset is provided then they are logically combined using an OR condition.
e.g.
@{firstname="bob", age=25}, @{firstname="sue"} will find records where (firstname=bob AND age=25) OR (firstname=sue)

Valid operators:
Equal, NotEqual, GreaterThan, LessThan, GreaterEqual, LessEqual, Like, NotLike, In, NotIn, Between, NotBetween, Null, NotNull, Yesterday, Today, Tomorrow, Last7Days, Next7Days, LastWeek, ThisWeek, NextWeek, LastMonth, ThisMonth, NextMonth, On, OnOrBefore, OnOrAfter, LastYear, ThisYear, NextYear, LastXHours, NextXHours, LastXDays, NextXDays, LastXWeeks, NextXWeeks, LastXMonths, NextXMonths, LastXYears, NextXYears, EqualUserId, NotEqualUserId, EqualBusinessId, NotEqualBusinessId, ChildOf, Mask, NotMask, MasksSelect, Contains, DoesNotContain, EqualUserLanguage, NotOn, OlderThanXMonths, BeginsWith, DoesNotBeginWith, EndsWith, DoesNotEndWith, ThisFiscalYear, ThisFiscalPeriod, NextFiscalYear, NextFiscalPeriod, LastFiscalYear, LastFiscalPeriod, LastXFiscalYears, LastXFiscalPeriods, NextXFiscalYears, NextXFiscalPeriods, InFiscalYear, InFiscalPeriod, InFiscalPeriodAndYear, InOrBeforeFiscalPeriodAndYear, InOrAfterFiscalPeriodAndYear, EqualUserTeams, EqualUserOrUserTeams, Under, NotUnder, UnderOrEqual, Above, AboveOrEqual, EqualUserOrUserHierarchy, EqualUserOrUserHierarchyAndTeams, OlderThanXYears, OlderThanXWeeks, OlderThanXDays, OlderThanXHours, OlderThanXMinutes, ContainValues, DoesNotContainValues, EqualRoleBusinessId

The type of value must use those expected by the SDK for the column type and operator.

```yaml
Type: Hashtable[]
Parameter Sets: Simple
Expand Down
4 changes: 3 additions & 1 deletion tests/Common.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ BeforeAll {

function getMockConnection() {
if (-not $metadata) {
Import-Module Rnwood.Dataverse.Data.PowerShell
if (-not (Get-Module Rnwood.Dataverse.Data.PowerShell)){
Import-Module Rnwood.Dataverse.Data.PowerShell
}
Add-Type -AssemblyName "System.Runtime.Serialization"

# Define the DataContractSerializer
Expand Down
33 changes: 33 additions & 0 deletions tests/Get-DataverseRecord.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,39 @@ Describe 'Get-DataverseRecord' {
$result.TableName | Should -be "contact"
}

It "Given filter with no explicit operator, gets all records matching using equals" {

$connection = getMockConnection
1..10 | ForEach-Object { @{"firstname" = "$_" } } | Set-DataverseRecord -Connection $connection -TableName contact
$result = Get-DataverseRecord -Connection $connection -TableName contact -filter @{"firstname"="1"}
$result | Should -HaveCount 1
$result[0].firstname | Should -Be "1"
}

It "Given filter with explicit operator, gets all records matching using that operator" {

$connection = getMockConnection
1..10 | ForEach-Object { @{"firstname" = "$_" } } | Set-DataverseRecord -Connection $connection -TableName contact
$result = Get-DataverseRecord -Connection $connection -TableName contact -filter @{"firstname:Like"="1%"}
$result | Should -HaveCount 2
}

It "Given filter with explicit operator not requiring a value, gets all records matching using that operator" {

$connection = getMockConnection
1..10 | ForEach-Object { @{"firstname" = "$_" } } | Set-DataverseRecord -Connection $connection -TableName contact
$result = Get-DataverseRecord -Connection $connection -TableName contact -filter @{"firstname:Null"=""}
$result | Should -HaveCount 0
}

It "Given filter with explicit operator requiring multiple values, gets all records matching using that operator" {

$connection = getMockConnection
1..10 | ForEach-Object { @{"firstname" = "$_" } } | Set-DataverseRecord -Connection $connection -TableName contact
$result = Get-DataverseRecord -Connection $connection -TableName contact -filter @{"firstname:In"=("1", "2")}
$result | Should -HaveCount 2
}

It "Given no filters, gets all records even beyond the page limit" {

$connection = getMockConnection
Expand Down
Loading