Files
relspecgo/pkg/writers/gorm
Hein 4181cb1fbd
All checks were successful
CI / Test (1.24) (push) Successful in -27m15s
CI / Test (1.25) (push) Successful in -27m10s
CI / Build (push) Successful in -27m38s
CI / Lint (push) Successful in -27m25s
Release / Build and Release (push) Successful in -27m27s
Integration Tests / Integration Tests (push) Successful in -27m18s
feat(writer): 🎉 Enhance relationship field naming and uniqueness
* Update relationship field naming conventions for has-one and has-many relationships.
* Implement logic to ensure unique field names by tracking used names.
* Add tests to verify new naming conventions and uniqueness constraints.
2026-01-10 17:45:13 +02:00
..
2025-12-17 20:44:02 +02:00
2025-12-28 10:34:20 +02:00
2025-12-16 18:10:40 +02:00

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 PostgreSQL database (single file)
relspec --input pgsql \
  --conn "postgres://localhost/mydb" \
  --output gorm \
  --out-file models.go \
  --package models

# Generate GORM models with multi-file output (one file per table)
relspec --input json \
  --in-file schema.json \
  --output gorm \
  --out-file models/ \
  --package models

# Convert DBML to GORM models
relspec --input dbml --in-file schema.dbml --output gorm --out-file models.go

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 Example

package models

import (
    "time"
    sql_types "git.warky.dev/wdevs/sql_types"
)

type ModelUser struct {
    ID        int64                `gorm:"column:id;type:bigint;primaryKey;autoIncrement" json:"id"`
    Username  string               `gorm:"column:username;type:varchar(50);not null;uniqueIndex" json:"username"`
    Email     string               `gorm:"column:email;type:varchar(100);not null" json:"email"`
    CreatedAt time.Time            `gorm:"column:created_at;type:timestamp;not null;default:now()" json:"created_at"`

    // Relationships
    Pos []*ModelPost `gorm:"foreignKey:UserID;references:ID;constraint:OnDelete:CASCADE" json:"pos,omitempty"`
}

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

type ModelPost struct {
    ID        int64           `gorm:"column:id;type:bigint;primaryKey" json:"id"`
    UserID    int64           `gorm:"column:user_id;type:bigint;not null" json:"user_id"`
    Title     string          `gorm:"column:title;type:varchar(200);not null" json:"title"`
    Content   sql_types.SqlString `gorm:"column:content;type:text" json:"content,omitempty"`

    // Belongs to
    Use *ModelUser `gorm:"foreignKey:UserID;references:ID" json:"use,omitempty"`
}

func (ModelPost) TableName() string {
    return "public.posts"
}

Writer Options

Metadata Options

Configure the writer behavior using metadata in WriterOptions:

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

Type Mapping

SQL Type Go Type Notes
bigint, int8 int64 -
integer, int, int4 int -
smallint, int2 int16 -
varchar, text string Not nullable
varchar, text (nullable) sql_types.SqlString Nullable
boolean, bool bool -
timestamp, timestamptz time.Time -
numeric, decimal float64 -
uuid string -
json, jsonb string -

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.
  • Generated code is auto-formatted with go fmt
  • JSON tags are automatically added
  • Supports schema-qualified table names in TableName() method