Bug: `@cascade` directive ignores graphql aliases

Report a GraphQL Bug

What edition and version of Dgraph are you using?

Edition:

  • SlashGraphQL
  • Dgraph (community edition/Dgraph Cloud)

If you are using the community edition or enterprise edition of Dgraph, please list the version:

Dgraph Version
Dgraph version   : v21.03.1
Dgraph codename  : rocket-1

Have you tried reproducing the issue with the latest release?

Yes, I’m encountering this issue while using

docker run --rm -it -p 8000:8000 -p 8080:8080 -p 9080:9080 dgraph/standalone:latest

Steps to reproduce the issue (paste the query/schema if possible)

Given the following schema:

type ContactList @withSubscription {
  id: ID!
  name: String! @search(by: [regexp])
  abbreviation: String! @search(by: [regexp])
  label: Boolean! @search
  description: String
  entries: [Contact!]! @hasInverse(field: contactLists)
}

interface Contact @withSubscription {
  id: ID!
  identifierIndex: String @search(by: [regexp])
  contactLists: [ContactList!]!
}

type ContactPerson implements Contact @withSubscription {
  nickname: String @search(by: [fulltext])
  firstName: String @search(by: [fulltext])
  firstNamePronunciation: String
  middleName: String @search(by: [fulltext])
  middleNamePronunciation: String
  lastName: String @search(by: [fulltext])
  lastNamePronunciation: String
}

And this query:

query GetContacts($selectedContactListIds: [ID!], $filter: String) {
  queryContact(
    order: { asc: identifierIndex }
    filter: { identifierIndex: { regexp: $filter } }
  ) @cascade(fields: ["contactLists"]) {
    __typename
    id

    contactLists(filter: { id: $selectedContactListIds }) {
      id
    }

    contactListLabels: contactLists(
      filter: { label: true }
      order: { asc: abbreviation }
    ) {
      id
      abbreviation
      label
      description
    }

    ... on ContactPerson {
      nickname
      firstName
      middleName
      lastName
    }
  }
}

Expected behaviour and actual result.

I expect the contacts returned from the above query to be the same as the contacts returned from this query:

query GetContacts($selectedContactListIds: [ID!], $filter: String) {
  queryContact(
    order: { asc: identifierIndex }
    filter: { identifierIndex: { regexp: $filter } }
  ) @cascade(fields: ["contactLists"]) {
    __typename
    id

    contactLists(filter: { id: $selectedContactListIds }) {
      id
    }

    ... on ContactPerson {
      nickname
      firstName
      middleName
      lastName
    }
  }
}

That is to say, I expect @cascade(fields: ["contactLists"]) to cascade the contactLists field but not the contactListLabels: contactLists field (which is an alias of the contactLists field. At the moment however, @cascade appears to be enforced on both the contactLists and contactListLabels fields in the queries. This means that, returned contacts must have edges to $selectedContactListIds and those contact lists must also have label: true which is surprising and undesirable.

At the moment, it’s unclear if there is a work around for this issue. Theoretically, if #13560 is landed, it will work around my specific issue, but this bug will still be problematic in general.

2 Likes

After some thought, I suspected that this issue could be worked around using a custom DQL resolver. However, this turns out not to be possible because custom DQL resolver variables can’t accept lists.

  • For variables, only scalar GraphQL arguments like Boolean, Int, Float, etc are allowed. Lists and Object types are not allowed to be used as variables with DQL queries.