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

Improve relationship nullability and joins without LATERAL (closes #8977) #10712

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

infnada
Copy link

@infnada infnada commented Mar 30, 2025

Description

Allows users to manually describe the nullability of a relationship (Object & Array), either by statically specifying it in the metadata configuration or dynamically by using new directives in the graphql query.

Also exposes another directive to use JOINS without LATERAL on Object relationships.

NOTE: Currently there is not much documentation on when Hasura uses LEFT OUTER vs INNER joins but it is quite simple. I think a more detailed documentation is needed on that, specially the implication of using Views (which is my case).

Simple performance test (check changelog for more information about directives):

query Query {
  assets(limit: 2, order_by: {firstAppearedInBlock: {forgedAt: asc}}) {
    assetId
    firstAppearedInBlock @nullable @lateral {
      epoch @nullable @lateral {
        number
      }
      transactions(limit: 2, order_by: {id: desc}) @nullable {
        id
        outputs(where: {index: {_eq: "0"}}) @nullable {
          id
          paymentAddress @nullable @lateral {
            address
            firstAppearedInTx @nullable @lateral {
              id
            }
          }
        }
      }
    }
  }
}

Before (without directives):
Response Time
2045689 ms (34 minutes)
Response Size
708 bytes

After (with directives):
Response Time
5087 ms (5 seconds)
Response Size
716 bytes

Changelog

Component : server
Type: feature
Product: community-edition

Long Changelog

  • Add a new nullable: bool option in manual_configuration metadata configuration. It follows the same logical_models nullability schema. This option is passed into RelInfo to latter be used to calculate LEFT OUTER vs INNER joins.
    -- This is also implemented for Array relationships. It may not make much sense, because you can filter it and end up with no results, but the core of this is to just improve* query performance.
  • Add a new INNER JOIN (without LATERAL) generated query for Object relationships. This massively improves* performance specially on nested order_by
  • Add two new directives @nullable & @lateral to dynamically configure an Array or Object relationship to make use of this new feature. This allows to configure querys with LEFT OUTER JOIN LATERAL & INNER JOIN (LATERAL) at execution time
  • Modify the schema-parser to extract the directives information (only selectionSets) and inject them into the necessary components.
    -- @nullable(override_to: boolean) -> defaults to False
    -- @lateral(override_to: boolean) -> defaults to False

NOTE: @nullable directive overrides the new nullable option set by manual_configuration and also overrides any previous nullability (FKEY joins)

* More tests needed to check performance improvements

Related Issues

May close (at least for me) #8977
Improves on closed #1965
May close by setting nullable option on metadata #7662
May close by using the new lateral (to a false) directive #5949
May close #7079
May close #6448
May help on #8333
...

Extra

This can be the start of fixing other issues like being able to rename fields. You only need to modify the parser like i did for selectionSets but for simple selections and apply the renaming in the query:

query Query {
  table {
    field @rename(to: "something")
  }

Solution and Design

  • Implement non LATERAL joins for object relationships
  • Implement manual nullability

Steps to test and verify

Use the directives specially on nested order_by queries

Limitations, known bugs & workarounds

I currently only tested SELECT queries with array/object_relationships with manual_configuration. A lot more tests are needed...

By not using LATERAL joins the order of the joins becomes a lot more important. Checks on this (sorting joins) are needed. That's why i configured it as a directive and not a static option in the metadata.

DO NOT MERGE TIS PR AS-IS. Previously i had 0 knowledge on Hasura codebase, and 0,1 on Haskell. The code, more than the logic, was heavily created using AI it may contain unexpected results. This aims to start a conversation to finally solve in some way or another a long running issue...

Metadata

Does this PR add a new Metadata feature?

  • [ x] Yes

GraphQL

  • [ x] New GraphQL schema is being generated:
    • It modifies the nullability of a field

Breaking changes

  • [ x] No Breaking changes

It should not break nor change the current Hasura execution unless the new metadata field is present or with the use of the new directives.

@infnada infnada requested a review from a team as a code owner March 30, 2025 01:52
@CLAassistant
Copy link

CLAassistant commented Mar 30, 2025

CLA assistant check)
All committers have signed the CLA.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants