writers

package
v1.0.90 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 12, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package writers provides interfaces and implementations for writing database schemas to various output formats and destinations.

Overview

The writers package defines a common Writer interface that all format-specific writers implement. This allows RelSpec to export database schemas to multiple formats including:

  • SQL schema files (PostgreSQL, SQLite)
  • Schema definition files (DBML, DCTX, DrawDB, GraphQL)
  • ORM model files (GORM, Bun, Drizzle, Prisma, TypeORM)
  • Data interchange formats (JSON, YAML)

Architecture

Each writer implementation is located in its own subpackage (e.g., pkg/writers/dbml, pkg/writers/pgsql) and implements the Writer interface, supporting three levels of granularity:

  • WriteDatabase() - Write complete database with all schemas
  • WriteSchema() - Write single schema with all tables
  • WriteTable() - Write single table with all columns and metadata

Usage

Writers are instantiated with WriterOptions containing destination-specific configuration:

// Write to file
writer := dbml.NewWriter(&writers.WriterOptions{
    OutputPath: "schema.dbml",
})
err := writer.WriteDatabase(db)

// Write ORM models with package name
writer := gorm.NewWriter(&writers.WriterOptions{
    OutputPath:  "./models",
    PackageName: "models",
})
err := writer.WriteDatabase(db)

// Write with schema flattening for SQLite
writer := sqlite.NewWriter(&writers.WriterOptions{
    OutputPath:    "schema.sql",
    FlattenSchema: true,
})
err := writer.WriteDatabase(db)

Schema Flattening

The FlattenSchema option controls how schema-qualified table names are handled:

  • false (default): Uses dot notation (schema.table)
  • true: Joins with underscore (schema_table), useful for SQLite

Supported Formats

  • dbml: Database Markup Language files
  • dctx: DCTX schema files
  • drawdb: DrawDB JSON format
  • graphql: GraphQL schema definition language
  • json: JSON database schema
  • yaml: YAML database schema
  • gorm: Go GORM model structs
  • bun: Go Bun model structs
  • drizzle: TypeScript Drizzle ORM schemas
  • prisma: Prisma schema language
  • typeorm: TypeScript TypeORM entities
  • pgsql: PostgreSQL SQL schema
  • sqlite: SQLite SQL schema with automatic flattening

Index

Constants

View Source
const (
	// NullableTypeSqlTypes uses git.warky.dev/wdevs/relspecgo/pkg/sqltypes
	// (SqlString, SqlInt32, SqlVector, SqlStringArray, …).
	NullableTypeSqlTypes = "sqltypes"

	// NullableTypeStdlib uses the standard library database/sql nullable types
	// (sql.NullString, sql.NullInt32, …) and plain Go slices for arrays.
	NullableTypeStdlib = "stdlib"

	// NullableTypeBaselib uses plain Go pointer types for nullable columns
	// (*string, *int32, *time.Time, …) and plain Go slices for arrays.
	// No external imports are required beyond the standard library. This is the default.
	NullableTypeBaselib = "baselib"
)

NullableType constants control which Go package is used for nullable column types in code-generation writers (Bun, GORM).

View Source
const (
	// NullableArraysSlice represents every array column (nullable or not) as
	// a plain slice ([]string, []int32, …). SQL NULL and '{}' both scan into
	// a zero-length/nil slice, so callers cannot distinguish them. This is
	// the default.
	NullableArraysSlice = "slice"

	// NullableArraysPointerSlice represents nullable array columns as a
	// pointer to a slice (*[]string, *[]int32, …), so callers can
	// distinguish SQL NULL (nil pointer) from '{}' (pointer to an empty
	// slice). NOT NULL array columns are unaffected and remain plain slices.
	NullableArraysPointerSlice = "pointer_slice"
)

NullableArrays constants control how nullable PostgreSQL array columns are represented in native-slice code-generation writers (Bun in stdlib/baselib mode).

Variables

This section is empty.

Functions

func ApplyTypeMapping added in v1.0.86

func ApplyTypeMapping(goType string, notNull bool) string

ApplyTypeMapping wraps an overridden Go type for nullability: NOT NULL uses the type verbatim; nullable columns get a pointer prefix unless the type is already a pointer, slice, map or interface.

func FailExecution added in v1.0.90

func FailExecution(opts *WriterOptions, dialect string, operations []ExecutionOperation, cause error) error

FailExecution records an invocation that failed before issuing any SQL.

func FinishExecution added in v1.0.90

func FinishExecution(opts *WriterOptions, report *ExecutionReport, runErr error) error

FinishExecution publishes legacy counters and a typed report even on failure.

func LookupTypeMapping added in v1.0.86

func LookupTypeMapping(mappings map[string]string, baseType string) (string, bool)

LookupTypeMapping returns the user-configured override for baseType, which the caller must already have canonicalized.

func ParseTypeMappings added in v1.0.86

func ParseTypeMappings(entries []string) (map[string]string, error)

ParseTypeMappings parses "sqltype=gotype" entries (as given to --type-map) into a map keyed by the canonical lower-case SQL base type, so that "VARCHAR", "character varying" and "varchar(50)" all address one entry. It returns nil for empty input.

func QualifiedTableName added in v1.0.30

func QualifiedTableName(schema, table string, flatten bool) string

QualifiedTableName returns a schema-qualified table name. When flatten is true, schema and table are joined with underscore (e.g., "schema_table"). When flatten is false, they are dot-separated (e.g., "schema.table"). If schema is empty, just the table name is returned regardless of flatten.

func QuoteDefaultValue added in v1.0.38

func QuoteDefaultValue(value, sqlType string) string

func RunExecution added in v1.0.90

func RunExecution(ctx context.Context, opts *WriterOptions, report *ExecutionReport, operations []ExecutionOperation, backend ExecutionBackend) error

RunExecution applies a plan, records every outcome, and publishes metadata and reports.

func SanitizeFilename added in v1.0.7

func SanitizeFilename(name string) string

SanitizeFilename removes quotes, comments, and invalid characters from identifiers to make them safe for use in filenames. This handles: - Double and single quotes: "table_name" or 'table_name' -> table_name - DBML comments: table [note: 'description'] -> table - Invalid filename characters: replaced with underscores

func SanitizeStructTagValue added in v1.0.8

func SanitizeStructTagValue(value string) string

SanitizeStructTagValue sanitizes a value to be safely used inside Go struct tags. Go struct tags are delimited by backticks, so any backtick in the value would break the syntax. This function: - Removes DBML/DCTX comments in brackets - Removes all quotes (double, single, and backticks) - Returns a clean identifier safe for use in struct tags and field names

func WriteExecutionReport added in v1.0.90

func WriteExecutionReport(path string, report *ExecutionReport) error

Types

type ExecutionBackend added in v1.0.90

type ExecutionBackend struct {
	Exec     func(context.Context, int, string) error
	Begin    func(context.Context) error
	Commit   func(context.Context) error
	Rollback func(context.Context) error
	// ScriptManaged means arbitrary scripts can commit/rollback internally.
	ScriptManaged bool
}

ExecutionBackend operates on one connection. Begin switches Exec to a transaction. Atomic execution stops at the first failure and rolls back the whole invocation.

type ExecutionError added in v1.0.90

type ExecutionError struct {
	StatementNumber int    `json:"statement_number"`
	Statement       string `json:"statement"`
	Error           string `json:"error"`
}

type ExecutionFailure added in v1.0.90

type ExecutionFailure struct{ Report *ExecutionReport }

ExecutionFailure is returned even when continuation was explicitly requested.

func (*ExecutionFailure) Error added in v1.0.90

func (e *ExecutionFailure) Error() string

type ExecutionOperation added in v1.0.90

type ExecutionOperation struct {
	StatementNumber int    `json:"statement_number"`
	Name            string `json:"name,omitempty"`
	Statement       string `json:"statement"`
	Status          string `json:"status"` // applied, executed (raw script), failed, skipped, rolled_back, unknown
	Error           string `json:"error,omitempty"`
	Skip            bool   `json:"-"`
	StopOnFailure   bool   `json:"-"`
}

ExecutionOperation is one generated statement or supplied script, in execution order. A failed raw script may have committed some of its own statements; see Outcome.

func StatementOperations added in v1.0.90

func StatementOperations(statements []string) []ExecutionOperation

StatementOperations creates a plan from the writers' structured statement lists.

type ExecutionReport added in v1.0.90

type ExecutionReport struct {
	Dialect              string               `json:"dialect,omitempty"`
	TotalStatements      int                  `json:"total_statements"`
	ExecutedStatements   int                  `json:"executed_statements"`
	FailedStatements     int                  `json:"failed_statements"`
	SkippedStatements    int                  `json:"skipped_statements"`
	RolledBackStatements int                  `json:"rolled_back_statements"`
	Outcome              string               `json:"outcome"`
	Operations           []ExecutionOperation `json:"operations"`
	Schemas              []SchemaReport       `json:"schemas"`
	Errors               []ExecutionError     `json:"errors,omitempty"`
	StartTime            string               `json:"start_time"`
	EndTime              string               `json:"end_time"`
}

ExecutionReport describes an entire invocation, including operations never attempted. ExecutedStatements counts operations still applied, excluding confirmed rollbacks.

type SchemaReport added in v1.0.90

type SchemaReport struct {
	Name   string        `json:"name"`
	Tables []TableReport `json:"tables"`
}

type TableReport added in v1.0.90

type TableReport struct {
	Name    string `json:"name"`
	Created bool   `json:"created"`
	Error   string `json:"error,omitempty"`
}

type Writer

type Writer interface {
	// WriteDatabase takes a Database model and writes it to the desired format
	WriteDatabase(db *models.Database) error

	// WriteSchema takes a Schema model and writes it to the desired format
	WriteSchema(schema *models.Schema) error

	// WriteTable takes a Table model and writes it to the desired format
	WriteTable(table *models.Table) error
}

Writer defines the interface for writing database specifications to various output formats at different granularity levels

type WriterOptions

type WriterOptions struct {
	// StrictConversion rejects known lossy MySQL conversions before output or execution.
	StrictConversion bool
	// Warning receives conversion diagnostics. MySQL writes warnings to stderr when nil.
	Warning func(string)

	// OutputPath is the path where the output should be written
	OutputPath string

	// PackageName is the Go package name (for code generation)
	PackageName string

	// FlattenSchema disables schema.table dot notation and instead joins
	// schema and table with an underscore (e.g., "public_users").
	// Useful for databases like SQLite that do not support schemas.
	FlattenSchema bool

	// LowercaseIdentifiers lowercases PostgreSQL names and structured references before generation.
	LowercaseIdentifiers bool

	// NullableTypes selects the Go type package used for nullable columns in
	// code-generation writers (bun, gorm). Accepted values:
	//   "sqltypes"              — git.warky.dev/wdevs/relspecgo/pkg/sqltypes
	//   "stdlib"                — database/sql (sql.NullString, sql.NullInt32, …)
	//   "baselib" (default)     — plain Go pointer types (*string, *int32, …)
	NullableTypes string

	// NullableArrays selects how nullable PostgreSQL array columns are
	// represented in native-slice code-generation writers (bun). Accepted values:
	//   "slice" (default)      — plain slice for every array column
	//   "pointer_slice"        — pointer-to-slice for nullable array columns,
	//                            distinguishing SQL NULL from '{}'
	// Has no effect in "sqltypes" NullableTypes mode, which always uses the
	// SqlXxxArray wrapper types.
	NullableArrays string

	// TypeMappings overrides the SQL-to-Go type mapping of the code-generation
	// writers (bun, gorm). Keys are SQL base types (aliases are canonicalized,
	// see ParseTypeMappings), values are Go type expressions. Array columns
	// use the override for their element type. Unmapped types keep the
	// built-in defaults.
	TypeMappings map[string]string

	// Prisma7 enables Prisma 7-specific output for Prisma writers.
	Prisma7 bool

	// StrictDirectives makes dialect directive translation fail on an
	// unsupported key for the writer's own namespace instead of skipping it.
	StrictDirectives bool

	// ContinueOnError instructs SQL writers to prepend `\set ON_ERROR_STOP off`
	// to their output so that psql continues past errors instead of stopping.
	// Live SQL execution also continues when set, but still returns an error
	// if any statement fails.
	ContinueOnError bool

	// AtomicExecution applies generated DDL in one transaction. It cannot be
	// combined with ContinueOnError; raw script execution rejects it.
	AtomicExecution bool

	// Additional options can be added here as needed
	Metadata map[string]interface{}
}

WriterOptions contains common options for writers

func (*WriterOptions) ShouldContinue added in v1.0.90

func (o *WriterOptions) ShouldContinue() bool

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL