Files
2026-04-23 23:58:59 -05:00

5.9 KiB

Schema Reference

Contents


Defining Types

Types with @table map to PostgreSQL tables. Data Connect auto-generates an implicit id: UUID! primary key.

type Movie @table {
  # id: UUID! is auto-added
  title: String!
  releaseYear: Int
  genre: String
}

Customizing Tables

type Movie @table(name: "movies", key: "id", singular: "movie", plural: "movies") {
  id: UUID! @col(name: "movie_id") @default(expr: "uuidV4()")
  title: String!
  releaseYear: Int @col(name: "release_year")
  genre: String @col(dataType: "varchar(20)")
}

User Table with Auth

type User @table(key: "uid") {
  uid: String! @default(expr: "auth.uid")
  email: String! @unique
  displayName: String @col(dataType: "varchar(100)")
  createdAt: Timestamp! @default(expr: "request.time")
}

Core Directives

@table

Defines a database table.

Argument Description
name PostgreSQL table name (snake_case default)
key Primary key field(s), default ["id"]
singular Singular name for generated fields
plural Plural name for generated fields

@col

Customizes column mapping.

Argument Description
name Column name in PostgreSQL
dataType PostgreSQL type: serial, varchar(n), text, etc.
size Required for Vector type

@default

Sets default value for inserts.

Argument Description
value Literal value: @default(value: "draft")
expr CEL expression: @default(expr: "uuidV4()"), @default(expr: "auth.uid"), @default(expr: "request.time")
sql Raw SQL: @default(sql: "now()")

Common expressions:

  • uuidV4() - Generate UUID
  • auth.uid - Current user's Firebase Auth UID
  • request.time - Server timestamp

@unique

Adds unique constraint.

type User @table {
  email: String! @unique
}

# Composite unique
type Review @table @unique(fields: ["movie", "user"]) {
  movie: Movie!
  user: User!
  rating: Int
}

@index

Creates database index for query performance.

type Movie @table @index(fields: ["genre", "releaseYear"], order: [ASC, DESC]) {
  title: String! @index
  genre: String
  releaseYear: Int
}
Argument Description
fields Fields for composite index (on @table)
order [ASC] or [DESC] for each field
type BTREE (default), GIN (arrays), HNSW/IVFFLAT (vectors)

@searchable

Enables full-text search on String fields.

type Post @table {
  title: String! @searchable
  body: String! @searchable(language: "english")
}

# Usage
query SearchPosts($q: String!) @auth(level: PUBLIC) {
  posts_search(query: $q) { id title body }
}

Relationships

One-to-Many (Implicit Foreign Key)

type Post @table {
  id: UUID! @default(expr: "uuidV4()")
  author: User!  # Creates authorId foreign key
  title: String!
}

type User @table {
  id: UUID! @default(expr: "uuidV4()")
  name: String!
  # Auto-generated: posts_on_author: [Post!]!
}

@ref Directive

Customizes foreign key reference.

type Post @table {
  author: User! @ref(fields: "authorId", references: "id")
  authorId: UUID!  # Explicit FK field
}
Argument Description
fields Local FK field name(s)
references Target field(s) in referenced table
constraintName PostgreSQL constraint name

Cascade behavior:

  • Required reference (User!): CASCADE DELETE (post deleted when user deleted)
  • Optional reference (User): SET NULL (authorId set to null when user deleted)

One-to-One

Use @unique on the reference field:

type User @table { id: UUID! name: String! }

type UserProfile @table {
  user: User! @unique  # One profile per user
  bio: String
  avatarUrl: String
}

# Query: user.userProfile_on_user

Many-to-Many

Use a join table with composite primary key:

type Movie @table { id: UUID! title: String! }
type Actor @table { id: UUID! name: String! }

type MovieActor @table(key: ["movie", "actor"]) {
  movie: Movie!
  actor: Actor!
  role: String!  # Extra data on relationship
}

# Generated fields:
# - movie.actors_via_MovieActor: [Actor!]!
# - actor.movies_via_MovieActor: [Movie!]!
# - movie.movieActors_on_movie: [MovieActor!]!

Data Types

GraphQL Type PostgreSQL Default Other PostgreSQL Types
String text varchar(n), char(n)
Int int4 int2, serial
Int64 bigint bigserial, numeric
Float float8 float4, numeric
Boolean boolean
UUID uuid
Date date
Timestamp timestamptz Stored as UTC
Any jsonb
Vector vector Requires @col(size: N)
[Type] Array e.g., [String]text[]

Enumerations

enum Status {
  DRAFT
  PUBLISHED
  ARCHIVED
}

type Post @table {
  status: Status! @default(value: DRAFT)
  allowedStatuses: [Status!]
}

Rules:

  • Enum names: PascalCase, no underscores
  • Enum values: UPPER_SNAKE_CASE
  • Values are ordered (for comparison operations)
  • Changing order or removing values is a breaking change

Views (Advanced)

Map custom SQL queries to GraphQL types:

type MovieStats @view(sql: """
  SELECT
    movie_id,
    COUNT(*) as review_count,
    AVG(rating) as avg_rating
  FROM review
  GROUP BY movie_id
""") {
  movie: Movie @unique
  reviewCount: Int
  avgRating: Float
}

# Query movies with stats
query TopMovies @auth(level: PUBLIC) {
  movies(orderBy: [{ rating: DESC }]) {
    title
    stats: movieStats_on_movie {
      reviewCount avgRating
    }
  }
}