Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Supporting new `cds-plugin` technique for zero configuration
- Support for filtering by `null` values
- Allow multiple filters on the same field, with the same operator, that are logically joined by `AND`. For example, filtering for all books with titles that contain both strings, "Wuthering" and "Heights":
```graphql
{
AdminService {
Books(filter: { title: { contains: ["Wuthering", "Heights"] } }) {
nodes {
title
}
}
}
}
```

### Changed

Expand Down
2 changes: 1 addition & 1 deletion lib/resolvers/parse/ast/enrich.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const _traverseArgumentOrObjectField = (info, argumentOrObjectField, _fieldOr_ar
argumentOrObjectField.value = substituteVariable(info, value)
break
case Kind.LIST:
_traverseListValue(info, value, type.getFields())
_traverseListValue(info, value, type.getFields?.())
break
case Kind.OBJECT:
_traverseObjectValue(info, value, type.getFields())
Expand Down
2 changes: 1 addition & 1 deletion lib/resolvers/parse/ast/fromObject.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const _objectToObjectValue = object => ({

const _arrayToListValue = array => ({
kind: Kind.LIST,
values: array.map(a => _objectToObjectValue(a))
values: array.map(a => _variableToValue(a))
})

const _variableToValue = variable => {
Expand Down
19 changes: 14 additions & 5 deletions lib/resolvers/parse/ast2cqn/where.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,27 @@ const GQL_TO_CDS_QL_OPERATOR = {
const _gqlOperatorToCdsOperator = gqlOperator =>
GQL_TO_CDS_QL_OPERATOR[gqlOperator] || GQL_TO_CDS_STRING_OPERATIONS[gqlOperator]

const _objectFieldTo_xpr = (objectField, columnName) => {
const gqlOperator = objectField.name.value
const _to_xpr = (ref, gqlOperator, value) => {
const cdsOperator = _gqlOperatorToCdsOperator(gqlOperator)

const ref = { ref: [columnName] }
const val = { val: objectField.value.value }
const val = { val: value }

if (STRING_OPERATIONS[gqlOperator]) return [{ func: cdsOperator, args: [ref, val] }]

return [ref, cdsOperator, val]
}

const _objectFieldTo_xpr = (objectField, columnName) => {
const ref = { ref: [columnName] }
const gqlOperator = objectField.name.value

if (objectField.value.kind === Kind.LIST) {
const _xprs = objectField.value.values.map(value => _to_xpr(ref, gqlOperator, value.value))
return _joinedXprFrom_xprs(_xprs, 'and')
}

return _to_xpr(ref, gqlOperator, objectField.value.value)
}

const _parseObjectField = (objectField, columnName) => {
if (columnName) return _objectFieldTo_xpr(objectField, columnName)

Expand Down
2 changes: 1 addition & 1 deletion lib/schema/args/filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ module.exports = cache => {
const cacheFilterType = cache.get(filterName)
if (cacheFilterType) return cacheFilterType

const fields = Object.fromEntries(operations.map(op => [[op], { type: gqlType }]))
const fields = Object.fromEntries(operations.map(op => [[op], { type: new GraphQLList(gqlType) }]))
const newFilterType = new GraphQLInputObjectType({ name: filterName, fields })
cache.set(filterName, newFilterType)

Expand Down
70 changes: 35 additions & 35 deletions test/schemas/bookshop-graphql.gql
Original file line number Diff line number Diff line change
Expand Up @@ -643,8 +643,8 @@ The `Binary` scalar type represents binary values as `base64url` encoded strings
scalar Binary

input Binary_filter {
eq: Binary
ne: Binary
eq: [Binary]
ne: [Binary]
}

type CatalogService {
Expand Down Expand Up @@ -1293,12 +1293,12 @@ The `Date` scalar type represents date values as strings in the ISO 8601 format
scalar Date

input Date_filter {
eq: Date
ge: Date
gt: Date
le: Date
lt: Date
ne: Date
eq: [Date]
ge: [Date]
gt: [Date]
le: [Date]
lt: [Date]
ne: [Date]
}

"""
Expand All @@ -1307,21 +1307,21 @@ The `Decimal` scalar type represents exact signed decimal values. Decimal repres
scalar Decimal

input Decimal_filter {
eq: Decimal
ge: Decimal
gt: Decimal
le: Decimal
lt: Decimal
ne: Decimal
eq: [Decimal]
ge: [Decimal]
gt: [Decimal]
le: [Decimal]
lt: [Decimal]
ne: [Decimal]
}

input Int_filter {
eq: Int
ge: Int
gt: Int
le: Int
lt: Int
ne: Int
eq: [Int]
ge: [Int]
gt: [Int]
le: [Int]
lt: [Int]
ne: [Int]
}

type Mutation {
Expand All @@ -1340,15 +1340,15 @@ enum SortDirection {
}

input String_filter {
contains: String
endswith: String
eq: String
ge: String
gt: String
le: String
lt: String
ne: String
startswith: String
contains: [String]
endswith: [String]
eq: [String]
ge: [String]
gt: [String]
le: [String]
lt: [String]
ne: [String]
startswith: [String]
}

"""
Expand All @@ -1357,10 +1357,10 @@ The `Timestamp` scalar type represents timestamp values as strings in the ISO 86
scalar Timestamp

input Timestamp_filter {
eq: Timestamp
ge: Timestamp
gt: Timestamp
le: Timestamp
lt: Timestamp
ne: Timestamp
eq: [Timestamp]
ge: [Timestamp]
gt: [Timestamp]
le: [Timestamp]
lt: [Timestamp]
ne: [Timestamp]
}
30 changes: 15 additions & 15 deletions test/schemas/edge-cases/field-named-localized.gql
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,12 @@ input FieldNamedLocalizedService_localized_orderBy {
}

input Int_filter {
eq: Int
ge: Int
gt: Int
le: Int
lt: Int
ne: Int
eq: [Int]
ge: [Int]
gt: [Int]
le: [Int]
lt: [Int]
ne: [Int]
}

type Mutation {
Expand All @@ -138,13 +138,13 @@ enum SortDirection {
}

input String_filter {
contains: String
endswith: String
eq: String
ge: String
gt: String
le: String
lt: String
ne: String
startswith: String
contains: [String]
endswith: [String]
eq: [String]
ge: [String]
gt: [String]
le: [String]
lt: [String]
ne: [String]
startswith: [String]
}
12 changes: 6 additions & 6 deletions test/schemas/model-structure/composition-of-aspect.gql
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,12 @@ type CompositionOfAspectService_input {
}

input ID_filter {
eq: ID
ge: ID
gt: ID
le: ID
lt: ID
ne: ID
eq: [ID]
ge: [ID]
gt: [ID]
le: [ID]
lt: [ID]
ne: [ID]
}

type Mutation {
Expand Down
Loading