Skip to content

Commit

Permalink
Add default field search support
Browse files Browse the repository at this point in the history
  • Loading branch information
ejsmith committed Mar 19, 2024
1 parent 0e13f7a commit 1c94c63
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 8 deletions.
29 changes: 24 additions & 5 deletions src/Foundatio.Parsers.SqlQueries/Extensions/SqlNodeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,20 +115,39 @@ public static EntityFieldInfo GetFieldInfo(List<EntityFieldInfo> fields, string

public static string ToSqlString(this TermNode node, ISqlQueryVisitorContext context)
{
if (String.IsNullOrEmpty(node.Field))
context.AddValidationError("Field is required for term node queries.");

if (!String.IsNullOrEmpty(node.Prefix))
context.AddValidationError("Prefix is not supported for term range queries.");

var builder = new StringBuilder();

if (String.IsNullOrEmpty(node.Field))
{
if (context.DefaultFields == null || context.DefaultFields.Length == 0)
{
context.AddValidationError("Field or DefaultFields is required for term queries.");
return String.Empty;
}

for (int index = 0; index < context.DefaultFields.Length; index++)
{
builder.Append(index == 0 ? "(" : " OR ");

string defaultField = context.DefaultFields[index];
builder.Append(defaultField).Append(".Contains(\"").Append(node.Term).Append("\")");

if (index == context.DefaultFields.Length - 1)
builder.Append(")");
}

return builder.ToString();
}

// support overriding the generated query
if (node.TryGetQuery(out string query))
return query;

var field = GetFieldInfo(context.Fields, node.Field);

var builder = new StringBuilder();

if (node.IsNegated.HasValue && node.IsNegated.Value)
builder.Append("NOT ");

Expand Down
27 changes: 24 additions & 3 deletions tests/Foundatio.Parsers.SqlQueries.Tests/SqlQueryParserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,24 @@ public Task ValidQueries(string query, string expected)
return ParseAndValidateQuery(query, expected, true);
}

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

var context = parser.GetContext(db.Employees.EntityType);
parser.Configuration.SetDefaultFields(["FullName", "Title"]);

string sqlExpected = db.Employees.Where(e => e.FullName.Contains("John") || e.Title.Contains("John")).ToQueryString();
string sqlActual = db.Employees.Where("""FullName.Contains("John") || Title.Contains("John")""").ToQueryString();
Assert.Equal(sqlExpected, sqlActual);
string sql = await parser.ToSqlAsync("John", context);
sqlActual = db.Employees.Where(sql).ToQueryString();
Assert.Equal(sqlExpected, sqlActual);
}

[Fact]
public async Task CanUseDateFilter()
{
Expand All @@ -68,8 +86,6 @@ public async Task CanUseDateFilter()
var parser = sp.GetRequiredService<SqlQueryParser>();

var context = parser.GetContext(db.Employees.EntityType);
context.Fields.Add(new EntityFieldInfo { Field = "age", IsNumber = true, Data = {{ "DataDefinitionId", 1 }}});
context.ValidationOptions.AllowedFields.Add("age");

string sqlExpected = db.Employees.Where(e => e.Created > new DateTime(2024, 1, 1)).ToQueryString();
string sqlActual = db.Employees.Where("""created > DateTime.Parse("2024-01-01")""").ToQueryString();
Expand Down Expand Up @@ -188,7 +204,12 @@ private async Task ParseAndValidateQuery(string query, string expected, bool isV

string nodes = await DebugQueryVisitor.RunAsync(result);
_logger.LogInformation(nodes);
string generatedQuery = await GenerateSqlVisitor.RunAsync(result, new SqlQueryVisitorContext());
var context = new SqlQueryVisitorContext { Fields =
[
new EntityFieldInfo { Field = "field", IsNumber = true }
]
};
string generatedQuery = await GenerateSqlVisitor.RunAsync(result, context);
Assert.Equal(expected, generatedQuery);
}
}
Expand Down

0 comments on commit 1c94c63

Please sign in to comment.