> ### Description > RFC rendered [here](https://github.com/hasura/graphql-engine-mono/blob/rakeshkky/rfc/computed-fields-filter/rfcs/computed-fields-filters-perms-orderby.md) PR-URL: https://github.com/hasura/graphql-engine-mono/pull/1642 GitOrigin-RevId: 69b7d11c9e85d0c539564b39d254baac71ce20f7
4.6 KiB
Note: This RFC assumes computed fields for Postgres backend.
OSS issue: https://github.com/hasura/graphql-engine/issues/3772
Before we proceed to the specification, we shall address the known limitation
Limitation
All the undermentioned implementations assumes computed field function has table row input and/or
session (json
type) input arguments. But we support computed fields with functions having multiple arguments.
Input values for additional arguments are provided via GraphQL field arguments.
For example, defining get_articles
computed field for author
table with get_articles(table_input author, search text)
SQL
function to return author's articles containing search
keyword.
query {
author {
id
name
get_articles(search: "Covid 19"){
title
content
}
}
}
It is complex to support such additional function inputs via GraphQL arguments. So, here I'm assuming the following limitation:
Allow filter/order by/permission for computed fields with no input arguments other than table row and session json input types
Filter
Reference OSS ticket: https://github.com/hasura/graphql-engine/issues/7100
Currently, we only support table columns and relationships (object and array) to filter rows in any GraphQL query. For example, to fetch an author whose id
is 1
the query would be (using column in filter)
query {
authors(where: {id: {_eq: 1}}){
id
first_name
last_name
}
}
Similarly, to fetch articles whose author
's first_name
is 'Bob', the query would be (using object relation in filter)
query {
articles(where: {author: {first_name: {_eq: "Bob"}}}){
id
title
}
}
Now, I defined a computed field full_name
to the author
table using the following SQL function
CREATE OR REPLACE FUNCTION public.full_name(author_table author)
RETURNS text
LANGUAGE sql
STABLE
AS $function$
SELECT author_table.first_name || ' ' || author_table.last_name
$function$
I should able to fetch an author whose full_name
is 'Bob Morley'
query {
authors(where: {full_name: {_eq: "Bob Morley"}}){
id
full_name
}
}
The above query isn't possible currently and hence, we need to support computed fields in filter expression (where
clause).
Approach
SELECT "base".* FROM "authors" AS "base" WHERE "full_name"("base") = 'Bob Morley'
Simply, our approach is to use the SQL function in the WHERE
expression of the generated SQL. So, aforementioned GraphQL query
translates to
SELECT
coalesce(json_agg("root"), '[]') AS "root"
FROM
(
SELECT
row_to_json(
(
SELECT
"_2_e"
FROM
(
SELECT
"_1_root.base"."first_name" AS "first_name",
"_1_root.base"."last_name" AS "last_name",
"public"."user_full_name"("_1_root.base") AS "full_name"
) AS "_2_e"
)
) AS "root"
FROM
(
SELECT
*
FROM
"public"."user" AS "_0_base"
WHERE
(
("public"."user_full_name"("_0_base".*)) = (('Bob Morley') :: text)
)
) AS "_1_root.base"
) AS "_3_root"
Permission
Reference OSS ticket: https://github.com/hasura/graphql-engine/issues/7102
Just like using computed fields in where
expression, similarly we need have an option to include computed fields in permission
check
and filter
expression
For example, I need to define a select permission on author
table whose full_name
is like 'Bob'
- type: create_select_permission
args:
table:
name: author
role: user
permission:
columns: '*'
filter:
full_name:
_like: 'Bob'
Approach
Similar to filtering
approach, we generate where
expression with the filter
/check
expression provided
in the permission metadata definition
Order by
Reference OSS ticket: https://github.com/hasura/graphql-engine/issues/7103
Enable using computed fields in order by expresssion. For example, fetch authors ordering by full_name
query {
authors(order_by: {full_name: desc}){
id
first_name
}
}
Approach
We extract computed fields with proper aliases and use the same in the ORDER BY
SQL expression.
The generated SQL will look like
SELECT
computed_field_function("table_alias") AS "computed_field_alias"
(SELECT * FROM our_table) AS "table_alias"
ORDER BY
"computed_field_alias" DESC