graphile / crystal

🔮 Graphile's Crystal Monorepo; home to Grafast, PostGraphile, pg-introspection, pg-sql2 and much more!
https://graphile.org/
Other
12.63k stars 572 forks source link

Procedure with enum arrays #417

Closed danielbuechele closed 7 years ago

danielbuechele commented 7 years ago

I created a procedure accepting an array of enums as argument, like this:

CREATE FUNCTION search_articles(type_filter article_type[]) ...

which creates a GraphQL field that can be queried like this:

searchArticles(typeFilter:[VIDEO,PHOTO])

However, this fails in SQL, saying function searchArticles(text[]) does not exists. The problem seems to be, that the array of enums is translated to a text array. Probably because in JavaScript the argument creates an array ['VIDEO','PHOTO'], because JavaScript is not aware of existing enums, which is then transformed to SQL.

On a first look, it looks like we can add some special case here: https://github.com/postgraphql/postgraphql/blob/master/src/postgraphql/schema/procedures/createPgProcedureSqlCall.ts#L36

calebmer commented 7 years ago

Another, simpler option would be to add type casting here: https://github.com/postgraphql/postgraphql/blob/master/src/postgres/inventory/type/PgEnumType.ts#L33 or here: https://github.com/postgraphql/postgraphql/blob/master/src/postgres/inventory/type/PgListType.ts#L40

So that it generates either:

array['x'::article_type, 'y'::article_type]

…or:

array['x', 'y']::article_type[]

Please feel free to submit a PR adding this casting! The former is easier and so probably what we want.

benjie commented 7 years ago

Procedure with enum[] arg

benjie commented 7 years ago

If someone fancied simply testing if this works in v4 that would be super helpful 👍

benjie commented 7 years ago

(I think it will.)

benjie commented 7 years ago

Yep; it works:

$ createdb test
$ psql test
[test] # create type test_enum as enum('ONE', 'TWO', 'THREE');
CREATE TYPE
Time: 63.477 ms
[test] # create function second(options test_enum[]) returns test_enum as $$ select options[2]; $$ language sql stable;
CREATE FUNCTION
Time: 8.991 ms
[test] # select second(ARRAY['TWO', 'THREE', 'ONE']::test_enum[]);
 second
--------
 THREE
(1 row)

Time: 0.429 ms
$ postgraphile -c postgres://localhost/test
{
  second(options: [TWO, THREE, ONE])
}
{
  "data": {
    "second": "THREE"
  }
}