Skip to content

Row-level filtering #219

@molexx

Description

@molexx

Whilst #163 is about hiding certain fields in the schema, there is a separate need to hide certain rows from the results depending on the query's context. As determining the filtering depends on the context, variables and db data at execution time the filter code needs to be run per-query as part of its execution. Usually (always?) that code will need to be Entity-specific, and may depend on the data in related Entities. My immediate use-case is by relation to the currently logged in user but let's design a generic system for other use-cases.

Requirements

  • allow predicates to be defined per-entity class which will be applied to all queries using it

  • the predicates must apply whenever the entity is referenced via relationships, not just top-level. e.g. if 'Luke Skywalker' is filtered out we will not see him on a query for all Characters, nor will we see him as a friend if we query for all Characters and include their friends list in the projection.

  • predicates must be able to join to other tables. For example this would allow querying of friends only.

  • predicates should re-use joins, otherwise a query in a large schema where every entity has a filter will become very large and slow

  • allow sets of predicates to be enabled/disabled at runtime depending on the context

Implementation considerations

  • Hibernate has @Filter which looks like it should do this, but:

    • I have been unable to reference other tables/entities, hibernate bug HHH-12967 for this has been open over a year
    • if tables are already used in the query I'm not sure if @Filter will re-use those joins or add them again under a different alias which will affect performance on a reasonably sized schema
  • As @igdianov suggested it would be nice to be able to specify the predicates as a JPQL string, which could include SpEL referencing ExecutorContext properties. Spring-data's use of this is relatively simple as the entire string is the query, to use here we would need to merge the string in with the rest of the generated JPQL. Would it be easy to re-use existing joins when doing that?

  • Add methods to Entity classes which return List<Predicate> and are annotated with new annotation @GraphQLRowFilter. For user and testing flexibility the filters can be named and a list of active filters can be passed to the executionEnvironment.


I'm currently experimenting with option 3 from above, calling the Entity methods from getFieldPredicates() and using reuseFetch() to try and keep the queries smaller.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions