Home

Configuration & Customization

Extra configuration options can be set on SQL entities using comment directives.

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


_10
@graphql(<JSON>)

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


_10
create table "BlogPost"(
_10
id int primary key,
_10
...
_10
);

results in GraphQL type names like


_10
BlogPost
_10
BlogPostEdge
_10
BlogPostConnection
_10
...

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:


_10
comment on schema <schema_name> is e'@graphql({"inflect_names": true})';

for example


_10
comment on schema public is e'@graphql({"inflect_names": true})';
_10
_10
create table blog_post(
_10
id int primary key,
_10
...
_10
);

similarly would generated the GraphQL type names


_10
BlogPost
_10
BlogPostEdge
_10
BlogPostConnection
_10
...

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.

For example, to increase the max rows per page for each table in the public schema:


_10
comment on schema public is e'@graphql({"max_rows": 100})';

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.


_10
type BlogPostConnection {
_10
edges: [BlogPostEdge!]!
_10
pageInfo: PageInfo!
_10
_10
"""The total number of records matching the `filter` criteria"""
_10
totalCount: Int! # this field
_10
}

to enable totalCount for a table, use the directive


_10
comment on table "BlogPost" is e'@graphql({"totalCount": {"enabled": true}})';

for example


_10
create table "BlogPost"(
_10
id serial primary key,
_10
email varchar(255) not null
_10
);
_10
comment on table "BlogPost" is e'@graphql({"totalCount": {"enabled": true}})';

Renaming#

Table's Type#

Use the "name" JSON key to override a table's type name.


_10
create table account(
_10
id serial primary key
_10
);
_10
_10
comment on table public.account is
_10
e'@graphql({"name": "AccountHolder"})';

results in:


_10
type AccountHolder { # previously: "Account"
_10
id: Int!
_10
}

Column's Field Name#

Use the "name" JSON key to override a column's field name.


_10
create table public."Account"(
_10
id serial primary key,
_10
email text
_10
);
_10
_10
comment on column "Account".email is
_10
e'@graphql({"name": "emailAddress"})';

results in:


_10
type Account {
_10
nodeId: ID!
_10
id: Int!
_10
emailAddress: String! # previously "email"
_10
}

Computed Field#

Use the "name" JSON key to override a computed field's name.


_18
create table "Account"(
_18
id serial primary key,
_18
"firstName" varchar(255) not null,
_18
"lastName" varchar(255) not null
_18
);
_18
_18
-- Extend with function
_18
create function public."_fullName"(rec public."Account")
_18
returns text
_18
immutable
_18
strict
_18
language sql
_18
as $$
_18
select format('%s %s', rec."firstName", rec."lastName")
_18
$$;
_18
_18
comment on function public._full_name is
_18
e'@graphql({"name": "displayName"})';

results in:


_10
type Account {
_10
nodeId: ID!
_10
id: Int!
_10
firstName: String!
_10
lastName: String!
_10
displayName: String # previously "fullName"
_10
}

Relationship's Field#

Use the "local_name" and "foreign_name" JSON keys to override a a relationships inbound and outbound field names.


_14
create table "Account"(
_14
id serial primary key
_14
);
_14
_14
create table "Post"(
_14
id serial primary key,
_14
"accountId" integer not null references "Account"(id),
_14
title text not null,
_14
body text
_14
);
_14
_14
comment on constraint post_owner_id_fkey
_14
on "Post"
_14
is E'@graphql({"foreign_name": "author", "local_name": "posts"})';

results in:


_20
type Post {
_20
nodeId: ID!
_20
id: Int!
_20
accountId: Int!
_20
title: String!
_20
body: String!
_20
author: Account # was "account"
_20
}
_20
_20
type Account {
_20
id: Int!
_20
posts( # was "postCollection"
_20
after: Cursor,
_20
before: Cursor,
_20
filter: PostFilter,
_20
first: Int,
_20
last: Int,
_20
orderBy: [PostOrderBy!]
_20
): PostConnection
_20
}

Description#

Tables, Columns, and Functions accept a description directive to populate user defined descriptions in the GraphQL schema.


_10
create table "Account"(
_10
id serial primary key
_10
);
_10
_10
comment on table public.account
_10
is e'@graphql({"description": "A User Account"})';
_10
_10
comment on column public.account.id
_10
is e'@graphql({"description": "The primary key identifier"})';


_10
"""A User Account"""
_10
type Account implements Node {
_10
_10
"""The primary key identifier"""
_10
id: Int!
_10
}

Enum Variant#

If a variant of a Postgres enum does not conform to GraphQL naming conventions, introspection returns an error:

For example:


_10
create type "Algorithm" as enum ('aead-ietf');

causes the error:


_10
{
_10
"errors": [
_10
{
_10
"message": "Names must only contain [_a-zA-Z0-9] but \"aead-ietf\" does not.",
_10
}
_10
]
_10
}

To resolve this problem, rename the invalid SQL enum variant to a GraphQL compatible name:


_10
alter type "Algorithm" rename value 'aead-ietf' to 'AEAD_IETF';

or, add a comment directive to remap the enum variant in the GraphQL API


_10
comment on type "Algorithm" is '@graphql({"mappings": {"aead-ietf": "AEAD_IETF"}})';

Which both result in the GraphQL enum:


_10
enum Algorithm {
_10
AEAD_IETF
_10
}