Skip to content

Commit 0381fe7

Browse files
tsnobipbenjie
andauthored
Document functions that return table enums (#374)
Co-authored-by: Benjie Gillam <benjie@jemjie.com>
1 parent 21a9218 commit 0381fe7

3 files changed

Lines changed: 91 additions & 3 deletions

File tree

src/pages/postgraphile/computed-columns.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ table type, but, unlike an actual column, the value for this field is the result
99
of calling a function defined in the PostgreSQL schema. This function will
1010
automatically be exposed to the resultant GraphQL schema as a field on the type;
1111
it can accept arguments that influence its result, and may return either a
12-
scalar, record, list or a set. Sets (denoted by `RETURNS SETOF ...`) are exposed
13-
as [connections](/postgraphile/connections/).
12+
scalar, record, [enum](/postgraphile/enums/#functions-returning-table-enums),
13+
list or a set. Sets (denoted by `RETURNS SETOF ...`) are exposed as
14+
[connections](/postgraphile/connections/).
1415

1516
_Performance note: we inline these function calls into the original `SELECT`
1617
statement, so there's no N+1 issues - it's very efficient._

src/pages/postgraphile/custom-queries.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ title: Custom Queries
77
You can add root-level `Query` fields to your GraphQL schema using "Custom
88
Queries". These are PostgreSQL functions, similar to
99
[computed columns](/postgraphile/computed-columns/), that can return scalars,
10-
records, lists or sets. Sets (denoted by `RETURNS SETOF ...`) are exposed as
10+
records, [enums](/postgraphile/enums/#functions-returning-table-enums), lists or
11+
sets. Sets (denoted by `RETURNS SETOF ...`) are exposed as
1112
[connections](/postgraphile/connections/). The arguments to these functions will
1213
be exposed via GraphQL - named arguments are preferred, if your arguments are
1314
not named we will assign them an auto-generated name such as `arg1`.

src/pages/postgraphile/enums.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,92 @@ comment on table animal_type is E'@enum\n@enumName TypeOfAnimal';
8484

8585
The name must conform to the GraphQL identifier restrictions.
8686

87+
#### Functions and table enums
88+
89+
_Since 4.14.0_
90+
91+
Functions exposed via GraphQL (as custom queries, computed columns and custom
92+
mutations) need a little assistance in order to indicate that an argument type
93+
or return type references a enum table and should be typed as a GraphQL enum.
94+
95+
You can achieve this by creating a domain for your enum that either:
96+
97+
- has a name that ends with `_enum_domain`, or
98+
- is tagged with `@enum the_enum_table_it_references`.
99+
100+
Example:
101+
102+
```sql
103+
create table stage_options (
104+
type text primary key
105+
);
106+
comment on table stage_options is E'@enum';
107+
insert into stage_options
108+
(type) values
109+
('pending'),
110+
('round 1'),
111+
('round 2'),
112+
('rejected'),
113+
('hired');
114+
115+
-- Either follow the convention of [enum_name]_enum_domain:
116+
create domain stage_options_enum_domain as text;
117+
-- or use any name for the domain and add a smart comment:
118+
-- create domain stage as text;
119+
-- comment on domain stage is E'@enum stage_options';
120+
121+
-- This function will add a `nextStage` field to applicant with GraphQL type
122+
-- `StageOptions` (our table enum):
123+
create function applicants_next_stage(a applicants)
124+
returns stage_options_enum_domain
125+
as $$
126+
select (case
127+
when a.stage = 'round 2' then 'hired'
128+
else 'rejected'
129+
end)::stage_options_enum_domain;
130+
$$ language sql stable;
131+
132+
-- This function allows to filter applicants by `StageOptions` value:
133+
create function applicants_by_stage(wanted_stage stage_options_enum_domain)
134+
returns setof applicants
135+
as $$
136+
select * from applicants a where a.stage = wanted_stage
137+
$$ language sql stable;
138+
```
139+
140+
For enums using unique constraints, you can achieve the same result by creating
141+
a domain that either:
142+
143+
- has a name that follows this pattern:
144+
`[enum_table_name]_[constraint_name]_enum_domain`, or
145+
- is that tagged with `@enum [enum_table_name]_[constraint_name]`.
146+
147+
For example:
148+
149+
```sql
150+
create table my_enums (
151+
transportation text not null constraint transportation_mean unique
152+
);
153+
154+
comment on constraint transportation_mean on my_enums is E'@enum';
155+
insert into my_enums
156+
(transportation) values
157+
('CAR'),
158+
('BIKE'),
159+
('SUBWAY');
160+
161+
-- Either follow the convention of [enum_table_name]_[constraint_name]_enum_domain:
162+
create domain my_enums_transportation_mean_enum_domain as text;
163+
164+
-- Or use any name for the domain and add a smart comment referencing the enum
165+
-- via `[enum_table_name]_[constraint_name]`:
166+
create domain transportation as text;
167+
comment on domain transportation is E'@enum my_enums_transportation_mean';
168+
169+
-- Then you can create functions that take this domain as the type of their
170+
-- arguments or return value like in the previous example.
171+
```
172+
87173
### With makeExtendSchemaPlugin
88174

89175
Use the standard `enum` GraphQL interface definition language (IDL/SDL) to

0 commit comments

Comments
 (0)