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

sqlschema

package
v0.0.0-...-2fd5d2c Latest Latest
Warning

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

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

Documentation

Index

Constants

View Source
const ContractsFileName = "schema-contracts.yaml"

ContractsFileName is the name of the file data teams maintain alongside the blueprint to declare their schema dependencies.

Variables

This section is empty.

Functions

func AnyBlocking

func AnyBlocking(impacts []ContractImpact) bool

AnyBlocking reports whether any impact has a blocking policy.

func ChangedTables

func ChangedTables(ctx context.Context, devConnStr, schemaPath, migrationsPath, engine string) ([]string, error)

ChangedTables returns the tables the pending schema change would touch, those added, dropped or modified by the migration `schema diff` would generate. It computes the diff against the dev database (replaying the existing migration directory) but writes nothing. Used to evaluate schema contracts.

func CheckPendingMigration

func CheckPendingMigration(ctx context.Context, devConnStr, schemaPath, migrationsPath, engine string) (bool, error)

CheckPendingMigration reports whether the schema YAML has changes that are not yet captured by a committed migration, which is to say whether `celerity schema diff` would generate a new migration. It computes the diff against the dev database (replaying the existing migration directory) but writes nothing. Used by `schema diff --check` as a CI completeness gate.

func DefaultPostgresCredentials

func DefaultPostgresCredentials() (user, password, database string)

DefaultPostgresCredentials returns the default local dev credentials for PostgreSQL containers.

func ExportSchema

func ExportSchema(s *Schema, format ExportFormat, resourceName string) (string, error)

ExportSchema renders a parsed schema in the given format for data-team consumption. resourceName is used in headers/titles. The export is derived purely from the schema YAML, so it needs no database connection.

func FindContractsFile

func FindContractsFile(dir string) (string, bool)

FindContractsFile returns the path to a schema-contracts.yaml in dir, and whether it exists.

func FormatConnectionString

func FormatConnectionString(host, port, user, password, database string) string

FormatConnectionString builds a PostgreSQL connection string from components.

func GenerateMigration

func GenerateMigration(ctx context.Context, devConnStr, schemaPath, migrationsPath, engine, name string) (string, error)

GenerateMigration computes the difference between the schema YAML (desired state) and the current state, which it obtains by replaying the existing migration directory on the dev database at devConnStr. The difference is written as a new timestamped migration file and atlas.sum is updated. It returns the path of the created file, or "" if there is no difference.

The dev database must be empty; the planner replays the migration directory into it to compute the current state.

func HasSqlDatabaseResources

func HasSqlDatabaseResources(bp *schema.Blueprint) bool

HasSqlDatabaseResources returns true if the blueprint contains any celerity/sqlDatabase resources.

func InspectCurrentSchema

func InspectCurrentSchema(ctx context.Context, a *Applier) (string, error)

InspectCurrentSchema reads the live database's public schema and renders it as a readable summary of the current deployed state.

func RehashMigrationDir

func RehashMigrationDir(migrationsPath string) error

RehashMigrationDir recomputes atlas.sum from the files currently in the migration directory. It is the deliberate "I edited a migration on purpose" step. Everything else in the CLI treats a checksum mismatch as a hard error, because on an already-applied migration it means the history no longer matches what ran.

func RenderContractImpacts

func RenderContractImpacts(w io.Writer, impacts []ContractImpact)

RenderContractImpacts writes a "Contracts affected" section for the given impacts. Blocking impacts are marked ⛔, notify impacts ⚠. It writes nothing when there are no impacts.

func RenderMigrationHistory

func RenderMigrationHistory(w io.Writer, records []MigrationRecord)

RenderMigrationHistory writes a human-readable migration history table.

func ResourceType

func ResourceType() string

ResourceType returns the blueprint resource type for SQL databases, for use by the compose generator.

func ScaffoldMigration

func ScaffoldMigration(migrationsPath, description string) (string, error)

ScaffoldMigration creates an empty, timestamped migration file for hand-written SQL and updates the atlas.sum integrity file. It returns the path of the created file.

func ValidateContracts

func ValidateContracts(cf *ContractsFile, schemas map[string]*Schema) []string

ValidateContracts checks a contracts file against the blueprint's SQL database resources and their schemas: every SQL dependency must name a known database and only tables that exist in it, and every dependency must declare a valid policy. It returns a list of human-readable problems (empty when valid). Datastore (NoSQL) dependencies are only checked for a valid policy, since NoSQL schema management is not yet implemented.

func ValidateMigrationDir

func ValidateMigrationDir(migrationsPath string) error

ValidateMigrationDir checks that the atlas.sum integrity file is present and matches the migration directory contents. Returns nil when the directory holds no migrations yet.

func ValidateMigrationFileNames

func ValidateMigrationFileNames(migrationsPath string) error

ValidateMigrationFileNames checks that every .sql file in the directory follows the <timestamp>_<description>.sql convention and that no two files share a version.

Atlas derives a migration's identity from the leading segment of its file name. Files that do not follow the convention, such as a Flyway-style "V001__name.up.sql" pair, collide on version, and the collision surfaces deep inside the executor as a panic rather than an error, so this runs before anything is executed.

func ValidateSchema

func ValidateSchema(schemaPath, engine string) error

ValidateSchema parses a schema YAML file and checks that it maps cleanly to the target engine: the file must parse, foreign keys must reference existing tables and columns, and column types must be understood. It does not require a database connection.

Types

type AppUser

type AppUser struct {
	// Name is the role to create. It is validated as an identifier, since
	// provisioning takes no free-form SQL.
	Name string

	// Password backs password authentication. Ignored in IAM mode.
	Password string

	// IAMAuth grants the engine's IAM authentication role instead of setting a
	// password, so the handler exchanges its execution role for a short-lived
	// token.
	IAMAuth bool

	// Database is the database the role is granted CONNECT on. Defaults to the
	// connected database when empty.
	Database string
}

AppUser describes the database role the application connects as.

This is deliberately not the master user. The master can drop any table and read every database on the instance, and the RDS Proxy already holds it to authenticate on the application's behalf; handing it to every handler would undo the per-handler role work. Migrations keep running as the master, the application runs as this role, and provisioning is what connects the two.

type Applier

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

Applier connects to a SQL database and applies schemas and migrations to it, backed by the embedded Atlas engine. Migration history is tracked in the atlas_schema_revisions table (see pgRevisions). Engine-specific connection concerns are delegated to a dialect implementation.

func NewApplier

func NewApplier(engine string, connStr string, logger *zap.Logger) (*Applier, error)

NewApplier creates an Applier for the given engine and connection string.

func (*Applier) Apply

func (a *Applier) Apply(ctx context.Context, schemaPath, migrationsPath, engine string) error

Apply brings the connected database up to date for local development.

Once a migration directory exists it is the only source of schema changes, so a local database comes up from exactly the migration history every other environment runs. Uncommitted schema YAML edits are reported separately (see HasUncommittedSchemaChanges) rather than being silently applied on top. Reconciling the YAML declaratively over a migrated database would drop anything the YAML cannot model, including hand-written indexes, triggers and the migration-history table itself.

The schema YAML is applied declaratively only before the first migration exists, so a new project gets a working local database without having to run `celerity schema diff` first.

The risk gate is fully open here (local dev applies everything); the gate is for deployed/live databases (see `schema apply`).

func (*Applier) ApplyDeclarative

func (a *Applier) ApplyDeclarative(ctx context.Context, schemaPath, engine string) error

ApplyDeclarative brings the connected database into line with the desired state described by a schema YAML file, applying the diff directly without writing migration files. This is the local-development path: it keeps the schema YAML as the source of truth for ephemeral databases. Committed migrations (via `celerity schema diff`) are applied by ApplyMigrationDir.

func (*Applier) ApplyMigrationDir

func (a *Applier) ApplyMigrationDir(ctx context.Context, migrationsPath string, maxRisk RiskLevel) error

ApplyMigrationDir applies pending migration files from an Atlas migration directory in timestamp order, tracking each in the atlas_schema_revisions table so already-applied migrations are skipped. Returns nil if the directory is empty or absent.

maxRisk is the highest risk level (see the migration risk header) that may be auto-applied. Pending migrations are applied in order until one exceeds maxRisk, at which point the apply stops with an error naming that migration, so a live system is never broken by an auto-applied contract change. Migrations already applied before the blocked one remain committed.

func (*Applier) Close

func (a *Applier) Close() error

Close releases the database connection.

func (*Applier) DropDatabase

func (a *Applier) DropDatabase(ctx context.Context, dbName string) error

DropDatabase removes a database if it exists. Must be called on an Applier connected to the admin database, with nothing else connected to the target.

func (*Applier) EnsureDatabase

func (a *Applier) EnsureDatabase(ctx context.Context, dbName string) error

EnsureDatabase creates a database if it does not already exist. Must be called on an Applier connected to the admin database.

func (*Applier) ExecSQL

func (a *Applier) ExecSQL(ctx context.Context, sqlContent string) error

ExecSQL executes a raw SQL string against the database.

func (*Applier) ForDatabase

func (a *Applier) ForDatabase(dbName string) (*Applier, error)

ForDatabase returns a new Applier connected to a specific database, derived from the original connection string by replacing the database path.

func (*Applier) HasUncommittedSchemaChanges

func (a *Applier) HasUncommittedSchemaChanges(
	ctx context.Context,
	schemaPath, migrationsPath, engine, scratchDBName string,
) (bool, error)

HasUncommittedSchemaChanges reports whether the schema YAML describes changes that no committed migration covers. It answers the same question as `schema diff --check`, but against a scratch database on the connection this Applier already holds rather than a throwaway container.

Must be called on an Applier connected to the admin database. The scratch database is created empty, replayed into, and dropped again.

func (*Applier) PendingMigrations

func (a *Applier) PendingMigrations(ctx context.Context, migrationsPath string) ([]PendingMigration, error)

PendingMigrations returns the migrations that are committed but not yet applied to the connected database, in apply order, each with its effective risk.

func (*Applier) ProvisionAppUser

func (a *Applier) ProvisionAppUser(ctx context.Context, user AppUser) (*ProvisionReport, error)

ProvisionAppUser creates or repairs the application database role. It is idempotent, so it can run after every deploy, and after a database is restored or replaced, without a caller having to determine whether it is needed.

It must be called on an Applier connected as the owner/master, the role that runs migrations, since it grants privileges over that role's objects. The default privileges it sets are attached to that same role, so tables created by later migrations are usable by the application without provisioning running again.

type CodegenLanguage

type CodegenLanguage string

CodegenLanguage is a target language for `schema codegen`.

const (
	LangTypeScript CodegenLanguage = "typescript"
	LangPython     CodegenLanguage = "python"
)

type Column

type Column struct {
	Type           string `yaml:"type"`
	PrimaryKey     bool   `yaml:"primaryKey"`
	Nullable       bool   `yaml:"nullable"`
	Unique         bool   `yaml:"unique"`
	Default        string `yaml:"default"`
	Description    string `yaml:"description"`
	Classification string `yaml:"classification"`
	// Tags are free-form categorisation labels for the column, surfaced in
	// exports. They have no effect on DDL.
	Tags       []string    `yaml:"tags"`
	References *ForeignKey `yaml:"references"`
}

Column describes a single table column with engine-native type.

type Constraint

type Constraint struct {
	Name       string   `yaml:"name"`
	Type       string   `yaml:"type"`
	Expression string   `yaml:"expression"`
	Columns    []string `yaml:"columns"`
}

Constraint describes a table constraint (check, unique, composite foreign key).

type Contract

type Contract struct {
	Name         string       `yaml:"name"`
	Owner        string       `yaml:"owner"`
	Dependencies []Dependency `yaml:"dependencies"`
}

Contract declares a downstream consumer and the schema objects it depends on.

type ContractImpact

type ContractImpact struct {
	Contract string
	Owner    string
	Policy   ContractPolicy
	Database string
	Tables   []string
}

ContractImpact records that a change to a database's tables touched a contract.

func EvaluateContracts

func EvaluateContracts(cf *ContractsFile, changed map[string][]string) []ContractImpact

EvaluateContracts returns the contracts affected by a set of changed tables, keyed by database resource name. A contract is affected when any table it watches on a database appears in that database's changed set.

type ContractPolicy

type ContractPolicy string

ContractPolicy is how a contract reacts when a watched table changes.

const (
	// PolicyBlocking fails CI (non-zero exit) when a watched table changes.
	PolicyBlocking ContractPolicy = "blocking"
	// PolicyNotify warns but does not affect the exit code.
	PolicyNotify ContractPolicy = "notify"
)

type ContractsFile

type ContractsFile struct {
	Contracts []Contract `yaml:"contracts"`
}

ContractsFile is a parsed schema-contracts.yaml.

func LoadContractsFile

func LoadContractsFile(path string) (*ContractsFile, error)

LoadContractsFile reads and parses a schema-contracts.yaml.

type DatabaseResource

type DatabaseResource struct {
	ResourceName   string
	Name           string
	Engine         string
	SchemaPath     string
	MigrationsPath string
	AuthMode       string
}

DatabaseResource holds the resolved configuration for a celerity/sqlDatabase blueprint resource. Paths are resolved to absolute paths.

func CollectDatabaseResources

func CollectDatabaseResources(bp *schema.Blueprint, projectRoot string) []DatabaseResource

CollectDatabaseResources extracts celerity/sqlDatabase resources from a blueprint and resolves schema/migration paths relative to the project root.

type Dependency

type Dependency struct {
	Database string   `yaml:"database"`
	Tables   []string `yaml:"tables"`
	// Datastore/Entities cover NoSQL datastores; SQL schema management ignores
	// them, but they are parsed so a combined contracts file stays valid.
	Datastore string         `yaml:"datastore"`
	Entities  []string       `yaml:"entities"`
	Policy    ContractPolicy `yaml:"policy"`
}

Dependency is a single database (or datastore) dependency within a contract.

type DriftReport

type DriftReport struct {
	Resource   string
	Target     string
	History    []string
	Structural []string
	Advanced   []string
	// StructuralTables lists the tables that drifted structurally, for schema
	// contract evaluation. Contracts, when populated by the caller, are rendered
	// in the report.
	StructuralTables []string
	Contracts        []ContractImpact
}

DriftReport describes how a live database has diverged from the state its committed migrations should have produced. It is reported at three layers, matching the schema-management spec:

  • History: the revision table vs the migration directory (migrations applied out-of-band, missing from the directory, or applied out of order).
  • Structural: the live tables/columns/indexes/keys/constraints vs the expected state (everything the schema YAML models).
  • Advanced: triggers/functions/views/RLS policies fingerprinted from the catalog (objects created by hand-written migrations), reported coarsely as changed / missing / unexpected.

Each layer is a list of human-readable lines; empty means no drift at that layer.

func DetectDrift

func DetectDrift(ctx context.Context, live *Applier, devConnStr, migrationsPath, engine string) (*DriftReport, error)

DetectDrift compares the live database behind `live` against the state its committed migrations should have produced.

History drift is always computed (it needs only the revision table and the migration directory). Structural and advanced-object drift require a clean dev database at devConnStr: the migrations recorded as applied are replayed into it to reconstruct the expected state, which is then diffed against the live database. Pass devConnStr == "" to run history drift only.

func (*DriftReport) HasDrift

func (r *DriftReport) HasDrift() bool

HasDrift reports whether any layer found drift.

func (*DriftReport) Render

func (r *DriftReport) Render(w io.Writer)

Render writes a human-readable report to w.

type ExportFormat

type ExportFormat string

ExportFormat is an output format for `schema export`.

const (
	ExportSQL        ExportFormat = "sql"
	ExportMarkdown   ExportFormat = "markdown"
	ExportJSONSchema ExportFormat = "json-schema"
	ExportMermaid    ExportFormat = "mermaid"
)

type ForeignKey

type ForeignKey struct {
	Table    string `yaml:"table"`
	Column   string `yaml:"column"`
	OnDelete string `yaml:"onDelete"`
}

ForeignKey describes a foreign key reference from a column.

type GeneratedFile

type GeneratedFile struct {
	Name    string
	Content string
}

GeneratedFile is a single codegen output: the file name (relative to the output directory) and its contents.

func GenerateCode

func GenerateCode(s *Schema, lang CodegenLanguage, resourceName string) (*GeneratedFile, error)

GenerateCode renders type-safe code for a parsed schema in the given language. resourceName names the output file and is used only for the header. v0 supports TypeScript (row interfaces + column/table constants) and Python (Pydantic models). There is no ORM coupling.

type Index

type Index struct {
	Name    string   `yaml:"name"`
	Columns []string `yaml:"columns"`
	Unique  bool     `yaml:"unique"`
	// Type is the index method (Postgres: btree, gin, gist, spgist, brin, hash;
	// MySQL: btree, hash, fulltext, spatial). Empty means the engine default
	// (btree). Only the index method is covered. Expression parts, operator
	// classes and partial-index predicates are not modelled here, and those
	// indexes belong in a hand-written migration listed under Schema.Exclude.
	Type string `yaml:"type"`
}

Index describes a table index.

type MigrationRecord

type MigrationRecord struct {
	Version       string
	Description   string
	AppliedAt     time.Time
	ExecutionTime time.Duration
	Failed        bool
	Error         string
}

MigrationRecord is a single applied migration read from the revision history.

func ReadMigrationHistory

func ReadMigrationHistory(ctx context.Context, a *Applier) ([]MigrationRecord, error)

ReadMigrationHistory returns the applied-migration history recorded in the database's atlas_schema_revisions table, ordered by version.

type PendingMigration

type PendingMigration struct {
	Name string
	Risk RiskLevel
}

PendingMigration describes a committed migration that has not yet been applied to the connected database.

type ProvisionReport

type ProvisionReport struct {
	// User is the role that was provisioned.
	User string

	// Schema is the schema its object privileges were granted in.
	Schema string

	// RoleCreated is true when the role did not exist and was created.
	RoleCreated bool

	// AuthConfigured is true when a password was set or the IAM role granted.
	AuthConfigured bool

	// IAMAuth records which authentication mode was configured.
	IAMAuth bool

	// Grants lists the privileges applied, in the order they were applied. Safe
	// to print: identifiers only, never the password.
	Grants []string
}

ProvisionReport records what provisioning actually changed, so a repeat run can honestly report that it did nothing.

func (*ProvisionReport) Changed

func (r *ProvisionReport) Changed() bool

Changed reports whether provisioning altered anything beyond re-applying grants that were already in place. Grants are idempotent and cheap, so they are re-applied every run and do not count as a change.

func (*ProvisionReport) Render

func (r *ProvisionReport) Render(w interface{ Write([]byte) (int, error) })

Render writes a human-readable summary of a provisioning run.

type RiskLevel

type RiskLevel string

RiskLevel classifies how safe it is to auto-apply a migration against a live database.

const (
	// RiskSafe changes are additive and backward-compatible with running code
	// (add table/column-with-default, add non-unique index, drop index/constraint).
	RiskSafe RiskLevel = "safe"
	// RiskRisky changes are data-dependent and can fail or lock depending on
	// existing data (set NOT NULL, add unique index, add foreign key/check,
	// change column type, add NOT NULL column without a default).
	RiskRisky RiskLevel = "risky"
	// RiskBreaking changes are destructive/backward-incompatible with running
	// code (drop table/column/schema).
	RiskBreaking RiskLevel = "breaking"
)

func ReadMigrationRisk

func ReadMigrationRisk(path string) (RiskLevel, error)

ReadMigrationRisk returns the risk classification recorded in a migration file's header (falling back to risky when absent).

type Schema

type Schema struct {
	Tables     map[string]Table `yaml:"tables"`
	Extensions []string         `yaml:"extensions"`
	// Exclude lists objects that exist in the database but are deliberately not
	// modelled here, typically because a hand-written migration creates them
	// (expression or partial indexes, triggers, functions, policies). Patterns
	// use Atlas's glob syntax relative to the managed schema, e.g.
	// "audit_log.index[idx_*]" or "legacy_*". Excluded objects are never
	// created, altered or dropped by schema-YAML-driven diffs.
	Exclude []string `yaml:"exclude"`
}

Schema represents a parsed SQL database schema YAML file. Column types are engine-native (e.g. "serial", "varchar(50)", "jsonb").

func ParseSchema

func ParseSchema(r io.Reader) (*Schema, error)

ParseSchema parses a SQL schema YAML from a reader.

func ParseSchemaFile

func ParseSchemaFile(path string) (*Schema, error)

ParseSchemaFile reads and parses a SQL schema YAML file from disk.

type Table

type Table struct {
	Description string            `yaml:"description"`
	Columns     map[string]Column `yaml:"columns"`
	Indexes     []Index           `yaml:"indexes"`
	Constraints []Constraint      `yaml:"constraints"`
	// Tags are free-form categorisation labels (e.g. "financial", "core-entity")
	// surfaced in exports. They have no effect on DDL.
	Tags []string `yaml:"tags"`
	// TypeName overrides the generated entity type name for this table (used by
	// `schema codegen`). When empty, the name is derived by singularising the
	// table name (e.g. customers → Customer). Set this for irregular plurals the
	// singulariser gets wrong.
	TypeName string `yaml:"typeName"`
}

Table describes a single database table.

Jump to

Keyboard shortcuts

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