Files
relspecgo/pkg/writers/gorm

GORM Writer

Generates Go source files with GORM model definitions from database schema information.

Overview

The GORM Writer converts RelSpec's internal database model representation into Go source code with GORM struct definitions, complete with proper tags, relationships, and methods.

Features

  • Generates GORM-compatible Go structs
  • Creates proper gorm struct tags
  • Generates TableName() methods
  • Adds relationship fields (belongs-to, has-many)
  • Supports both single-file and multi-file output
  • Auto-generates helper methods (optional)
  • Maps SQL types to Go types
  • Handles nullable fields with custom sql_types

Usage

Basic Example

package main

import (
    "git.warky.dev/wdevs/relspecgo/pkg/models"
    "git.warky.dev/wdevs/relspecgo/pkg/writers"
    "git.warky.dev/wdevs/relspecgo/pkg/writers/gorm"
)

func main() {
    // Assume db is a *models.Database from a reader
    options := &writers.WriterOptions{
        OutputPath:  "models.go",
        PackageName: "models",
    }

    writer := gorm.NewWriter(options)
    err := writer.WriteDatabase(db)
    if err != nil {
        panic(err)
    }
}

CLI Examples

# Generate GORM models from a DBML schema (default: resolvespec types)
relspec convert --from dbml --from-path schema.dbml \
  --to gorm --to-path models.go --package models

# Use standard library database/sql nullable types instead of resolvespec
relspec convert --from dbml --from-path schema.dbml \
  --to gorm --to-path models.go --package models \
  --types stdlib

# Explicitly select resolvespec types (same as omitting --types)
relspec convert --from pgsql --from-conn "postgres://localhost/mydb" \
  --to gorm --to-path models.go --package models \
  --types resolvespec

# Multi-file output (one file per table)
relspec convert --from json --from-path schema.json \
  --to gorm --to-path models/ --package models

Output Modes

Single File Mode

Generates all models in one file:

relspec --input pgsql --conn "..." --output gorm --out-file models.go

Multi-File Mode

Generates one file per table (auto-detected when output is a directory):

relspec --input pgsql --conn "..." --output gorm --out-file models/

Files are named: sql_{schema}_{table}.go

Generated Code Examples

Default — resolvespec types (--types resolvespec)

package models

import (
    sql_types "github.com/bitechdev/ResolveSpec/pkg/spectypes"
)

type ModelUser struct {
    ID        string                      `gorm:"column:id;type:uuid;primaryKey" json:"id"`
    Username  string                      `gorm:"column:username;type:text;not null" json:"username"`
    Email     sql_types.SqlString         `gorm:"column:email;type:text" json:"email,omitempty"`
    Tags      sql_types.SqlStringArray    `gorm:"column:tags;type:text[];not null;default:'{}'" json:"tags"`
    CreatedAt sql_types.SqlTimeStamp      `gorm:"column:created_at;type:timestamptz;not null;default:now()" json:"created_at"`
}

func (ModelUser) TableName() string {
    return "public.users"
}

Standard library — --types stdlib

package models

import (
    "database/sql"
    "time"
)

type ModelUser struct {
    ID        string         `gorm:"column:id;type:uuid;primaryKey" json:"id"`
    Username  string         `gorm:"column:username;type:text;not null" json:"username"`
    Email     sql.NullString `gorm:"column:email;type:text" json:"email,omitempty"`
    Tags      []string       `gorm:"column:tags;type:text[];not null;default:'{}'" json:"tags"`
    CreatedAt time.Time      `gorm:"column:created_at;type:timestamptz;not null;default:now()" json:"created_at"`
}

func (ModelUser) TableName() string {
    return "public.users"
}

Writer Options

NullableTypes

Controls which Go package is used for nullable column types. Set via the --types CLI flag or WriterOptions.NullableTypes:

// Use resolvespec types (default — omit NullableTypes or set to "resolvespec")
options := &writers.WriterOptions{
    OutputPath:    "models.go",
    PackageName:   "models",
    NullableTypes: writers.NullableTypeResolveSpec,
}

// Use standard library database/sql types
options := &writers.WriterOptions{
    OutputPath:    "models.go",
    PackageName:   "models",
    NullableTypes: writers.NullableTypeStdlib,
}

Metadata Options

Configure additional writer behavior using metadata in WriterOptions:

options := &writers.WriterOptions{
    OutputPath:  "models.go",
    PackageName: "models",
    Metadata: map[string]any{
        "multi_file":          true, // Enable multi-file mode
        "populate_refs":       true, // Populate RefDatabase/RefSchema
        "generate_get_id_str": true, // Generate GetIDStr() methods
    },
}

Type Mapping

The nullable type package is selected with --types (or WriterOptions.NullableTypes).

SQL Type NOT NULL — both Nullable — resolvespec Nullable — stdlib
bigint int64 SqlInt64 sql.NullInt64
integer int32 SqlInt32 sql.NullInt32
smallint int16 SqlInt16 sql.NullInt16
text, varchar string SqlString sql.NullString
boolean bool SqlBool sql.NullBool
timestamp, timestamptz time.Time SqlTimeStamp sql.NullTime
numeric, decimal float64 SqlFloat64 sql.NullFloat64
uuid string SqlUUID sql.NullString
jsonb string SqlString sql.NullString
text[] SqlStringArray SqlStringArray []string
integer[] SqlInt32Array SqlInt32Array []int32
uuid[] SqlUUIDArray SqlUUIDArray []string
vector SqlVector SqlVector []float32

Relationship Generation

The writer automatically generates relationship fields:

  • Belongs-to: Generated for tables with foreign keys
  • Has-many: Generated for tables referenced by foreign keys
  • Relationship field names use 3-letter prefixes
  • Includes proper gorm tags with foreignKey and references

Notes

  • Model names are prefixed with "Model" (e.g., ModelUser)
  • Nullable columns use sql_types.SqlString, sql_types.SqlInt64, etc. by default; pass --types stdlib to use sql.NullString, sql.NullInt64, etc. instead
  • Array columns use sql_types.SqlStringArray, sql_types.SqlInt32Array, etc. by default; --types stdlib produces plain Go slices ([]string, []int32, …)
  • Generated code is auto-formatted with go fmt
  • JSON tags are automatically added
  • Supports schema-qualified table names in TableName() method