Help us shape the future of Go! Take the 2026 Go Developer Survey

database

package
v1.0.2 Latest Latest
Warning

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

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

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ConnectDB

func ConnectDB(ctx context.Context, dsn string) (*sql.DB, error)

ConnectDB opens a database connection using the pgx driver.

func CreateMigration

func CreateMigration(ctx context.Context, name, dir string, opts *MigrationOptions) error

CreateMigration creates a new forward-only SQL migration, versioned with a UTC timestamp (YYYYMMDDHHMMSS_name.up.sql). See internal/migrationver for why the version is a timestamp rather than max+1: a sequential allocator hands the same number to every branch cut from the same commit, which is how ten version numbers in control-plane each ended up claimed by two different migrations. Existing sequential files are never renamed — a 14-digit timestamp sorts after any 5-digit number. The file opens with a short header naming where the schema lives (GeneratePointerComment); with opts.Context (or opts.DSN) it carries the full schema context instead.

func FormatSchemaJSON

func FormatSchemaJSON(tables []Table) (string, error)

FormatSchemaJSON formats schema as JSON.

func FormatSchemaText

func FormatSchemaText(tables []Table) string

FormatSchemaText formats schema as a human-readable text table.

func GenerateContextComment

func GenerateContextComment(ctx *MigrationContext) string

GenerateContextComment builds the full SQL comment block for a new migration.

func GeneratePointerComment added in v0.1.46

func GeneratePointerComment(name string, history []string, created time.Time) string

GeneratePointerComment is the header a new migration gets by default: what it is and where the schema lives, not the schema itself.

The full context block (GenerateContextComment) copies the reconstructed schema, the whole previous migration and every filename into the file. On a real project that is thousands of lines — 4,658 on reliant, most of it a baseline it had just squashed — in a file whose SQL is three lines, and an agent or reviewer reads all of it. The schema is one command away, kept current, and not frozen into a migration that will outlive it.

It names no path: the file is committed, and the directory it sits in is the one it means.

func GetMigrationHistory

func GetMigrationHistory(dir string) ([]string, error)

GetMigrationHistory returns a sorted list of all migration filenames (just .up.sql).

func PendingMigrations added in v0.1.45

func PendingMigrations(dir string) ([]string, error)

PendingMigrations returns the *.up.sql files in dir that are new on this branch — above the default branch's merge-base high-water mark — which is what `--all-pending` means.

Without git, newness is unknowable and this returns nothing rather than guessing. Offering to rename every migration in a directory, including merged history, is exactly the outcome the refusal exists to prevent, and an empty answer with an explanation is the honest version of "cannot tell".

Types

type AlreadyMergedError added in v0.1.45

type AlreadyMergedError struct {
	// File is the base name of the migration that was refused.
	File string
	// Version is the version it claims.
	Version uint64
	// MergeBaseMax is the high-water mark it is at or below.
	MergeBaseMax uint64
}

AlreadyMergedError reports a refusal to re-version a migration that has already merged to the default branch.

It is a type, not a formatted string, so the CLI can report every refused file in one pass and a test can assert on the reason rather than on prose.

func (*AlreadyMergedError) Error added in v0.1.45

func (e *AlreadyMergedError) Error() string

type Column

type Column struct {
	Name      string `json:"name"`
	Type      string `json:"type"`
	Nullable  bool   `json:"nullable"`
	Default   string `json:"default,omitempty"`
	IsPrimary bool   `json:"is_primary"`
	MaxLength *int   `json:"max_length,omitempty"`
	UDTName   string `json:"udt_name,omitempty"`
}

Column represents a database column.

type ForeignKey

type ForeignKey struct {
	Name             string `json:"name"`
	Column           string `json:"column"`
	ReferencedTable  string `json:"referenced_table"`
	ReferencedColumn string `json:"referenced_column"`
}

ForeignKey represents a foreign key constraint.

type Index

type Index struct {
	Name    string   `json:"name"`
	Columns []string `json:"columns"`
	Unique  bool     `json:"unique"`
}

Index represents a database index.

type MigrationContext

type MigrationContext struct {
	MigrationName     string
	CreatedAt         time.Time
	ParsedTables      []ParsedTable // Schema reconstructed from existing migrations
	LiveTables        []Table       // Schema from live DB introspection (if --dsn)
	PreviousMigration *PreviousMigrationInfo
	MigrationHistory  []string // List of all previous migration filenames
}

MigrationContext holds all gathered context for generating rich migration comments.

func GatherMigrationContext

func GatherMigrationContext(ctx context.Context, name, migDir string, opts MigrationOptions) (*MigrationContext, error)

GatherMigrationContext collects all available context for a new migration.

type MigrationOptions

type MigrationOptions struct {
	DSN string // If set, introspect the live DB for schema

	// Context writes the full context block — the schema, the previous
	// migration and the history — into the new file instead of a pointer to
	// where they live. Set by --context, and implied by DSN.
	Context bool

	// The compatibility declaration written at the top of the file (see
	// compatHeader). At most one of BackwardCompatible and BreaksRollback,
	// each the reason; RequireCompatDeclaration writes the choices as
	// examples when neither is given.
	BackwardCompatible       string
	BreaksRollback           string
	RequireCompatDeclaration bool

	// Body is SQL written after the header, for a migration whose content
	// forge already knows (`forge db migration new --closed-set`). Empty
	// leaves the file for the author to write.
	Body string
}

MigrationOptions controls what context is included when creating a new migration.

type MigrationService

type MigrationService interface {
	CreateMigration(ctx context.Context, name string, dir string, opts *MigrationOptions) error
	GatherMigrationContext(ctx context.Context, name string, migDir string, opts MigrationOptions) (*MigrationContext, error)
	GetPreviousMigration(ctx context.Context, dir string) (*PreviousMigrationInfo, error)
	GetMigrationHistory(ctx context.Context, dir string) ([]string, error)
}

MigrationService creates and manages database migrations.

type ParsedColumn

type ParsedColumn struct {
	Name       string
	Type       string
	Constraint string // e.g. "PRIMARY KEY", "NOT NULL", "UNIQUE", "REFERENCES users(id)"
}

ParsedColumn represents a column extracted from a CREATE TABLE or ALTER TABLE statement.

type ParsedTable

type ParsedTable struct {
	Name    string
	Columns []ParsedColumn
}

ParsedTable represents a table reconstructed from parsing migration SQL files.

func ParseMigrationsForSchema

func ParseMigrationsForSchema(dir string) ([]ParsedTable, error)

ParseMigrationsForSchema reads all .up.sql files in dir (sorted by name) and reconstructs a best-effort schema by parsing CREATE TABLE and ALTER TABLE statements.

type PreviousMigrationInfo

type PreviousMigrationInfo struct {
	Filename string
	Content  string
}

PreviousMigrationInfo holds information about the most recent migration.

func GetPreviousMigration

func GetPreviousMigration(dir string) (*PreviousMigrationInfo, error)

GetPreviousMigration reads the most recent .up.sql file from the migrations dir. Content is that migration's SQL without forge's generated header.

type RebaseResult added in v0.1.45

type RebaseResult struct {
	OldPath string
	NewPath string
	// OldVersion and NewVersion are the numeric version prefixes, so a
	// caller can assert ordering without re-parsing the filenames.
	OldVersion uint64
	NewVersion uint64
}

RebaseResult is one file's rename: what it was called and what it is called now. Returned rather than only printed so the CLI owns the output format and a test can assert on the decision instead of parsing stdout.

func RebaseMigrations added in v0.1.45

func RebaseMigrations(dir string, paths []string) ([]RebaseResult, error)

RebaseMigrations re-versions each file in paths to a fresh UTC timestamp that sorts after every version in dir and after the default branch's merge-base high-water mark.

The name stem is preserved: the version is the only thing that changes, so a reviewer following the file across the rename sees the same migration. Files are processed in ascending version order, which keeps their relative order intact — a batch that depends on being applied in sequence still is.

type SchemaIntrospector

type SchemaIntrospector interface {
	ConnectDB(ctx context.Context, dsn string) (*sql.DB, error)
	IntrospectSchema(ctx context.Context, db *sql.DB, tableFilter string) ([]Table, error)
	IntrospectTable(ctx context.Context, db *sql.DB, tableName string) (*Table, error)
}

SchemaIntrospector connects to databases and introspects their schema.

type Table

type Table struct {
	Name        string       `json:"name"`
	Schema      string       `json:"schema"`
	Columns     []Column     `json:"columns"`
	PrimaryKey  []string     `json:"primary_key"`
	Indexes     []Index      `json:"indexes"`
	ForeignKeys []ForeignKey `json:"foreign_keys"`
}

Table represents a database table with its full schema metadata.

func IntrospectSchema

func IntrospectSchema(ctx context.Context, db *sql.DB, tableFilter string) ([]Table, error)

IntrospectSchema connects to the database and returns the full schema. If tableFilter is non-empty, only that table is returned.

func IntrospectTable

func IntrospectTable(ctx context.Context, db *sql.DB, tableName string) (*Table, error)

IntrospectTable returns full metadata for a single table.

Jump to

Keyboard shortcuts

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