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

Add record struct support for sort #7166

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,14 @@ private bool TryCreateSortType(
return false;
}

//Record struct will have a generated PrintMembers method while guid/decimals won't
if (runtimeType.Type is { IsValueType: true, IsPrimitive: false } &&
runtimeType.Type.GetMethod("PrintMembers", BindingFlags.NonPublic | BindingFlags.Instance) != null)
{
type = typeof(SortInputType<>).MakeGenericType(runtimeType.Type);
return true;
}

if (runtimeType.Type.IsClass ||
runtimeType.Type.IsInterface)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using CookieCrumble;
using HotChocolate.Data.Sorting;

namespace HotChocolate.Data.Tests;

public class SortInputStructTypesTest : SortTestBase
{

[Fact]
public void SortInputType_RecordStructSortableProperties()
{
// arrange
var builder = SchemaBuilder.New()
.AddQueryType<AccountsQuery>()
.AddSorting();

// act
// assert
builder.Create().MatchSnapshot();
}

[Fact]
public void SortInputType_RecordStructSortableNestedWithSortInputType()
{
// arrange
var builder = SchemaBuilder.New()
.AddQueryType<TestObjectsQuery>()
.AddSorting();

// act
// assert
builder.Create().MatchSnapshot();
}


public class AccountsQuery
{
[UseSorting]
public IQueryable<Account> Accounts() => new List<Account>().AsQueryable();
}

public record struct Account(Guid CorrelationId, string AccountKey, DateOnly BalanceDate, DateTime Created);

public class TestObjectsQuery
{
[UseSorting<TestObjectSortInputType>]
public IQueryable<TestObject> TestObjects() => new List<TestObject>().AsQueryable();
}


public record struct TestObject
{
public Guid ObjectId { get; init; }
public bool IsRoot { get; init; }
public ChildObject Child { get; init; }
}

public record struct ChildObject(NestedId Id, double Amount, decimal Sum);

public record NestedId
{
public Guid ObjectId { get; init; }
}

public class TestObjectSortInputType : SortInputType<TestObject>
{
protected override void Configure(ISortInputTypeDescriptor<TestObject> descriptor)
{
descriptor.Ignore(x => x.IsRoot);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
schema {
query: TestObjectsQuery
}

type ChildObject {
id: NestedId!
amount: Float!
sum: Decimal!
}

type NestedId {
objectId: UUID!
}

type TestObject {
objectId: UUID!
isRoot: Boolean!
child: ChildObject!
}

type TestObjectsQuery {
testObjects(order: [TestObjectSortInput!]): [TestObject!]!
}

input ChildObjectSortInput {
id: NestedIdSortInput
amount: SortEnumType
sum: SortEnumType
}

input NestedIdSortInput {
objectId: SortEnumType
}

input TestObjectSortInput {
objectId: SortEnumType
child: ChildObjectSortInput
}

enum SortEnumType {
ASC
DESC
}

"The `@specifiedBy` directive is used within the type system definition language to provide a URL for specifying the behavior of custom scalar definitions."
directive @specifiedBy("The specifiedBy URL points to a human-readable specification. This field will only read a result for scalar types." url: String!) on SCALAR

"The built-in `Decimal` scalar type."
scalar Decimal

scalar UUID @specifiedBy(url: "https:\/\/tools.ietf.org\/html\/rfc4122")
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
schema {
query: AccountsQuery
}

type Account {
correlationId: UUID!
accountKey: String!
balanceDate: Date!
created: DateTime!
}

type AccountsQuery {
accounts(order: [AccountSortInput!]): [Account!]!
}

input AccountSortInput {
correlationId: SortEnumType
accountKey: SortEnumType
balanceDate: SortEnumType
created: SortEnumType
}

enum SortEnumType {
ASC
DESC
}

"The `@specifiedBy` directive is used within the type system definition language to provide a URL for specifying the behavior of custom scalar definitions."
directive @specifiedBy("The specifiedBy URL points to a human-readable specification. This field will only read a result for scalar types." url: String!) on SCALAR

"The `Date` scalar represents an ISO-8601 compliant date type."
scalar Date

"The `DateTime` scalar represents an ISO-8601 compliant date time type."
scalar DateTime @specifiedBy(url: "https:\/\/www.graphql-scalars.com\/date-time")

scalar UUID @specifiedBy(url: "https:\/\/tools.ietf.org\/html\/rfc4122")