Skip to content

Commit

Permalink
Merge pull request #22 from Evodim/feat--query-dynamic-helper-extensions
Browse files Browse the repository at this point in the history
Feat  query dynamic helper extensions
  • Loading branch information
medevod authored Feb 6, 2023
2 parents 17c8549 + c114240 commit e74ba4e
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace Azure.EntityServices.Queries
{
public static class DynamicQueryExtensions
{
/// <summary>
/// Build query filters by iterate on each given collection item
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="U">Generic collection</typeparam>
/// <param name="query"></param>
/// <param name="list"></param>
/// <param name="action"></param>
/// <returns></returns>
public static IFilterOperator<T> WithEach<T, U>(this IFilterOperator<T> query, IEnumerable<U> list, Func<U, IFilterOperator<T>, IFilterOperator<T>> action)
{
var dynamicQuery = query;
foreach (var item in list)
{
dynamicQuery = action(item, dynamicQuery);
}
return dynamicQuery;
}

/// <summary>
/// Build a filter to check if current field value was present in given list
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="P"></typeparam>
/// <param name="query"></param>
/// <param name="values"></param>
/// <returns></returns>
public static IFilterOperator<T> In<T, P>(this IQueryFilter<T, P> query, params P[] values)
{
IQuery<T> nextQuery = (IQuery<T>)query;
foreach (var item in values.SkipLast(1))
{
nextQuery = (IQuery<T>)(nextQuery as IQueryFilter<T>).Equal(item).Or(query.PropertyName);
}
(nextQuery as IQueryFilter<T>).Equal(values.Last());
return nextQuery as IFilterOperator<T>;
}

/// <summary>
/// Build a filter to check if current field value was not present in given list
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="P"></typeparam>
/// <param name="query"></param>
/// <param name="values"></param>
/// <returns></returns>
public static IFilterOperator<T> NotIn<T, P>(this IQueryFilter<T, P> query, params P[] values)
{
IQuery<T> nextQuery = (IQuery<T>)query;
foreach (var item in values.SkipLast(1))
{
nextQuery = (IQuery<T>)(nextQuery as IQueryFilter<T>).NotEqual(item).And(query.PropertyName);
}
(nextQuery as IQueryFilter<T>).NotEqual(values.Last());
return nextQuery as IFilterOperator<T>;
}
}
}
5 changes: 4 additions & 1 deletion src/Azure.EntityServices.Queries/IQueryFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ public interface IQueryFilter<T> : IQueryFilter<T, object>

public interface IQueryFilter<T, P>
{
string PropertyName { get; }

IFilterOperator<T> AddFilterCondition(string comparison, P value);

IFilterOperator<T> AddFilterCondition(string comparison, object value, Type type);

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,5 +121,98 @@ public void Should_Build_TableStorage_Query_Expression_With_Grouped_Filter_Insid
.Should()
.Be("PartitionKey eq 'Tenant-1' and TenantId eq '10' and not (Created gt datetime'2012-04-21T18:25:43.0000000Z' or Created lt datetime'2012-04-21T18:25:43.0000000Z') or not (Enabled eq true)");
}

[TestMethod]
public void Should_BuildGroup_Dynamic_Query_Expression()
{
var builder = new MockedExpressionBuilder<PersonEntity>();

var dynamicQuery = builder.Query
.Where(p => p.TenantId).Equal("50");
for (var i = 0; i < 10; i++)
{
dynamicQuery = dynamicQuery.Or(p => p.FirstName).Equal($"do {i}");
}

var queryStr = builder.Build();

queryStr.Trim()
.Should()
.Be("TenantId Equal '50' Or FirstName Equal 'do 0' Or FirstName Equal 'do 1' Or FirstName Equal 'do 2' Or FirstName Equal 'do 3' Or FirstName Equal 'do 4' Or FirstName Equal 'do 5' Or FirstName Equal 'do 6' Or FirstName Equal 'do 7' Or FirstName Equal 'do 8' Or FirstName Equal 'do 9'");
}

[TestMethod]
public void Should_BuildGroup_Dynamic_Query_Expression_WithEach_Extension_Helper()
{
var builder = new MockedExpressionBuilder<PersonEntity>();

var dynamicQuery = builder.Query
.Where(p => p.TenantId).Equal("50");

dynamicQuery.WithEach(new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, (item, q) =>
q.Or(p => p.FirstName).Equal($"do {item}"));

var queryStr = builder.Build();

queryStr.Trim()
.Should()
.Be("TenantId Equal '50' Or FirstName Equal 'do 0' Or FirstName Equal 'do 1' Or FirstName Equal 'do 2' Or FirstName Equal 'do 3' Or FirstName Equal 'do 4' Or FirstName Equal 'do 5' Or FirstName Equal 'do 6' Or FirstName Equal 'do 7' Or FirstName Equal 'do 8' Or FirstName Equal 'do 9'");
}

[TestMethod]
public void Should_BuildGroup_Dynamic_Query_Expression_In_Extension_Helper()
{
var builder = new MockedExpressionBuilder<PersonEntity>();

var dynamicQuery = builder.Query
.Where(p => p.TenantId).Equal("50")
.And(p => p.LastName)
.In("Doe");

var queryStr = builder.Build();

queryStr.Trim()
.Should()
.Be("TenantId Equal '50' And LastName Equal 'Doe'");

dynamicQuery = builder.Query
.Where(p => p.TenantId).Equal("50")
.And("LastName")
.In("Doe", "Kent");

queryStr = builder.Build();

queryStr.Trim()
.Should()
.Be("TenantId Equal '50' And LastName Equal 'Doe' Or LastName Equal 'Kent'");
}

[TestMethod]
public void Should_BuildGroup_Dynamic_Query_Expression_NotIn_Extension_Helper()
{
var builder = new MockedExpressionBuilder<PersonEntity>();

var dynamicQuery = builder.Query
.Where(p => p.TenantId).Equal("50")
.And(p => p.LastName)
.NotIn("Doe");

var queryStr = builder.Build();

queryStr.Trim()
.Should()
.Be("TenantId Equal '50' And LastName NotEqual 'Doe'");

dynamicQuery = builder.Query
.Where(p => p.TenantId).Equal("50")
.And("LastName")
.NotIn("Doe", "Kent");

queryStr = builder.Build();

queryStr.Trim()
.Should()
.Be("TenantId Equal '50' And LastName NotEqual 'Doe' And LastName NotEqual 'Kent'");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -154,5 +154,26 @@ public void Should_Build_Table_Filter_Expression_With_Invariant_Floating_Point_V
result.Should()
.Be("PartitionKey eq 'tenantId' and Latitude eq 48.77309806265856 and Distance eq '148.45648566856' and BankAmount eq '1248.7731'");
}
[TestMethod]
public void Should_Use_Multi_PartitionKey_filter()
{
var builder = new TableStorageQueryBuilder<PersonEntity>(new TagFilterExpression<PersonEntity>("Created"));

(builder.Query as TagFilterExpression<PersonEntity>)
.WherePartitionKey()
.Equal("partition1")
.OrPartitionKey()
.Equal("partition2")
.OrPartitionKey()
.Equal("Partition3");

var queryStr = builder.Build();

queryStr.Trim()
.Should()
.Be("PartitionKey eq 'partition1' or PartitionKey eq 'partition2' or PartitionKey eq 'Partition3'");

}

}
}

0 comments on commit e74ba4e

Please sign in to comment.