Skip to content

Commit

Permalink
Working on EF SQL adapter
Browse files Browse the repository at this point in the history
  • Loading branch information
ejsmith committed Mar 1, 2024
1 parent 3e6bbe2 commit 335f26e
Show file tree
Hide file tree
Showing 11 changed files with 409 additions and 6 deletions.
12 changes: 12 additions & 0 deletions Foundatio.Parsers.sln
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Foundatio.Parsers.ElasticQueries.Tests", "tests\Foundatio.Parsers.ElasticQueries.Tests\Foundatio.Parsers.ElasticQueries.Tests.csproj", "{C353E601-874C-4855-9B01-2980BC624BC4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Foundatio.Parsers.SqlQueries", "src\Foundatio.Parsers.SqlQueries\Foundatio.Parsers.SqlQueries.csproj", "{53C0B9D8-6398-437C-AE15-43BD4CB7AD8D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Foundatio.Parsers.SqlQueries.Tests", "tests\Foundatio.Parsers.SqlQueries.Tests\Foundatio.Parsers.SqlQueries.Tests.csproj", "{B30934E7-C69F-465B-BACF-61AAEC7DA775}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -44,6 +48,14 @@ Global
{C353E601-874C-4855-9B01-2980BC624BC4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C353E601-874C-4855-9B01-2980BC624BC4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C353E601-874C-4855-9B01-2980BC624BC4}.Release|Any CPU.Build.0 = Release|Any CPU
{53C0B9D8-6398-437C-AE15-43BD4CB7AD8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{53C0B9D8-6398-437C-AE15-43BD4CB7AD8D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{53C0B9D8-6398-437C-AE15-43BD4CB7AD8D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{53C0B9D8-6398-437C-AE15-43BD4CB7AD8D}.Release|Any CPU.Build.0 = Release|Any CPU
{B30934E7-C69F-465B-BACF-61AAEC7DA775}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B30934E7-C69F-465B-BACF-61AAEC7DA775}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B30934E7-C69F-465B-BACF-61AAEC7DA775}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B30934E7-C69F-465B-BACF-61AAEC7DA775}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
2 changes: 1 addition & 1 deletion build/common.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project>

<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<TargetFrameworks>netstandard2.0;</TargetFrameworks>
<Product>Foundatio.Parsers</Product>
<Description>A lucene style query parser that is extensible and allows additional syntax features.</Description>
<PackageProjectUrl>https://github.com/FoundatioFx/Foundatio.Parsers</PackageProjectUrl>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\build\common.props" />
<ItemGroup>
<PackageReference Include="Exceptionless.DateTimeExtensions" Version="3.4.3" />
<PackageReference Include="System.Text.Json" Version="6.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Foundatio.Parsers.LuceneQueries\Foundatio.Parsers.LuceneQueries.csproj" />
</ItemGroup>
</Project>
51 changes: 51 additions & 0 deletions src/Foundatio.Parsers.SqlQueries/SqlQueryParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using System;
using System.Threading.Tasks;
using Foundatio.Parsers.LuceneQueries;
using Foundatio.Parsers.LuceneQueries.Extensions;
using Foundatio.Parsers.LuceneQueries.Nodes;
using Foundatio.Parsers.LuceneQueries.Visitors;
using Foundatio.Parsers.SqlQueries.Visitors;
using Pegasus.Common;

namespace Foundatio.Parsers.SqlQueries;

public class SqlQueryParser : LuceneQueryParser {
public SqlQueryParser(Action<SqlQueryParserConfiguration> configure = null) {
var config = new SqlQueryParserConfiguration();
configure?.Invoke(config);
Configuration = config;
}

public SqlQueryParserConfiguration Configuration { get; }

public override async Task<IQueryNode> ParseAsync(string query, IQueryVisitorContext context = null) {
query ??= String.Empty;

if (context == null)
context = new SqlQueryVisitorContext();

//SetupQueryVisitorContextDefaults(context);
try {
var result = await base.ParseAsync(query, context).ConfigureAwait(false);
switch (context.QueryType) {
case QueryTypes.Aggregation:
result = await Configuration.AggregationVisitor.AcceptAsync(result, context).ConfigureAwait(false);
break;
case QueryTypes.Query:
result = await Configuration.QueryVisitor.AcceptAsync(result, context).ConfigureAwait(false);
break;
case QueryTypes.Sort:
result = await Configuration.SortVisitor.AcceptAsync(result, context).ConfigureAwait(false);
break;
}

return result;
} catch (FormatException ex) {
var cursor = ex.Data["cursor"] as Cursor;
context.GetValidationResult().QueryType = context.QueryType;
context.AddValidationError(ex.Message, cursor.Column);

return null;
}
}
}
223 changes: 223 additions & 0 deletions src/Foundatio.Parsers.SqlQueries/SqlQueryParserConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Foundatio.Parsers.LuceneQueries;
using Foundatio.Parsers.LuceneQueries.Visitors;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;

namespace Foundatio.Parsers.SqlQueries;

public class SqlQueryParserConfiguration {
private ILogger _logger = NullLogger.Instance;

public SqlQueryParserConfiguration() {
//AddQueryVisitor(new CombineQueriesVisitor(), 10000);
AddSortVisitor(new TermToFieldVisitor(), 0);
AddAggregationVisitor(new AssignOperationTypeVisitor(), 0);
//AddAggregationVisitor(new CombineAggregationsVisitor(), 10000);
AddVisitor(new FieldResolverQueryVisitor((field, context) => FieldResolver != null ? FieldResolver(field, context) : Task.FromResult<string>(null)), 10);
AddVisitor(new ValidationVisitor(), 30);
}

public ILoggerFactory LoggerFactory { get; private set; } = NullLoggerFactory.Instance;
public string[] DefaultFields { get; private set; }
public QueryFieldResolver FieldResolver { get; private set; }
public IncludeResolver IncludeResolver { get; private set; }
//public ElasticMappingResolver MappingResolver { get; private set; }
public QueryValidationOptions ValidationOptions { get; private set; }
public ChainedQueryVisitor SortVisitor { get; } = new ChainedQueryVisitor();
public ChainedQueryVisitor QueryVisitor { get; } = new ChainedQueryVisitor();
public ChainedQueryVisitor AggregationVisitor { get; } = new ChainedQueryVisitor();

public SqlQueryParserConfiguration SetLoggerFactory(ILoggerFactory loggerFactory) {
LoggerFactory = loggerFactory ?? NullLoggerFactory.Instance;
_logger = loggerFactory.CreateLogger<SqlQueryParserConfiguration>();

return this;
}

public SqlQueryParserConfiguration SetDefaultFields(string[] fields) {
DefaultFields = fields;
return this;
}

public SqlQueryParserConfiguration UseFieldResolver(QueryFieldResolver resolver, int priority = 10) {
FieldResolver = resolver;
ReplaceVisitor<FieldResolverQueryVisitor>(new FieldResolverQueryVisitor(resolver), priority);

return this;
}

public SqlQueryParserConfiguration UseFieldMap(IDictionary<string, string> fields, int priority = 10) {
if (fields != null)
return UseFieldResolver(fields.ToHierarchicalFieldResolver(), priority);

return UseFieldResolver(null);
}

public SqlQueryParserConfiguration UseIncludes(IncludeResolver includeResolver, ShouldSkipIncludeFunc shouldSkipInclude = null, int priority = 0) {
IncludeResolver = includeResolver;

return AddVisitor(new IncludeVisitor(shouldSkipInclude), priority);
}

public SqlQueryParserConfiguration UseIncludes(Func<string, string> resolveInclude, ShouldSkipIncludeFunc shouldSkipInclude = null, int priority = 0) {
return UseIncludes(name => Task.FromResult(resolveInclude(name)), shouldSkipInclude, priority);
}

public SqlQueryParserConfiguration UseIncludes(IDictionary<string, string> includes, ShouldSkipIncludeFunc shouldSkipInclude = null, int priority = 0) {
return UseIncludes(name => includes.ContainsKey(name) ? includes[name] : null, shouldSkipInclude, priority);
}

public SqlQueryParserConfiguration SetValidationOptions(QueryValidationOptions options) {
ValidationOptions = options;
return this;
}

#region Combined Visitor Management

public SqlQueryParserConfiguration AddVisitor(IChainableQueryVisitor visitor, int priority = 0) {
QueryVisitor.AddVisitor(visitor, priority);
AggregationVisitor.AddVisitor(visitor, priority);
SortVisitor.AddVisitor(visitor, priority);

return this;
}

public SqlQueryParserConfiguration RemoveVisitor<T>() where T : IChainableQueryVisitor {
QueryVisitor.RemoveVisitor<T>();
AggregationVisitor.RemoveVisitor<T>();
SortVisitor.RemoveVisitor<T>();

return this;
}

public SqlQueryParserConfiguration ReplaceVisitor<T>(IChainableQueryVisitor visitor, int? newPriority = null) where T : IChainableQueryVisitor {
QueryVisitor.ReplaceVisitor<T>(visitor, newPriority);
AggregationVisitor.ReplaceVisitor<T>(visitor, newPriority);
SortVisitor.ReplaceVisitor<T>(visitor, newPriority);

return this;
}

public SqlQueryParserConfiguration AddVisitorBefore<T>(IChainableQueryVisitor visitor) {
QueryVisitor.AddVisitorBefore<T>(visitor);
AggregationVisitor.AddVisitorBefore<T>(visitor);
SortVisitor.AddVisitorBefore<T>(visitor);

return this;
}

public SqlQueryParserConfiguration AddVisitorAfter<T>(IChainableQueryVisitor visitor) {
QueryVisitor.AddVisitorAfter<T>(visitor);
AggregationVisitor.AddVisitorAfter<T>(visitor);
SortVisitor.AddVisitorAfter<T>(visitor);

return this;
}

#endregion

#region Query Visitor Management

public SqlQueryParserConfiguration AddQueryVisitor(IChainableQueryVisitor visitor, int priority = 0) {
QueryVisitor.AddVisitor(visitor, priority);

return this;
}

public SqlQueryParserConfiguration RemoveQueryVisitor<T>() where T : IChainableQueryVisitor {
QueryVisitor.RemoveVisitor<T>();

return this;
}

public SqlQueryParserConfiguration ReplaceQueryVisitor<T>(IChainableQueryVisitor visitor, int? newPriority = null) where T : IChainableQueryVisitor {
QueryVisitor.ReplaceVisitor<T>(visitor, newPriority);

return this;
}

public SqlQueryParserConfiguration AddQueryVisitorBefore<T>(IChainableQueryVisitor visitor) {
QueryVisitor.AddVisitorBefore<T>(visitor);

return this;
}

public SqlQueryParserConfiguration AddQueryVisitorAfter<T>(IChainableQueryVisitor visitor) {
QueryVisitor.AddVisitorAfter<T>(visitor);

return this;
}

#endregion

#region Sort Visitor Management

public SqlQueryParserConfiguration AddSortVisitor(IChainableQueryVisitor visitor, int priority = 0) {
SortVisitor.AddVisitor(visitor, priority);

return this;
}

public SqlQueryParserConfiguration RemoveSortVisitor<T>() where T : IChainableQueryVisitor {
SortVisitor.RemoveVisitor<T>();

return this;
}

public SqlQueryParserConfiguration ReplaceSortVisitor<T>(IChainableQueryVisitor visitor, int? newPriority = null) where T : IChainableQueryVisitor {
SortVisitor.ReplaceVisitor<T>(visitor, newPriority);

return this;
}

public SqlQueryParserConfiguration AddSortVisitorBefore<T>(IChainableQueryVisitor visitor) {
SortVisitor.AddVisitorBefore<T>(visitor);

return this;
}

public SqlQueryParserConfiguration AddSortVisitorAfter<T>(IChainableQueryVisitor visitor) {
SortVisitor.AddVisitorAfter<T>(visitor);

return this;
}

#endregion

#region Aggregation Visitor Management

public SqlQueryParserConfiguration AddAggregationVisitor(IChainableQueryVisitor visitor, int priority = 0) {
AggregationVisitor.AddVisitor(visitor, priority);

return this;
}

public SqlQueryParserConfiguration RemoveAggregationVisitor<T>() where T : IChainableQueryVisitor {
AggregationVisitor.RemoveVisitor<T>();

return this;
}

public SqlQueryParserConfiguration ReplaceAggregationVisitor<T>(IChainableQueryVisitor visitor, int? newPriority = null) where T : IChainableQueryVisitor {
AggregationVisitor.ReplaceVisitor<T>(visitor, newPriority);

return this;
}

public SqlQueryParserConfiguration AddAggregationVisitorBefore<T>(IChainableQueryVisitor visitor) {
AggregationVisitor.AddVisitorBefore<T>(visitor);

return this;
}

public SqlQueryParserConfiguration AddAggregationVisitorAfter<T>(IChainableQueryVisitor visitor) {
AggregationVisitor.AddVisitorAfter<T>(visitor);

return this;
}

#endregion
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;
using System.Threading.Tasks;
using Foundatio.Parsers.LuceneQueries.Visitors;

namespace Foundatio.Parsers.SqlQueries.Visitors {
public interface ISqlQueryVisitorContext : IQueryVisitorContext {
Func<Task<string>> DefaultTimeZone { get; set; }
bool UseScoring { get; set; }
//ElasticMappingResolver MappingResolver { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;
using System.Threading.Tasks;
using Foundatio.Parsers.LuceneQueries.Visitors;

namespace Foundatio.Parsers.SqlQueries.Visitors;

public class SqlQueryVisitorContext : QueryVisitorContext, ISqlQueryVisitorContext {
public Func<Task<string>> DefaultTimeZone { get; set; }
public bool UseScoring { get; set; }
//public ElasticMappingResolver MappingResolver { get; set; }
}
9 changes: 5 additions & 4 deletions tests/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
<Import Project="..\build\common.props" />
<PropertyGroup>
<TargetFrameworks>net8.0</TargetFrameworks>
<TargetFrameworks>net8.0;</TargetFrameworks>
<IsPackable>False</IsPackable>
<NoWarn>$(NoWarn);CS1591;NU1701</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="xunit" Version="2.6.5" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.6" />
<PackageReference Include="GitHubActionsTestLogger" Version="2.3.3" PrivateAssets="All" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
<PackageReference Include="xunit" Version="2.7.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.7" />
<PackageReference Include="GitHubActionsTestLogger" Version="2.3.3" PrivateAssets="All" />

<PackageReference Include="Foundatio.TestHarness" Version="10.7.0" Condition="'$(ReferenceFoundatioSource)' == '' OR '$(ReferenceFoundatioSource)' == 'false'" />
<ProjectReference Include="..\..\..\Foundatio\src\Foundatio.TestHarness\Foundatio.TestHarness.csproj" Condition="'$(ReferenceFoundatioSource)' == 'true'" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Threading.Tasks;
using Foundatio.Parsers.LuceneQueries.Nodes;
using Foundatio.Parsers.LuceneQueries.Visitors;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!--<DefineConstants>ENABLE_TRACING</DefineConstants>-->
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Foundatio.Parsers.SqlQueries\Foundatio.Parsers.SqlQueries.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.2" />
</ItemGroup>

</Project>
Loading

0 comments on commit 335f26e

Please sign in to comment.