Browse Source

Merge remote-tracking branch 'upstream/master'

pull/346/head
Marcel Hilgersom 7 years ago
parent
commit
87266950b8
  1. 2
      src/Squidex.Infrastructure.MongoDb/MongoDb/Queries/FilterVisitor.cs
  2. 5
      src/Squidex.Infrastructure/Queries/FilterBuilder.cs
  3. 2
      src/Squidex.Infrastructure/Queries/FilterComparison.cs
  4. 1
      src/Squidex.Infrastructure/Queries/FilterOperator.cs
  5. 8
      src/Squidex.Infrastructure/Queries/OData/EdmModelExtensions.cs
  6. 6
      src/Squidex.Infrastructure/Queries/OData/FilterVisitor.cs
  7. 20
      tests/Squidex.Domain.Apps.Entities.Tests/Contents/MongoDb/MongoDbQueryTests.cs
  8. 18
      tests/Squidex.Infrastructure.Tests/Queries/ODataConversionTests.cs

2
src/Squidex.Infrastructure.MongoDb/MongoDb/Queries/FilterVisitor.cs

@ -51,6 +51,8 @@ namespace Squidex.Infrastructure.MongoDb.Queries
switch (nodeIn.Operator) switch (nodeIn.Operator)
{ {
case FilterOperator.Empty:
return Filter.Or(Filter.Exists(propertyName, false), Filter.Eq(propertyName, default(T)), Filter.Eq(propertyName, string.Empty), Filter.Eq(propertyName, new T[0]));
case FilterOperator.StartsWith: case FilterOperator.StartsWith:
return Filter.Regex(propertyName, BuildRegex(nodeIn, s => "^" + s)); return Filter.Regex(propertyName, BuildRegex(nodeIn, s => "^" + s));
case FilterOperator.Contains: case FilterOperator.Contains:

5
src/Squidex.Infrastructure/Queries/FilterBuilder.cs

@ -47,6 +47,11 @@ namespace Squidex.Infrastructure.Queries
return Binary(path, FilterOperator.Equals, value); return Binary(path, FilterOperator.Equals, value);
} }
public static FilterComparison Empty(string path)
{
return new FilterComparison(path.Split('.', '/'), FilterOperator.Empty, FilterValue.Null);
}
public static FilterComparison In(string path, params long[] value) public static FilterComparison In(string path, params long[] value)
{ {
return new FilterComparison(path.Split('.', '/'), FilterOperator.In, new FilterValue(value.ToList())); return new FilterComparison(path.Split('.', '/'), FilterOperator.In, new FilterValue(value.ToList()));

2
src/Squidex.Infrastructure/Queries/FilterComparison.cs

@ -42,6 +42,8 @@ namespace Squidex.Infrastructure.Queries
{ {
case FilterOperator.Contains: case FilterOperator.Contains:
return $"contains({path}, {Rhs})"; return $"contains({path}, {Rhs})";
case FilterOperator.Empty:
return $"empty({path})";
case FilterOperator.EndsWith: case FilterOperator.EndsWith:
return $"endsWith({path}, {Rhs})"; return $"endsWith({path}, {Rhs})";
case FilterOperator.StartsWith: case FilterOperator.StartsWith:

1
src/Squidex.Infrastructure/Queries/FilterOperator.cs

@ -10,6 +10,7 @@ namespace Squidex.Infrastructure.Queries
public enum FilterOperator public enum FilterOperator
{ {
Contains, Contains,
Empty,
EndsWith, EndsWith,
Equals, Equals,
GreaterThan, GreaterThan,

8
src/Squidex.Infrastructure/Queries/OData/EdmModelExtensions.cs

@ -14,6 +14,14 @@ namespace Squidex.Infrastructure.Queries.OData
{ {
public static class EdmModelExtensions public static class EdmModelExtensions
{ {
static EdmModelExtensions()
{
CustomUriFunctions.AddCustomUriFunction("empty",
new FunctionSignatureWithReturnType(
EdmCoreModel.Instance.GetBoolean(false),
EdmCoreModel.Instance.GetString(true)));
}
public static ODataUriParser ParseQuery(this IEdmModel model, string query) public static ODataUriParser ParseQuery(this IEdmModel model, string query)
{ {
if (!model.EntityContainer.EntitySets().Any()) if (!model.EntityContainer.EntitySets().Any())

6
src/Squidex.Infrastructure/Queries/OData/FilterVisitor.cs

@ -49,6 +49,12 @@ namespace Squidex.Infrastructure.Queries.OData
public override FilterNode Visit(SingleValueFunctionCallNode nodeIn) public override FilterNode Visit(SingleValueFunctionCallNode nodeIn)
{ {
var fieldNode = nodeIn.Parameters.ElementAt(0); var fieldNode = nodeIn.Parameters.ElementAt(0);
if (string.Equals(nodeIn.Name, "empty", StringComparison.OrdinalIgnoreCase))
{
return new FilterComparison(PropertyPathVisitor.Visit(fieldNode), FilterOperator.Empty, FilterValue.Null);
}
var valueNode = nodeIn.Parameters.ElementAt(1); var valueNode = nodeIn.Parameters.ElementAt(1);
if (string.Equals(nodeIn.Name, "endswith", StringComparison.OrdinalIgnoreCase)) if (string.Equals(nodeIn.Name, "endswith", StringComparison.OrdinalIgnoreCase))

20
tests/Squidex.Domain.Apps.Entities.Tests/Contents/MongoDb/MongoDbQueryTests.cs

@ -19,7 +19,6 @@ using Squidex.Domain.Apps.Entities.MongoDb.Contents;
using Squidex.Domain.Apps.Entities.MongoDb.Contents.Visitors; using Squidex.Domain.Apps.Entities.MongoDb.Contents.Visitors;
using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.Collections;
using Squidex.Infrastructure.MongoDb; using Squidex.Infrastructure.MongoDb;
using Squidex.Infrastructure.MongoDb.Queries; using Squidex.Infrastructure.MongoDb.Queries;
using Squidex.Infrastructure.Queries; using Squidex.Infrastructure.Queries;
@ -46,13 +45,13 @@ namespace Squidex.Domain.Apps.Entities.Contents.MongoDb
schemaDef = schemaDef =
new Schema("user") new Schema("user")
.AddString(1, "firstName", Partitioning.Language, .AddString(1, "firstName", Partitioning.Language,
new StringFieldProperties { Label = "FirstName", IsRequired = true, AllowedValues = ReadOnlyCollection.Create("1", "2") }) new StringFieldProperties())
.AddString(2, "lastName", Partitioning.Language, .AddString(2, "lastName", Partitioning.Language,
new StringFieldProperties { Hints = "Last Name", Editor = StringFieldEditor.Input }) new StringFieldProperties())
.AddBoolean(3, "isAdmin", Partitioning.Invariant, .AddBoolean(3, "isAdmin", Partitioning.Invariant,
new BooleanFieldProperties()) new BooleanFieldProperties())
.AddNumber(4, "age", Partitioning.Invariant, .AddNumber(4, "age", Partitioning.Invariant,
new NumberFieldProperties { MinValue = 1, MaxValue = 10 }) new NumberFieldProperties())
.AddDateTime(5, "birthday", Partitioning.Invariant, .AddDateTime(5, "birthday", Partitioning.Invariant,
new DateTimeFieldProperties()) new DateTimeFieldProperties())
.AddAssets(6, "pictures", Partitioning.Invariant, .AddAssets(6, "pictures", Partitioning.Invariant,
@ -61,7 +60,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.MongoDb
new ReferencesFieldProperties()) new ReferencesFieldProperties())
.AddString(8, "dashed-field", Partitioning.Invariant, .AddString(8, "dashed-field", Partitioning.Invariant,
new StringFieldProperties()) new StringFieldProperties())
.Update(new SchemaProperties { Hints = "The User" }); .Update(new SchemaProperties());
var schema = A.Dummy<ISchemaEntity>(); var schema = A.Dummy<ISchemaEntity>();
A.CallTo(() => schema.Id).Returns(Guid.NewGuid()); A.CallTo(() => schema.Id).Returns(Guid.NewGuid());
@ -144,7 +143,16 @@ namespace Squidex.Domain.Apps.Entities.Contents.MongoDb
} }
[Fact] [Fact]
public void Should_make_query_date_field_created() public void Should_make_query_with_empty_test()
{
var i = F(FilterBuilder.Empty("data/firstName/iv"), true);
var o = C("{ '$or' : [{ 'dd.1.iv' : { '$exists' : false } }, { 'dd.1.iv' : null }, { 'dd.1.iv' : '' }, { 'dd.1.iv' : [] }] }");
Assert.Equal(o, i);
}
[Fact]
public void Should_make_query_with_datetime_data()
{ {
var i = F(FilterBuilder.Eq("data/birthday/iv", InstantPattern.General.Parse("1988-01-19T12:00:00Z").Value)); var i = F(FilterBuilder.Eq("data/birthday/iv", InstantPattern.General.Parse("1988-01-19T12:00:00Z").Value));
var o = C("{ 'do.5.iv' : '1988-01-19T12:00:00Z' }"); var o = C("{ 'do.5.iv' : '1988-01-19T12:00:00Z' }");

18
tests/Squidex.Infrastructure.Tests/Queries/ODataConversionTests.cs

@ -229,6 +229,24 @@ namespace Squidex.Infrastructure.Queries
Assert.Equal(o, i); Assert.Equal(o, i);
} }
[Fact]
public void Should_parse_filter_with_empty()
{
var i = Q("$filter=empty(lastName)");
var o = C("Filter: empty(lastName)");
Assert.Equal(o, i);
}
[Fact]
public void Should_parse_filter_with_empty_to_true()
{
var i = Q("$filter=empty(lastName) eq true");
var o = C("Filter: empty(lastName)");
Assert.Equal(o, i);
}
[Fact] [Fact]
public void Should_parse_filter_with_contains() public void Should_parse_filter_with_contains()
{ {

Loading…
Cancel
Save