codegen

package
v0.0.0-...-6f40dae Latest Latest
Warning

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

Go to latest
Published: Jun 22, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package codegen generates Go source from a database schema model (meta.Metadata): the typed table bindings that the sqlkit query builder is driven from, and optionally a row struct (DTO) per table.

The generated binding for each table exposes typed Column[T] fields and the table identity, so statements start from the db handle with the table as an argument (db.Select().From(Users), db.Insert(Users)…) and the compiler checks every column and value. With EmitRelations the generator also emits foreign-key relation metadata (powering JoinRel, Preload, and typed filter bundles) and with EmitDTO a row struct per table.

The usual entry point is the sqlkit command (go run github.com/aita/sqlkit/cmd/sqlkit@latest generate), which calls Generate for you. Call the library directly when you need what the CLI flags cannot express — chiefly the SQL→Go type mapping (TypeMapper / NewDefaultTypeMapper) and the DTO naming scheme:

md, _ := catalog.Build() // a meta.Metadata, from decl or introspect
files, _ := codegen.Generate(md, codegen.Options{
	PackageName:   "appdb",
	EmitRelations: true,
})
_ = codegen.Write("appdb", files)

The type mapper's hooks are consulted most-specific first (OverrideFunc, then ColumnOverrides by table.column, then Overrides by SQL type name), falling through to the built-in tables; nullability is applied on top. A column whose SQL type has no Go mapping is an error — supply an override or pin a Go type on the decl column. See the package-level documentation guide at https://pkg.go.dev/github.com/aita/sqlkit and docs/schema-codegen.md for the full workflow.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DeclTypeExpr

func DeclTypeExpr(column meta.Column, dialect string) string

DeclTypeExpr maps an engine type name back to the decl package expression that produces it. Types without a portable name fall back to decl.Type, which keeps the engine name verbatim. It is exported for reuse by the migration autogenerator, which renders the same decl vocabulary.

func GeneratorID

func GeneratorID() string

GeneratorID fingerprints this sqlkit build's code generator: the format version, a hash of the generation templates (the source the emitted bindings are produced from), and the sqlkit module version. codegen bakes it into each binding's TableInfo.Generator. Bindings produced by different sqlkit versions or generator code carry different IDs, so a Unit of Work refuses to reconcile generated code that drifted across packages even when the structure matches.

func ReferentialActionExpr

func ReferentialActionExpr(action meta.ReferentialAction) string

ReferentialActionExpr renders a foreign-key referential action as the decl package constant that produces it (e.g. "decl.Cascade"), or "" when the action is empty (the engine default). It is shared with the migration autogenerator, which emits the same decl vocabulary.

func Write

func Write(dir string, files []File) error

Write writes generated files into dir, creating it (and any subdirectories a file's name nests it in, e.g. from Options.FileNameFor) as needed.

Types

type CatalogOptions

type CatalogOptions struct {
	// PackageName is the package of the generated catalog file. Required.
	PackageName string

	// FileName is the output file name (default "schema.go").
	FileName string

	// Tables, when non-empty, restricts generation to these table names.
	Tables []string

	// Dialect ("postgres" or "mysql", default postgres) selects how engine
	// type names map back to decl package types.
	Dialect string
}

CatalogOptions configures GenerateCatalog.

type DefaultTypeMapper

type DefaultTypeMapper struct {
	// contains filtered or unexported fields
}

DefaultTypeMapper maps standard PostgreSQL and MySQL types to Go types and turns nullable columns into pointer types (slices, already nullable, are left as-is). Construct it with NewDefaultTypeMapper; the zero value is the default mapper with no customization. It resolves a column's Go type in precedence order:

  1. Config.OverrideFunc, if set and it returns ok.
  2. Config.ColumnOverrides, by column name (most specific key wins).
  3. Config.Overrides, by lowercase SQL type name.
  4. A Go type pinned on the column's meta.Type at the schema source (the decl DSL's DataType.Go), so a custom DB type carries its Go type along.
  5. The built-in PostgreSQL/MySQL type tables.

Nullability is applied to the resolved type at every level (a nullable column becomes a pointer), so overrides pin the bare type.

func NewDefaultTypeMapper

func NewDefaultTypeMapper(cfg TypeMapperConfig) DefaultTypeMapper

NewDefaultTypeMapper builds a DefaultTypeMapper from the config.

func (DefaultTypeMapper) GoTypeFor

func (m DefaultTypeMapper) GoTypeFor(table meta.Table, column meta.Column, dialect string) (meta.GoType, error)

GoTypeFor implements TypeMapper.

type File

type File struct {
	Name    string
	Content []byte
}

File is a single generated source file: a suggested name and its formatted contents.

func Generate

func Generate(md meta.Metadata, opts Options) ([]File, error)

Generate renders the catalog into one or more Go source files according to opts and returns their formatted contents. The md argument is the built schema model (meta.Metadata) — produce it with decl's Catalog.Build, the introspection, or by hand. The dialect (opts.Dialect, default postgres) selects the default SQL→Go type table.

func GenerateCatalog

func GenerateCatalog(md meta.Metadata, opts CatalogOptions) (File, error)

GenerateCatalog renders the schema as decl catalog source — the inverse of building a catalog: introspect a live database once, then maintain the schema as Go code and generate bindings and DDL from it. Unlike binding generation the result is a starting point meant to be edited, so it carries no DO NOT EDIT marker.

type GoType

type GoType = meta.GoType

GoType is an alias for meta.GoType, re-exported so library users that only import codegen can spell type overrides as codegen.GoType.

type Options

type Options struct {
	// PackageName is the package of the generated files. Required.
	PackageName string

	// Tables, when non-empty, restricts generation to these table names.
	Tables []string

	// Dialect overrides Schema.Dialect ("postgres" or "mysql"); it selects the
	// default SQL→Go type table.
	Dialect string

	// FilePerTable writes one file per table (named "<table>.go") instead of a
	// single combined file. Use FileNameFor to customize the per-table path or
	// split tables across subdirectories.
	FilePerTable bool

	// FileName overrides the single-file output name (default "tables.go").
	// Ignored when FilePerTable or FileNameFor is set.
	FileName string

	// FileNameFor, when set, derives each table's generated file path relative to
	// the output directory, implying one file per table (FilePerTable). The
	// returned path may contain slashes to nest the file in a subdirectory, which
	// Write creates. Defaults to "<table>.go". When DTOSeparateFile is set, the
	// DTO file sits beside it with "_dto" inserted before the extension
	// (e.g. "users.go" -> "users_dto.go").
	FileNameFor func(table meta.Table) string

	// EmitRelations generates the relation-aware surface: foreign-key relation
	// metadata (table.Rels) implementing sqlkit.Relation, Query/Q entry points
	// returning a sqlkit.SelectQuery, and a columns/table struct split. Off by
	// default, so the binding stays pure metadata unless asked.
	EmitRelations bool

	// EmitDTO additionally generates a row struct (DTO) per table.
	EmitDTO bool

	// DTOSeparateFile writes the DTOs into their own file(s), separate from the
	// table bindings.
	DTOSeparateFile bool

	// TypeMapper customizes the SQL→Go type mapping. Defaults to the zero
	// DefaultTypeMapper (equivalent to NewDefaultTypeMapper(TypeMapperConfig{})).
	TypeMapper TypeMapper

	// DTOName derives the DTO type name from a table. Defaults to a singular,
	// collision-avoiding name (e.g. table "users" -> "User"). When the derived
	// name collides with a binding identifier, "Row" is appended.
	DTOName func(table meta.Table) string

	// BindingName derives the table binding's base Go identifier from a table.
	// The returned name backs every binding identifier: the package var
	// ("Users"), its table type ("UsersTable"), and—in the relation-aware
	// layout—the columns type ("UsersColumns"), its constructor
	// ("newUsersColumns"), the relations type ("UsersRels"), and the filter
	// bundle ("UsersFilter"). It is the caller's responsibility to keep the
	// returned names valid and distinct across tables.
	//
	// Returning the empty string for a table (or leaving BindingName nil) falls
	// back to the default: the exported camel-case of the table name (e.g. table
	// "users" -> "Users"). A decl catalog exposes its declared overrides as a
	// ready-made hook via Catalog.BindingNames.
	BindingName func(table meta.Table) string
}

Options configures generation. The zero value (with PackageName set) emits a single file of table bindings.

type TypeMapper

type TypeMapper interface {
	GoTypeFor(table meta.Table, column meta.Column, dialect string) (meta.GoType, error)
}

TypeMapper resolves the Go type a column's field uses, for a given dialect. The table is supplied so a mapper can key its decision on the table and column names, not just the SQL type. Implement it (or build a DefaultTypeMapper with NewDefaultTypeMapper) to customize the SQL→Go mapping when using codegen as a library.

type TypeMapperConfig

type TypeMapperConfig struct {
	// Overrides maps a lowercase SQL/engine type name to a Go type, e.g. to map
	// every "numeric" column to a decimal type:
	//
	//	Overrides: map[string]codegen.GoType{
	//		"numeric": {ImportPath: "github.com/shopspring/decimal", Name: "decimal.Decimal"},
	//	}
	Overrides map[string]meta.GoType
	// ColumnOverrides maps a specific column to a Go type, keyed by
	// "schema.table.column", "table.column", or bare "column" (most specific
	// match wins), regardless of the column's SQL type:
	//
	//	ColumnOverrides: map[string]codegen.GoType{
	//		"users.id": {ImportPath: "github.com/google/uuid", Name: "uuid.UUID"},
	//		"metadata": {ImportPath: "encoding/json", Name: "json.RawMessage"},
	//	}
	ColumnOverrides map[string]meta.GoType
	// OverrideFunc, when set, is consulted first for each column. Return ok=true
	// with the resolved Go type to use it, ok=false to fall through to the maps,
	// pinned types, and built-in tables, or a non-nil error to fail generation.
	// It receives the table so it can decide on the table and column names.
	OverrideFunc func(table meta.Table, column meta.Column, dialect string) (gt meta.GoType, ok bool, err error)
}

TypeMapperConfig initializes a DefaultTypeMapper; pass it to NewDefaultTypeMapper. All fields are optional — the zero config maps standard types to Go types out of the box.

type TypeMapperFunc

type TypeMapperFunc func(table meta.Table, column meta.Column, dialect string) (meta.GoType, error)

TypeMapperFunc adapts a plain function to the TypeMapper interface.

func (TypeMapperFunc) GoTypeFor

func (f TypeMapperFunc) GoTypeFor(table meta.Table, column meta.Column, dialect string) (meta.GoType, error)

GoTypeFor calls f.

Jump to

Keyboard shortcuts

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