Configuration
Extra configuration options can be set on SQL entities using comment directives.
Comment Directives
Comment directives are snippets of configuration associated with SQL entities that alter how those entities behave.
The format of a comment directive is
1 | |
Inflection
Inflection describes how SQL entities' names are transformed into GraphQL type and field names. By default, inflection is disabled and SQL names are literally interpolated such that
1 2 3 4 | |
results in GraphQL type names like
1 2 3 4 | |
Since snake case is a common casing structure for SQL types, pg_graphql support basic inflection from snake_case to PascalCase for type names, and snake_case to camelCase for field names to match Javascript conventions.
The inflection directive can be applied at the schema level with:
1 | |
for example
1 2 3 4 5 6 | |
similarly would generated the GraphQL type names
1 2 3 4 | |
For more fine grained adjustments to reflected names, see renaming.
Max Rows
The default page size for collections is 30 entries. To adjust the number of entries on each page, set a max_rows directive on the relevant schema entity, table or view.
For example, to increase the max rows per page for each table in the public schema:
1 | |
To limit the max rows per page for the blog_post table and Person view:
1 2 | |
The max_rows value falls back to the parent object if it is missing on the current object. For example, if a table doesn't have max_rows set, the value set on the table's schema will be used. If the schema also doesn't have max_rows set, then it falls back to default value 30. The parent object of a view is the schema, not the table on which the view is created.
Introspection
GraphQL introspection is disabled by default to reduce the potential for API enumeration. Tools like GraphiQL, code generators, Apollo DevTools, and the Relay compiler rely on introspection. Opt in per schema when you need them.
To enable introspection on public schema:
1 | |
To explicitly disable it (same as the default):
1 | |
When no exposed schema has opted in, __schema and __type selections return an error:
1 | |
Partial introspection across multiple schemas
disable introspection for all schemas
It is recommended to disable introspection for all schemas in production.
The introspection directive is per schema. If two exposed schemas have introspection enabled for one but disabled for another, instead of returning Unknown field... errors, disabled schema's types are hidden from introspection fields.
Consider a setup with two schemas, where public has introspection enabled and private has it disabled:
1 2 3 4 5 6 7 8 9 10 | |
__schema and __type will not return an error because at least one schema (public) has introspection enabled. If neither schema had it enabled, both fields would return Unknown field "__schema" on type Query.
__type Field Queries
The __type field successfully resolves types belonging to the public schema:
1 | |
1 | |
But it returns null for types in the private schema:
1 | |
1 | |
Any non-existent types in the private schema also return null. In that case the introspecting user does not have visibility into if the requested type is in a schema without introspection, or if it doesn't exist. The two responses are indistinguishable:
1 | |
1 | |
__schema Field Queries
__schema field also filters out types from the private schema. Blog and its derived types (BlogEdge, BlogConnection, BlogFilter, BlogOrderBy, etc.) appear in the list, while Account and its derivatives are absent:
1 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
Note that built-in scalars and meta-types continue to appear:
1 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
The Query type's field listing is filtered the same way. blogCollection appears, accountCollection is hidden:
1 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
Same for the the Mutation type's field listing, Blog's mutation fields appear, Account's are hidden:
1 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
Mixed Field Queries
If a query contains both an introspection field (__schema, __type) and a data
field, and introspection is disabled, only the introspection fields return an error, the data field is resolved correctly:
1 2 3 4 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
If there are two schemas with introspection enabled only on one schema, there is no error on the introspection fields but entities from the introspection disabled schema are filtered out:
1 2 3 4 5 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | |
Non-introspection Queries
Non-introspection queries are not affected by disabling introspection. accountCollection, insertIntoAccountCollection, etc. continue to resolve normally as long as the role has the underlying SQL privileges:
1 2 3 4 5 6 7 8 9 10 | |
1 2 3 4 5 6 7 8 9 | |
The four combinations across the two schemas behave as follows:
public |
private |
__schema / __type available |
Blog visible |
Account visible |
Non-introspection queries |
|---|---|---|---|---|---|
| on | on | yes | yes | yes | unchanged |
| on | off | yes | yes | no | unchanged |
| off | on | yes | no | yes | unchanged |
| off | off | no (Unknown field error) |
n/a | n/a | unchanged |
totalCount
totalCount is an opt-in field that extends a table's Connection type. It provides a count of the rows that match the query's filters, and ignores pagination arguments.
1 2 3 4 5 6 7 8 9 | |
to enable totalCount for a table, use the directive
1 | |
for example
1 2 3 4 5 | |
Aggregate
The aggregate field is an opt-in field that extends a table's Connection type. It provides various aggregate functions like count, sum, avg, min, and max that operate on the collection of records that match the query's filters.
1 2 3 4 5 6 7 8 9 | |
To enable the aggregate field for a table, use the directive:
1 | |
For example:
1 2 3 4 5 6 | |
You can combine both totalCount and aggregate directives:
1 | |
Renaming
Table's Type
Use the "name" JSON key to override a table's type name.
1 2 3 4 5 6 | |
results in:
1 2 3 | |
Column's Field Name
Use the "name" JSON key to override a column's field name.
1 2 3 4 5 6 7 | |
results in:
1 2 3 4 5 | |
Computed Field
Use the "name" JSON key to override a computed field's name.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
results in:
1 2 3 4 5 6 7 | |
Relationship's Field
Use the "local_name" and "foreign_name" JSON keys to override a relationship's inbound and outbound field names.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
results in:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |
Description
Tables, Columns, and Functions accept a description directive to populate user defined descriptions in the GraphQL schema.
1 2 3 4 5 6 7 8 9 | |
1 2 3 4 5 6 7 8 9 | |
Enum Variant
If a variant of a Postgres enum does not conform to GraphQL naming conventions, introspection returns an error:
For example:
1 | |
causes the error:
1 2 3 4 5 6 7 | |
To resolve this problem, rename the invalid SQL enum variant to a GraphQL compatible name:
1 | |
or, add a comment directive to remap the enum variant in the GraphQL API
1 | |
Which both result in the GraphQL enum:
1 2 3 | |