Skip to content

Commit

Permalink
Add checks for navigation collections (#80)
Browse files Browse the repository at this point in the history
* test(sql): add tests for using navigations

* fix: correct tests to highlight navigation bug

* fix: add check if skip navigation is collection

* test: add checks to confirm skip navigations

* fix: respect ISkipNavigation#IsCollection
  • Loading branch information
gordysc authored Apr 11, 2024
1 parent 01a935a commit 299a3f1
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 2 deletions.
7 changes: 5 additions & 2 deletions src/Foundatio.Parsers.SqlQueries/SqlQueryParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,9 @@ private void AddEntityFields(List<EntityFieldInfo> fields, IEntityType entityTyp
continue;

string propertyPath = prefix + nav.Name;
AddEntityFields(fields, nav.TargetEntityType, entityTypeStack, propertyPath + ".", false, depth + 1);
bool isNavCollection = nav is IReadOnlyNavigationBase { IsCollection: true };

AddEntityFields(fields, nav.TargetEntityType, entityTypeStack, propertyPath + ".", isNavCollection, depth + 1);
}

foreach (var skipNav in entityType.GetSkipNavigations())
Expand All @@ -139,7 +141,8 @@ private void AddEntityFields(List<EntityFieldInfo> fields, IEntityType entityTyp
continue;

string propertyPath = prefix + skipNav.Name;
AddEntityFields(fields, skipNav.TargetEntityType, entityTypeStack, propertyPath + ".", true, depth + 1);

AddEntityFields(fields, skipNav.TargetEntityType, entityTypeStack, propertyPath + ".", skipNav.IsCollection, depth + 1);
}

entityTypeStack.Pop();
Expand Down
1 change: 1 addition & 0 deletions tests/Foundatio.Parsers.SqlQueries.Tests/SampleContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public class Employee {
public int Id { get; set; }
public string FullName { get; set; }
public string Title { get; set; }
public int Salary { get; set; }
public List<Company> Companies { get; set; }
public List<DataValue> DataValues { get; set; }
public DateTime Created { get; set; } = DateTime.Now;
Expand Down
50 changes: 50 additions & 0 deletions tests/Foundatio.Parsers.SqlQueries.Tests/SqlQueryParserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,54 @@ public async Task CanUseCollectionDefaultFields()
Assert.Equal(sqlExpected, sqlActual);
}

[Fact]
public async Task CanUseNavigationFields()
{
var sp = GetServiceProvider();
await using var db = await GetSampleContextWithDataAsync(sp);
var parser = sp.GetRequiredService<SqlQueryParser>();

var context = parser.GetContext(db.Companies.EntityType);

Assert.Contains(db.Companies.EntityType.GetNavigations(), e => e.TargetEntityType == db.DataDefinitions.EntityType);

string sqlExpected = db.Companies.Where(e => e.DataDefinitions.Any(c => c.Key == "age")).ToQueryString();
string sqlActual = db.Companies.Where("""DataDefinitions.Any(Key.Equals("age"))""").ToQueryString();
Assert.Equal(sqlExpected, sqlActual);
string sql = await parser.ToDynamicLinqAsync("datadefinitions.key:age", context);
sqlActual = db.Companies.Where(sql).ToQueryString();
Assert.Equal(sqlExpected, sqlActual);

var query = db.Companies.AsQueryable();
var companies = await query.Where(sql).ToListAsync();

Assert.Single(companies);
}

[Fact]
public async Task CanUseSkipNavigationFields()
{
var sp = GetServiceProvider();
await using var db = await GetSampleContextWithDataAsync(sp);
var parser = sp.GetRequiredService<SqlQueryParser>();

var context = parser.GetContext(db.Companies.EntityType);

Assert.Contains(db.Companies.EntityType.GetSkipNavigations(), e => e.TargetEntityType == db.Employees.EntityType);

string sqlExpected = db.Companies.Where(e => e.Employees.Any(c => c.Salary.Equals(80_000))).ToQueryString();
string sqlActual = db.Companies.Where("""Employees.Any(Salary.Equals(80000))""").ToQueryString();
Assert.Equal(sqlExpected, sqlActual);
string sql = await parser.ToDynamicLinqAsync("employees.salary:80000", context);
sqlActual = db.Companies.Where(sql).ToQueryString();
Assert.Equal(sqlExpected, sqlActual);

var query = db.Companies.AsQueryable();
var companies = await query.Where(sql).ToListAsync();

Assert.Single(companies);
}

[Fact]
public async Task CanGenerateSql()
{
Expand Down Expand Up @@ -231,13 +279,15 @@ public async Task<SampleContext> GetSampleContextWithDataAsync(IServiceProvider
{
FullName = "John Doe",
Title = "Software Developer",
Salary = 80_000,
DataValues = [ new() { Definition = company.DataDefinitions[0], NumberValue = 30 } ],
Companies = [company]
});
db.Employees.Add(new Employee
{
FullName = "Jane Doe",
Title = "Software Developer",
Salary = 90_000,
DataValues = [ new() { Definition = company.DataDefinitions[0], NumberValue = 23 } ],
Companies = [company]
});
Expand Down

0 comments on commit 299a3f1

Please sign in to comment.