9

I have a query like this:

query getUsers ($setId: Int) {
  user(where: { user_sets: { set_id: { _in: [$setId] } } }) {
    id
    name
    status
    user_sets {
      set {
        name
      }
    }
    # more fields...
  }
}

What I'm looking for, is a way to not apply the where filter and give all entries if $setId is null. I'd like to avoid dynamically writing the query - it'd be easy to do something like this, but we want queries in static .graphql files:

const query = `
query getUsers (${ setId ? '$setId: Int' : ''}) {
  user(${ setId ? 'where: { user_sets: { set_id: { _in: [$setId] } } }' : '' }) {
`

Some things I've tried:

  • Using GraphQL directives like @skip and @include, but it seems these only apply to fields returned, not to any part of a where filter
  • Using Hasura boolExps like _is_null and _or, but it seems these can't test variables directly, they can only compare variables to columns contents
user56reinstatemonica8
  • 27,132
  • 16
  • 87
  • 109

2 Answers2

5

It seems like matching all if the variable is null is the default behaviour if the _eq boolExp is used. I wasn't seeing this because this query was using _in.

Changing to this gives all items if $setId is passed as null:

query getUsers ($setId: Int) {
  user(where: { user_sets: { set_id: { _eq: $setId } } }) {
    id
    name
    status
    user_sets {
      set {
        name
      }
    }
    # more fields...
  }
}

This is because Hasura follows SQL by having null not comparable to anything (only _is_null can match values that are set as null in nullable columns).

Therefore, { _eq: null } logically can't match anything, so it's simply optimised away. This:

(where: { user_sets: { set_id: { _eq: $setId } } })

...becomes this:

(where: { user_sets: { set_id: {} } }

...and because {} is trueExp, treated as true, it optimises away to be effectively WHERE 'true'.

user56reinstatemonica8
  • 27,132
  • 16
  • 87
  • 109
  • 2
    do you have a solution for other options such as `gte`, `lte` and empty arrays for `in`? – Kerem Jan 06 '21 at 10:42
3

You can use bool expressions as binding variables for such situations

query getUsers ($condition: user_bool_exp!) {
  user (where: $condition) {
    id
    name
    status
    user_sets {
      set {
        name
      }
    }
    # more fields...
  }
}

And you can build conditions depending on your variables

{ condition: { user_sets: { set_id: { _in: [$setId] } } } }

or

{ condition: { user_sets: {} }
olegen
  • 43
  • 5