Skip to content
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

Fixes part removal in where if the index has multiple aliases #3217

Merged
merged 2 commits into from
Feb 20, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using GraphQL.Resolvers;
Expand Down Expand Up @@ -108,11 +109,14 @@ private async Task<IQuery<ContentItem>> FilterWhereArguments(
// Add all provided table alias to the current predicate query
var providers = context.ServiceProvider.GetServices<IIndexAliasProvider>();
var indexes = new Dictionary<string, IndexAlias>(StringComparer.OrdinalIgnoreCase);
var indexAliases = new List<string>();

foreach (var aliasProvider in providers)
{
foreach (var alias in aliasProvider.GetAliases())
{
predicateQuery.CreateAlias(alias.Alias, alias.Index);
indexAliases.Add(alias.Alias);

if (!indexes.ContainsKey(alias.Index))
{
Expand All @@ -122,7 +126,7 @@ private async Task<IQuery<ContentItem>> FilterWhereArguments(
}

var expressions = Expression.Conjunction();
BuildWhereExpressions(where, expressions, null, indexes);
BuildWhereExpressions(where, expressions, null, indexAliases);

var whereSqlClause = expressions.ToSqlString(predicateQuery);
query = query.Where(whereSqlClause);
Expand Down Expand Up @@ -202,25 +206,25 @@ private static IQuery<ContentItem, ContentItemIndex> FilterVersion(IQuery<Conten
return query;
}

private void BuildWhereExpressions(JToken where, Junction expressions, string tableAlias, Dictionary<string, IndexAlias> indexes)
private void BuildWhereExpressions(JToken where, Junction expressions, string tableAlias, IEnumerable<string> indexAliases)
{
if (where is JArray array)
{
foreach (var child in array.Children())
{
if (child is JObject whereObject)
{
BuildExpressionsInternal(whereObject, expressions, tableAlias, indexes);
BuildExpressionsInternal(whereObject, expressions, tableAlias, indexAliases);
}
}
}
else if (where is JObject whereObject)
{
BuildExpressionsInternal(whereObject, expressions, tableAlias, indexes);
BuildExpressionsInternal(whereObject, expressions, tableAlias, indexAliases);
}
}

private void BuildExpressionsInternal(JObject where, Junction expressions, string tableAlias, Dictionary<string, IndexAlias> indexes)
private void BuildExpressionsInternal(JObject where, Junction expressions, string tableAlias, IEnumerable<string> indexAliases)
{
foreach (var entry in where.Properties())
{
Expand All @@ -232,10 +236,14 @@ private void BuildExpressionsInternal(JObject where, Junction expressions, strin
var property = values[0];
if (!string.IsNullOrEmpty(tableAlias))
{
// check if we need to stick a prefix of 'Part' on the alias.
if (indexes != null && indexes.TryGetValue($"{tableAlias}PartIndex", out var indexAlias))
{
tableAlias = indexAlias.Alias;
// check if we need to stick a suffix of 'Part' on the alias.
if (!tableAlias.EndsWith("Part")) {

var aliasLookup = indexAliases.FirstOrDefault(x => x.Equals($"{tableAlias}Part", StringComparison.OrdinalIgnoreCase));
if (aliasLookup != null)
{
tableAlias = aliasLookup;
}
}

property = $"{tableAlias}.{property}";
Expand All @@ -246,24 +254,24 @@ private void BuildExpressionsInternal(JObject where, Junction expressions, strin
if (string.Equals(values[0], "or", StringComparison.OrdinalIgnoreCase))
{
expression = Expression.Disjunction();
BuildWhereExpressions(entry.Value, (Junction)expression, tableAlias, indexes);
BuildWhereExpressions(entry.Value, (Junction)expression, tableAlias, indexAliases);
}
else if (string.Equals(values[0], "and", StringComparison.OrdinalIgnoreCase))
{
expression = Expression.Conjunction();
BuildWhereExpressions(entry.Value, (Junction)expression, tableAlias, indexes);
BuildWhereExpressions(entry.Value, (Junction)expression, tableAlias, indexAliases);
}
else if (string.Equals(values[0], "not", StringComparison.OrdinalIgnoreCase))
{
expression = Expression.Conjunction();
BuildWhereExpressions(entry.Value, (Junction)expression, tableAlias, indexes);
BuildWhereExpressions(entry.Value, (Junction)expression, tableAlias, indexAliases);
expression = Expression.Not(expression);
}
else if (entry.HasValues && entry.Value.Type == JTokenType.Object)
{
// Loop through the part's properties, passing the name of the part as the table tableAlias.
// This tableAlias can then be used with the table alias to index mappings to join with the correct table.
BuildWhereExpressions(entry.Value, expressions, values[0], indexes);
BuildWhereExpressions(entry.Value, expressions, values[0], indexAliases);
}
else
{
Expand Down
74 changes: 71 additions & 3 deletions test/OrchardCore.Tests/Apis/GraphQL/ContentItemsFieldTypeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,51 @@ public async Task ShouldFilterOnMultipleIndexesOnSameAlias()
Assert.False(animals.First().As<Animal>().IsHappy);
}
}

[Fact]
public async Task ShouldFilterPartsWithoutPartPrefix()
carlwoodhouse marked this conversation as resolved.
Show resolved Hide resolved
{
_store.RegisterIndexes<AnimalIndexProvider>();

using (var services = new FakeServiceCollection())
{
services.Populate(new ServiceCollection());
services.Services.AddScoped(x => _store.CreateSession());
services.Services.AddScoped<IIndexProvider, ContentItemIndexProvider>();
services.Services.AddScoped<IIndexProvider, AnimalIndexProvider>();
services.Services.AddScoped<IIndexAliasProvider, MultipleAliasIndexProvider>();
services.Build();

var retrunType = new ListGraphType<StringGraphType>();
retrunType.ResolvedType = new StringGraphType() { Name = "Animal" };

var context = new ResolveFieldContext
{
Arguments = new Dictionary<string, object>(),
UserContext = new GraphQLContext
{
ServiceProvider = services
},
ReturnType = retrunType
};

var ci = new ContentItem { ContentType = "Animal", Published = true, ContentItemId = "1", ContentItemVersionId = "1" };
ci.Weld(new AnimalPart { Name = "doug" });

var session = ((GraphQLContext)context.UserContext).ServiceProvider.GetService<ISession>();
session.Save(ci);
await session.CommitAsync();

var type = new ContentItemsFieldType("Animal", new Schema());


carlwoodhouse marked this conversation as resolved.
Show resolved Hide resolved
context.Arguments["where"] = JObject.Parse("{ animal: { name: \"doug\" } }");
var dogs = await ((AsyncFieldResolver<IEnumerable<ContentItem>>)type.Resolver).Resolve(context);

Assert.Single(dogs);
Assert.Equal("doug", dogs.First().As<AnimalPart>().Name);
}
}
}

public class Animal : ContentPart
Expand All @@ -194,6 +239,8 @@ public class Animal : ContentPart
public bool IsScary { get; set; }
}

public class AnimalPart : Animal { };

public class AnimalIndex : MapIndex
{
public string Name { get; set; }
Expand All @@ -208,7 +255,9 @@ public override void Describe(DescribeContext<ContentItem> context)
{
return new AnimalIndex
{
Name = contentItem.As<Animal>().Name
Name = contentItem.As<Animal>() != null ?
contentItem.As<Animal>().Name
: contentItem.As<AnimalPart>().Name
};
});
}
Expand All @@ -227,10 +276,23 @@ public override void Describe(DescribeContext<ContentItem> context)
context.For<AnimalTraitsIndex>()
.Map(contentItem =>
{
var animal = contentItem.As<Animal>();

if (animal != null)
{
return new AnimalTraitsIndex
{
IsHappy = contentItem.As<Animal>().IsHappy,
IsScary = contentItem.As<Animal>().IsScary
};
}

var animalPartSuffix = contentItem.As<AnimalPart>();

return new AnimalTraitsIndex
{
IsHappy = contentItem.As<Animal>().IsHappy,
IsScary = contentItem.As<Animal>().IsScary
IsHappy = animalPartSuffix.IsHappy,
IsScary = animalPartSuffix.IsScary
};
});
}
Expand All @@ -252,6 +314,12 @@ public class MultipleAliasIndexProvider : IIndexAliasProvider
Alias = "dogs",
Index = nameof(AnimalIndex),
With = q => q.With<AnimalIndex>()
},
new IndexAlias
{
Alias = nameof(AnimalPart),
Index = nameof(AnimalIndex),
With = q => q.With<AnimalIndex>()
}
};

Expand Down