Hasura v2.10.0 Release Notes

  • ๐Ÿ‘ Introducing Apollo Federation v1 support (experimental)

    HGE can now be used as a subgraph in an Apollo federated GraphQL server. โœ… You can read more about this feature in the docs.

    This is an experimental feature (can be enabled by setting HASURA_GRAPHQL_EXPERIMENTAL_FEATURES: apollo_federation). This is supported over all databases. To expose a table in an Apollo federated gateway, we need ๐Ÿ“‡ to enable Apollo federation in its metadata. This can be done via the *_track_table metadata API or via Modify Table page in console.

    Enabling Apollo Federation on a table would add the @key directive in the GraphQL schema with fields argument set to the primary key of the table (say id), i.e:

    type user @key(fields: "id") {
      id: Int!
      name: String
      ...
    }
    

    Behaviour changes

    • server: When providing a JSON path in a JWT claims map, you can now use double-quotes as well as single-quotes. Escaped characters in strings will now be honored appropriately, in the same way as JSON.

    • server: In certain error messages, JSON paths will use double-quotes instead of single-quotes to represent field access.

    For example, instead of $.args['$set'], you will see $.args["$set"].

    • ๐Ÿ“‡ cli: Use 2-spaces indent for GraphQL content in metadata instead of tabs (#8469)

    Example: Old Behaviourmetadata/query_collections.yml New Behaviourmetadata/query_collections.yml

    • name: allowed-queries definition: queries:
      • name: getAlbums query: | query getAlbums { albums { id title } }
    • name: allowed-queries definition: queries:
      • name: getAlbums query: | query getAlbums { albums { id title } }

    โšก๏ธ Update multiple records for Postgres

    โšก๏ธ We are introducing a new way to allow updating multiple records in the same transaction for Postgres sources (#2768).

    For example, the following query can be used to run the equivalent of two update_by_pk in a single transaction:

    update_artist_many(
      updates: [
        { where: { id: { _eq: 1 } },
          _set: { name: "new name", description: "other" }
        }
        { where: { id: { _eq: 2 } },
          _set: { name: "new name" }
        }
        ]
    ) {
      affected_rows
      returning {
        name
      }
    }
    

    โšก๏ธ However, this feature allows arbitrary updates, even when they overlap:

    update_artist_many(
      updates: [
        { where: { id: { _lte: 3 } },
          _set: { name: "first", description: "other" }
        }
        { where: { id: { _eq: 2 } },
          _set: { name: "second" }
        }
        { where: { id: { _gt: 2 } },
          _set: { name: "third", description: "hello" }
        }
        { where: { id: { _eq: 1 } },
          _set: { name: "done" }
        }
        ]
    ) {
      affected_rows
      returning {
        id
        name
      }
    }
    

    Given the table looked like this before the query:

    id name description
    1 one d1
    2 two d2
    3 three d3
    4 four d4

    After executing the query, the table will look like:

    id name description
    1 done other
    2 second other
    3 third hello
    4 third hello

    The returned data will look like this:

    {
      "data": {
        "update_artist_many": [
          {
            "affected_rows": 3,
            "returning": [
              {
                "id": 1,
                "name": "first"
              },
              {
                "id": 2,
                "name": "first"
              },
              {
                "id": 3,
                "name": "first"
              }
            ]
          },
          {
            "affected_rows": 1,
            "returning": [
              {
                "id": 2,
                "name": "second"
              }
            ]
          },
          {
            "affected_rows": 2,
            "returning": [
              {
                "id": 3,
                "name": "third"
              },
              {
                "id": 4,
                "name": "third"
              }
            ]
          },
          {
            "affected_rows": 1,
            "returning": [
              {
                "id": 1,
                "name": "done"
              }
            ]
          }
        ]
      }
    }
    

    The way it works is:

    • โšก๏ธ we allow arbitrary where clauses (just like in a regular update)
    • we allow arbitrary updates (_set, _inc, etc., depending on the field type)
    • โšก๏ธ we run each update in sequence, in a transaction (if one of them fails, everything is rolled back)
    • we collect the return value of each query and return a list of results

    Please submit any feedback you may have for this feature at https://github.com/hasura/graphql-engine/issues/2768.

    Error message syntax

    We are slowly standardizing the format of error messages, especially with regards to the way values are quoted.

    ๐Ÿ“œ Any errors generated during the parsing of GraphQL or the construction of the schema might have changed the way they quote certain values. For example, GraphQL names are now always quoted with single quotes, leading to changes such as the following.

    Before:

    field "nonexistent_root_field" not found in type: 'query_root'
    

    After:

    field 'nonexistent_root_field' not found in type: 'query_root'
    

    โšก๏ธ If you are depending on the specific text of an error message and/or parsing the message, you may need to update your code accordingly.

    Further changes are forthcoming along similar lines.

    ๐Ÿ› Bug fixes and improvements

    • server: Kriti basicFunctions now available for REST Connectors and Webhook Transforms
    • server: Fix bug where Hasura SQL trigger was not dropped when MS SQL Server source is dropped
    • server: Delete event trigger related database SQL triggers from tables when they are untracked
    • server: Use root_field_namespace as prefix for remote schema (fix #8438)
    • 0๏ธโƒฃ server: Fix prefix/suffix behaviour for graphql-default naming convention (fix #8544)
    • server: Fix namespace visibility during introspection (fix #8434)
    • ๐Ÿ“‡ server: Create missing SQL triggers, if any, while reloading metadata and startup.
    • 0๏ธโƒฃ server: Fix name/enum transformation bugs in graphql-default naming convention (fix #8640)
    • server: Parameterize array variables in generated SQL for queries and subscriptions
    • server: Make postgres-client-cert fields: sslcert, sslkey and sslpassword optional
    • โšก๏ธ server: Add *_update_source API to update configuration of a connected database (See docs)
    • server: Changes to the Rest Endpoints OpenAPI specification:
      • The nullability of items in the output is now always correctly reported
      • Scalars other than UUID are more consistently inlined
      • Objects now have a title and, when available, the same description as in the GraphQL schema
    • ๐Ÿ“ฆ server: Bump Kriti package version to support optional variable lookup in string interpolation (fix #8574)
    • โ†ช server: Generate unique intermediate column names in PostgreSQL SQL queries to workaround PostgreSQL's identifier length limitation (fix #3796)
    • console: Hide TimescaleDB internal schemas from data tab for connected TimescaleDB databases
    • ๐Ÿ‘ console: Support naming convention in source customization for PostgreSQL DBs
    • console: Fix bug where "Analyze" button in the API explorer would stay in analyzing state after analyze failed
    • 0๏ธโƒฃ console: Fix missing remote database relationship info for databases other than default on new table relationships page
    • ๐Ÿ— build: Changes to the hasura/graphql-engine Docker image:
      • Default graphql-engine docker images (hasura/graphql-engine:<VERSION>) now use an Ubuntu base instead of Debian.
      • Debian flavour of images (hasura/graphql-engine:<VERSION>.debian) are still published to Docker Hub.