Skip to content

Query Builder Endpoint #52

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

Merged
merged 43 commits into from
Mar 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
b59fe69
Query Builder POC
jcoitino Oct 16, 2024
33f01a0
Comment added
jcoitino Oct 16, 2024
845356d
Custom serializers added
jcoitino Oct 17, 2024
e2d4dda
code polishing
jcoitino Oct 17, 2024
9a49df7
Map to DTOs
jcoitino Oct 19, 2024
245d062
code polishing
jcoitino Oct 19, 2024
54e742c
SC Supression
jcoitino Oct 19, 2024
8a1ee22
Code polishing
jcoitino Oct 19, 2024
6d48137
Project requested columns only
jcoitino Oct 19, 2024
690c5e4
Code polishing
jcoitino Oct 19, 2024
a233500
Subqueries implemented
jcoitino Oct 19, 2024
0d22741
SQL Generator implemented
jcoitino Oct 19, 2024
020efd0
Resolve subqueries
jcoitino Oct 19, 2024
5ba3441
Type issue fixed
jcoitino Oct 20, 2024
a76c041
Handle nullables
jcoitino Oct 20, 2024
556115d
subquery issue fixed
jcoitino Oct 20, 2024
6725348
Code polishing
jcoitino Oct 20, 2024
c0e10b7
Fix subquery type
jcoitino Oct 20, 2024
0bd1be3
Fix subqueries type issue
jcoitino Oct 20, 2024
5c70ddc
Fix crash when null strings used in conditions
jcoitino Oct 21, 2024
e1473bf
Handle empty and notEmpty
jcoitino Oct 21, 2024
28a1b44
Empty includes isNull, I guess
jcoitino Oct 21, 2024
47548f2
Discriminated union imp for Query Filters
jcoitino Oct 22, 2024
b45da91
Remove NIEs
jcoitino Oct 22, 2024
02a216c
Enable column projection
jcoitino Oct 23, 2024
b6aa5fc
IN subquery issue fixed
jcoitino Oct 24, 2024
201ea8e
In subquery issue fixed
jcoitino Oct 24, 2024
cd87188
Merge branch 'main' into jcoitino/query-builder-poc
jcoitino Nov 7, 2024
b36a8a6
Code polishing
jcoitino Nov 8, 2024
f92b4e8
Code polishing
jcoitino Nov 9, 2024
fd2d79e
Code polishing
jcoitino Nov 9, 2024
aebb959
Unused imports removed
jcoitino Nov 9, 2024
bc22a61
Merge branch 'main' into jcoitino/query-builder-poc
jcoitino Mar 4, 2025
1c98933
Update inQuery/notInQuery conditions for 19.1
pmoleri Mar 4, 2025
01cfb64
Potential fix for code scanning alert no. 20: Log entries created fro…
zdrawku Mar 4, 2025
18e98fb
Fix failing ci
zdrawku Mar 4, 2025
1d2e82a
Fix string empty error
zdrawku Mar 4, 2025
a987b24
Missing operators added
jcoitino Mar 12, 2025
e5c7206
Add missing operators
jcoitino Mar 12, 2025
e75a48a
Code polishing
jcoitino Mar 13, 2025
d278745
Configure Newtonsoft to not mangle dates
pmoleri Mar 13, 2025
2cd40fa
Fix true and false ops
jcoitino Mar 13, 2025
92358df
code polishing
jcoitino Mar 13, 2025
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
25 changes: 13 additions & 12 deletions .github/workflows/build-test-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,25 @@ on:
pull_request:
branches:
- main

jobs:
build-and-test:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Checkout code
uses: actions/checkout@v3

- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 6.x
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.x'

- name: Restore dependencies
run: dotnet restore
- name: Restore dependencies
run: dotnet restore

- name: Build
run: dotnet build --configuration Release
- name: Build
run: dotnet build --configuration Release

- name: Run tests
run: dotnet test --configuration Release --no-build
- name: Run tests
run: dotnet test --configuration Release --no-build
69 changes: 69 additions & 0 deletions NorthwindCRUD/Controllers/QueryBuilderController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
namespace QueryBuilder;

using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using NorthwindCRUD;
using NorthwindCRUD.Models.Dtos;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;

[SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1516:Elements should be separated by blank line", Justification = "...")]
[SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1025:Code should not contain multiple whitespace in a row", Justification = "...")]
[SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1134:Attributes should not share line", Justification = "...")]
[SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1011:Closing square brackets should be spaced correctly", Justification = "...")]
public class QueryBuilderResult
{
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public AddressDto[]? Addresses { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public CategoryDto[]? Categories { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public ProductDto[]? Products { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public RegionDto[]? Regions { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public TerritoryDto[]? Territories { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public EmployeeDto[]? Employees { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public CustomerDto[]? Customers { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public OrderDto[]? Orders { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public OrderDetailDto[]? OrderDetails { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public ShipperDto[]? Shippers { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public SupplierDto[]? Suppliers { get; set; }
}

[ApiController]
[Route("[controller]")]
[SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1025:Code should not contain multiple whitespace in a row", Justification = "...")]
public class QueryBuilderController : ControllerBase
{
private readonly DataContext dataContext;
private readonly IMapper mapper;
private readonly ILogger<QueryBuilderController> logger;

public QueryBuilderController(DataContext dataContext, IMapper mapper, ILogger<QueryBuilderController> logger)
{
this.dataContext = dataContext;
this.mapper = mapper;
this.logger = logger;
}

[HttpPost("ExecuteQuery")]
[Consumes("application/json")]
[Produces("application/json")]
public ActionResult<QueryBuilderResult> ExecuteQuery(Query query)
{
var sanitizedEntity = query.Entity.Replace("\r", string.Empty).Replace("\n", string.Empty);
logger.LogInformation("Executing query for entity: {Entity}", sanitizedEntity);
var t = query.Entity.ToLower(CultureInfo.InvariantCulture);
return Ok(new QueryBuilderResult
{
Addresses = t == "addresses" ? mapper.Map<AddressDto[]>(dataContext.Addresses.Run(query)) : null,
Categories = t == "categories" ? mapper.Map<CategoryDto[]>(dataContext.Categories.Run(query)) : null,
Products = t == "products" ? mapper.Map<ProductDto[]>(dataContext.Products.Run(query)) : null,
Regions = t == "regions" ? mapper.Map<RegionDto[]>(dataContext.Regions.Run(query)) : null,
Territories = t == "territories" ? mapper.Map<TerritoryDto[]>(dataContext.Territories.Run(query)) : null,
Employees = t == "employees" ? mapper.Map<EmployeeDto[]>(dataContext.Employees.Run(query)) : null,
Customers = t == "customers" ? mapper.Map<CustomerDto[]>(dataContext.Customers.Run(query)) : null,
Orders = t == "orders" ? mapper.Map<OrderDto[]>(dataContext.Orders.Run(query)) : null,
OrderDetails = t == "orderdetails" ? mapper.Map<OrderDetailDto[]>(dataContext.OrderDetails.Run(query)) : null,
Shippers = t == "shippers" ? mapper.Map<ShipperDto[]>(dataContext.Shippers.Run(query)) : null,
Suppliers = t == "suppliers" ? mapper.Map<SupplierDto[]>(dataContext.Suppliers.Run(query)) : null,
});
}
}
8 changes: 3 additions & 5 deletions NorthwindCRUD/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@
using AutoMapper;
using GraphQL.AspNet.Configuration.Mvc;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using NorthwindCRUD.Filters;
using NorthwindCRUD.Helpers;
Expand Down Expand Up @@ -40,7 +37,8 @@ public static void Main(string[] args)
options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true;
}).AddNewtonsoftJson(options =>
{
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
options.SerializerSettings.DateParseHandling = DateParseHandling.None;
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
options.SerializerSettings.Converters.Add(new StringEnumConverter());
});

Expand Down
7 changes: 7 additions & 0 deletions NorthwindCRUD/QueryBuilder/Model/FilterType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace QueryBuilder;

public enum FilterType
{
And = 0,
Or = 1,
}
12 changes: 12 additions & 0 deletions NorthwindCRUD/QueryBuilder/Model/Query.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace QueryBuilder;

public class Query
{
public string Entity { get; set; }

public string[] ReturnFields { get; set; }

public FilterType Operator { get; set; }

public QueryFilter[] FilteringOperands { get; set; }
}
20 changes: 20 additions & 0 deletions NorthwindCRUD/QueryBuilder/Model/QueryFilter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace QueryBuilder;

public class QueryFilter
{
// Basic condition
public string? FieldName { get; set; }

public bool? IgnoreCase { get; set; }

public QueryFilterCondition? Condition { get; set; }

public object? SearchVal { get; set; }

public Query? SearchTree { get; set; }

// And/Or
public FilterType? Operator { get; set; }

public QueryFilter[] FilteringOperands { get; set; }
}
10 changes: 10 additions & 0 deletions NorthwindCRUD/QueryBuilder/Model/QueryFilterCondition.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace QueryBuilder;

public class QueryFilterCondition
{
public string Name { get; set; }

public bool IsUnary { get; set; }

public string IconName { get; set; }
}
Loading