Documentation
¶
Overview ¶
Package viewdeps finds, drops, and restores the views and materialized views that transitively depend on a set of tables, so DDL PostgreSQL refuses while a dependent view exists — DROP TABLE, DROP COLUMN, ALTER COLUMN TYPE — can proceed.
Discovery walks pg_depend/pg_rewrite rather than matching view names, so it is complete regardless of how a view is named or which schema it lives in. A name-convention sweep silently misses a view outside the connection's search_path — the DROP resolves to nothing and succeeds — and the blocked DDL then fails much later with a confusing error.
The package deliberately depends only on the standard library so callers can use it with any driver: *sql.DB, *sql.Tx and gorm's connection pool all satisfy Querier as-is.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Definition ¶
type Definition struct {
View
// SQL is the view body from pg_get_viewdef. Note this is the *expanded*
// definition: a view written as "SELECT a.*" comes back with every column
// listed, so restoring after a column was dropped fails loudly rather than
// silently changing the view's shape.
SQL string
// Indexes are complete CREATE INDEX statements. Materialized views only —
// and load-bearing, since REFRESH ... CONCURRENTLY requires a unique index.
Indexes []string
Owner string
Comment string
Grants []string
}
Definition is everything needed to recreate a view exactly as it was. It is read from the catalog before the view is dropped, so a view no migration owns survives a schema change instead of blocking it or being lost.
func (Definition) CreateStatements ¶
func (d Definition) CreateStatements() []string
CreateStatements returns the ordered DDL that recreates the view: the view itself, then owner, indexes, comment and grants. Materialized views are created WITH DATA so they are queryable immediately — an unpopulated materialized view errors on every read until someone refreshes it.
type DropOptions ¶
type DropOptions struct {
// Tables whose dependent views block the pending DDL. Empty is a no-op.
Tables []Table
// Query reads the dependency graph. Required.
Query Querier
// Exec runs each DROP and each restore statement. Required.
Exec Exec
// Owned reports whether the caller recreates this view itself. Owned views
// are dropped and left to the caller — restoring them from the captured
// definition would resurrect a stale one. Unowned views are captured before
// the drop and rebuilt by the returned restore func. Nil owns nothing.
Owned func(View) bool
// Logf, when set, receives one line per dropped view.
Logf func(format string, args ...any)
}
DropOptions configures Sweep.
type Exec ¶
Exec runs a single DDL statement. Callers supply the execution policy: the migrate package wraps each statement in a bounded lock_timeout with retry, and a gorm caller routes through *gorm.DB so an open transaction stays in scope.
type Querier ¶
type Querier interface {
QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
}
Querier reads the dependency graph. *sql.DB, *sql.Tx, *sql.Conn and gorm's ConnPool all satisfy it without an adapter.
type RestoreError ¶
RestoreError reports a view that was dropped to allow a schema change and could not be recreated. It carries the full DDL so an operator can replay it by hand — the database is otherwise migrated correctly but missing the view.
func (*RestoreError) Error ¶
func (e *RestoreError) Error() string
func (*RestoreError) Unwrap ¶
func (e *RestoreError) Unwrap() error
type Table ¶
Table identifies a relation whose dependents must be cleared. An empty Schema is resolved through the connection's search_path, which is usually what a caller migrating its own database wants; set it only to target a specific schema.
type View ¶
View identifies a live view or materialized view. Kind is pg_class.relkind: "v" for a view, "m" for a materialized view.
func Dependents ¶
Dependents returns every view and materialized view that transitively depends on any of tables, in dependency order: a view always follows everything it reads. Tables that do not exist are ignored; the tables themselves are never returned.
func Lookup ¶
Lookup resolves relation names to schema-qualified view refs, skipping names that do not exist or name something that is not a view.
func Sweep ¶
Sweep drops every view that transitively depends on opts.Tables and returns the views it dropped plus a func that restores the unowned ones.
Call the restore func after the schema change, and after whatever recreates the owned views — an unowned view may be built on top of one of them. Restoring is not atomic with the DDL; a failure returns a *RestoreError carrying the DDL so the view can be replayed by hand.
func (View) DropStatement ¶
DropStatement returns the schema-qualified, identifier-quoted DROP. CASCADE is unconditional: a view built on this one is itself a dependent that has already been captured, so taking it here is both safe and necessary.
func (View) Materialized ¶
Materialized reports whether the view holds its own copy of the data.