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
1@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
1create table "BlogPost"(2 id int primary key,3 ...4);results in GraphQL type names like
1BlogPost2BlogPostEdge3BlogPostConnection4...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:
1comment on schema <schema_name> is e'@graphql({"inflect_names": true})';for example
1comment on schema public is e'@graphql({"inflect_names": true})';23create table blog_post(4 id int primary key,5 ...6);similarly would generated the GraphQL type names
1BlogPost2BlogPostEdge3BlogPostConnection4...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:
1comment on schema public is e'@graphql({"max_rows": 100})';To limit the max rows per page for the blog_post table and Person view:
1comment on table blog_post is e'@graphql({"max_rows": 20})';2comment on view "Person" is e'@graphql({"primary_key_columns": ["id"], "max_rows": 10})';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.
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.
1type BlogPostConnection {2 edges: [BlogPostEdge!]!3 pageInfo: PageInfo!45 """The total number of records matching the `filter` criteria"""6 totalCount: Int! # this field7}to enable totalCount for a table, use the directive
1comment on table "BlogPost" is e'@graphql({"totalCount": {"enabled": true}})';for example
1create table "BlogPost"(2 id serial primary key,3 email varchar(255) not null4);5comment on table "BlogPost" is e'@graphql({"totalCount": {"enabled": true}})';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.
1type BlogPostConnection {2 edges: [BlogPostEdge!]!3 pageInfo: PageInfo!45 """Aggregate functions calculated on the collection of `BlogPost`"""6 aggregate: BlogPostAggregate # this field7}To enable the aggregate field for a table, use the directive:
1comment on table "BlogPost" is e'@graphql({"aggregate": {"enabled": true}})';For example:
1create table "BlogPost"(2 id serial primary key,3 title varchar(255) not null,4 rating int not null5);6comment on table "BlogPost" is e'@graphql({"aggregate": {"enabled": true}})';You can combine both totalCount and aggregate directives:
1comment on table "BlogPost" is e'@graphql({"totalCount": {"enabled": true}, "aggregate": {"enabled": true}})';Renaming
Table's Type
Use the "name" JSON key to override a table's type name.
1create table account(2 id serial primary key3);45comment on table public.account is6e'@graphql({"name": "AccountHolder"})';results in:
1type AccountHolder { # previously: "Account"2 id: Int!3}Column's Field Name
Use the "name" JSON key to override a column's field name.
1create table public."Account"(2 id serial primary key,3 email text4);56comment on column "Account".email is7e'@graphql({"name": "emailAddress"})';results in:
1type Account {2 nodeId: ID!3 id: Int!4 emailAddress: String! # previously "email"5}Computed Field
Use the "name" JSON key to override a computed field's name.
1create table "Account"(2 id serial primary key,3 "firstName" varchar(255) not null,4 "lastName" varchar(255) not null5);67-- Extend with function8create function public."_fullName"(rec public."Account")9 returns text10 immutable11 strict12 language sql13as $$14 select format('%s %s', rec."firstName", rec."lastName")15$$;1617comment on function public._full_name is18e'@graphql({"name": "displayName"})';results in:
1type Account {2 nodeId: ID!3 id: Int!4 firstName: String!5 lastName: String!6 displayName: String # previously "fullName"7}Relationship's Field
Use the "local_name" and "foreign_name" JSON keys to override a relationship's inbound and outbound field names.
1create table "Account"(2 id serial primary key3);45create table "Post"(6 id serial primary key,7 "accountId" integer not null references "Account"(id),8 title text not null,9 body text10);1112comment on constraint post_account_id_fkey13 on "Post"14 is E'@graphql({"foreign_name": "author", "local_name": "posts"})';results in:
1type Post {2 nodeId: ID!3 id: Int!4 accountId: Int!5 title: String!6 body: String!7 author: Account # was "account"8}910type Account {11 id: Int!12 posts( # was "postCollection"13 after: Cursor,14 before: Cursor,15 filter: PostFilter,16 first: Int,17 last: Int,18 orderBy: [PostOrderBy!]19 ): PostConnection20}Description
Tables, Columns, and Functions accept a description directive to populate user defined descriptions in the GraphQL schema.
1create table "Account"(2 id serial primary key3);45comment on table public.account6is e'@graphql({"description": "A User Account"})';78comment on column public.account.id9is e'@graphql({"description": "The primary key identifier"})';1"""A User Account"""2type Account implements Node {34 """The primary key identifier"""5 id: Int!6}Enum Variant
If a variant of a Postgres enum does not conform to GraphQL naming conventions, introspection returns an error:
For example:
1create type "Algorithm" as enum ('aead-ietf');causes the error:
1{2 "errors": [3 {4 "message": "Names must only contain [_a-zA-Z0-9] but \"aead-ietf\" does not.",5 }6 ]7}To resolve this problem, rename the invalid SQL enum variant to a GraphQL compatible name:
1alter type "Algorithm" rename value 'aead-ietf' to 'AEAD_IETF';or, add a comment directive to remap the enum variant in the GraphQL API
1comment on type "Algorithm" is '@graphql({"mappings": {"aead-ietf": "AEAD_IETF"}})';Which both result in the GraphQL enum:
1enum Algorithm {2 AEAD_IETF3}