On this page
Package model provides the resolved intermediate representation for pgdesign, the canonical in-memory schema that all downstream packages consume.
#internal/model
#internal/model
Package model provides the resolved intermediate representation for pgdesign, the canonical in-memory schema that all downstream packages consume.
Adding a new schema object type (e.g., domain, sequence, composite type):
1. parse/types.go — raw TOML struct for the new object 2. parse/parse.go — parse function to populate the raw struct 3. model/model.go — model struct + field on Schema 4. model/build.go — resolve function (type resolution, dependency wiring) 5. validate/validate.go — validation checks (E-codes) 6. generate/generate.go — DDL generation section 7. sql/sql.go — DDL helper functions (CREATE, ALTER, DROP) 8. diff/diff.go — diff fields + comparison (use matchObjects[T]) 9. migrate/generate.go — migration op generation 10. migrate/sql_gen.go — op-to-SQL rendering 11. migrate/parse_migration.go — TOML serialization (tomlDDL fields) 12. risk/risk.go — risk classification for new ops 13. introspect/introspect.go — pg_catalog query 14. introspect/export.go — TOML export 15. generate/d2.go — diagram rendering (optional) 16. generate/doc.go — documentation output (optional)
#TowardReferencing
const TowardReferencing WalkDirection = iotaTowardReferencing follows Reverse edges: from a referenced table into the tables whose FKs point at it. This is the direction ON DELETE actions propagate at runtime (deleting a referenced row mutates rows in the referencing tables).
#TowardReferenced
const TowardReferencedTowardReferenced follows Forward edges: from a referencing table out to the tables it references (toward the potential delete origins whose DELETE would write into the start table).
#BuildOption
type BuildOption func(*buildOptions)BuildOption customizes model construction. Options are the extension point for build inputs that come from OUTSIDE the schema TOML (e.g. the project's [imports] declarations, which live in pgdesign.toml). Existing callers pass no options and get the same behavior as before.
#FKEdge
type FKEdge structFKEdge represents a single foreign key relationship between two tables. Both endpoints carry their schema so the edge is unambiguous across schemas; the FromTable/ToTable fields remain the bare table names (codegen and workload use them for type/identifier derivation), and TableKey combines them into the graph's canonical (schema, name) map key.
#FKGraph
type FKGraph structFKGraph is a pre-computed graph of foreign key relationships across all tables. Every map is keyed by TableKey(schema, name).
#WalkDirection
type WalkDirection intWalkDirection selects which way WalkCascade traverses FK edges.
#FKNodeProjection
type FKNodeProjection structFKNodeProjection is one table node in an FKGraphProjection: its (schema, name) identity plus the constraint fan counts.
#FKEdgeProjection
type FKEdgeProjection structFKEdgeProjection is one FK edge in an FKGraphProjection. It mirrors FKEdge, including the schema qualification of both endpoints and the Imported flag, so the projection is a faithful, self-describing snapshot.
#FKGraphProjection
type FKGraphProjection structFKGraphProjection is a deterministic, (schema, name)-keyed, JSON-able snapshot of an FKGraph. It is EXCLUDED from schema identity (the graph is a derived structure, never a declared one — FKGraph itself is json:"-"), but it is carried in the API payload so consumers can read the resolved relationship graph without re-deriving it. Nodes and edges are sorted, so json.Marshal of a projection is stable regardless of the source graph's map iteration order.
#NamedTransition
type NamedTransition structNamedTransition holds a single named state machine transition with its metadata. Used by codegen to generate per-transition methods.
#SMTransitionMap
type SMTransitionMap structSMTransitionMap holds the allowed transitions for a state machine type. Keys are source state names, values are the set of reachable target states.
#SMState
type SMState structSMState is a single state of a state-machine type. Its declaration order is SEMANTIC (it becomes the enum label order in the generated CREATE TYPE ... AS ENUM), so the collection is never reordered.
#SMTransition
type SMTransition structSMTransition is a single named transition of a state-machine type. The transition collection is a CANONICAL-ONLY set (declaration order is not observable); From is a source-state SET.
#StateMachine
type StateMachine structStateMachine is the first-class model representation of a state-machine type definition. It carries the full transition graph WITH comments — the identity content that has no home in the derived StateMachineTransitions duplicate or in the state-name Enum. Populated during Build() from the semtype registry for every state-machine type in use. This is the identity carrier for state-machine types (encoded as a first-class object by internal/enc); the state names additionally materialize into a model Enum for DDL generation.
#Schema
type Schema structSchema is the top-level resolved schema.
#View
type View structView represents a resolved view definition.
#MaterializedView
type MaterializedView structMaterializedView represents a resolved materialized view definition.
#Table
type Table structTable represents a resolved table definition.
#Column
type Column structColumn represents a resolved column definition.
#FK
type FK structFK represents a resolved foreign key constraint.
#Index
type Index structIndex represents a resolved index definition.
#UniqueConstraint
type UniqueConstraint structUniqueConstraint represents a unique constraint.
#CheckConstraint
type CheckConstraint structCheckConstraint represents a check constraint.
#ExclusionElement
type ExclusionElement structExclusionElement represents a single element in an exclusion constraint.
#ExclusionConstraint
type ExclusionConstraint structExclusionConstraint represents an exclusion constraint.
#Policy
type Policy structPolicy represents a row-level security (RLS) policy.
#Trigger
type Trigger structTrigger represents a user-defined trigger on a table.
#Enum
type Enum structEnum represents a resolved enum type.
#Sequence
type Sequence structSequence represents a standalone PostgreSQL sequence.
#FunctionArg
type FunctionArg structFunctionArg represents a single argument to a function or procedure.
#Function
type Function structFunction represents a resolved function or procedure definition.
#Domain
type Domain structDomain represents a resolved PostgreSQL domain type.
#CompositeField
type CompositeField structCompositeField represents a single field in a composite type.
#CompositeType
type CompositeType structCompositeType represents a resolved PostgreSQL composite type.
#PartitionSpec
type PartitionSpec structPartitionSpec represents partitioning configuration.
#MaintenanceConfig
type MaintenanceConfig structMaintenanceConfig represents maintenance configuration for a table.
#WithImports
func WithImports(imports map[string]string) BuildOptionWithImports supplies the project's declared import aliases (alias -> target PG schema) so alias:table FK references resolve at build time (roadmap 7.1).
#WithImportedTables
func WithImportedTables(tables []Table) BuildOptionWithImportedTables supplies the REFERENCE tables decoded from the vendored import surface (roadmap 7.3). They populate Schema.ImportedTables and are unioned into TablesByName and the FKGraph so imported-FK targets resolve, but are kept out of Schema.Tables so every Tables-iterating consumer is fail-closed by omission.
#Build
func Build(raw *parse.RawSchema, reg *semtype.Registry, opts ...BuildOption) (*Schema, diagnostic.Diagnostics)Build constructs a resolved Schema from raw parse output and a type registry. It returns the schema (possibly partial) and any diagnostics encountered.
#BuildMulti
func BuildMulti(raws []*parse.RawSchema, reg *semtype.Registry, opts ...BuildOption) (*Schema, diagnostic.Diagnostics)BuildMulti constructs a resolved Schema from multiple raw schemas and a type registry. Tables, enums, and extensions from all schemas are merged into one Schema. Each table's Schema field is set from its source RawSchema's meta.schema. The returned Schema.Name is empty (multi-schema has no single name).
#IsStateMachineColumn
func IsStateMachineColumn(col Column, reg *semtype.Registry) boolIsStateMachineColumn returns true if the column's semantic type is a state machine.
#TableKey
func TableKey(schema, name string) stringTableKey is THE canonical map key for a table across the model package. TablesByName, the FKGraph adjacency maps (Forward/Reverse/FanIn/FanOut), the topological sort, and group resolution all key on it. The rule is a single function of (schema, name): "
This reconciles the two historical conventions — TablesByName's leading-dot ".name" form for empty schemas and the FKGraph's schema-blind bare names — into one rule, so a table has exactly one identity everywhere and same-named tables in different schemas never collide in the graph.
#FKGraphFromProjection
func FKGraphFromProjection(p FKGraphProjection) *FKGraphFKGraphFromProjection reconstructs an FKGraph from a projection. Forward and Reverse are rebuilt from the edge list (keyed by TableKey); FanIn/FanOut are taken from the node records. Project∘FKGraphFromProjection∘Project is the identity on the projection (round-trip stable).
#StrPtr
func StrPtr(s string) *stringStrPtr returns a pointer to the given string. Used for constructing struct literals with *string fields.
#Int64Ptr
func Int64Ptr(v int64) *int64Int64Ptr returns a pointer to the given int64. Used for constructing struct literals with *int64 fields.
#Float64Ptr
func Float64Ptr(v float64) *float64Float64Ptr returns a pointer to the given float64. Used for constructing struct literals with *float64 fields.
#Schema.Canonicalize
func (s *Schema) Canonicalize()Canonicalize is the shared finalize routine that puts a resolved Schema into canonical form. It is invoked by Build, BuildMulti, Introspect, and the FilterByGroups/FilterBySource filters so that every schema — regardless of origin (TOML declaration order or introspect ORDER BY) — serializes to the same bytes.
It performs three kinds of work:
1. Ordering. Per-table collections (FKs, indexes, uniques, checks, exclusions, policies, triggers), materialized-view indexes, top-level type collections (enums, domains, composite types, sequences), and Extensions are sorted alphabetically. Tables, views, materialized views, and functions are ordered topologically with an alphabetical tie-break. Columns, enum values, composite-type fields, function args, partition key columns, FK column correspondence, and index key-column order are SOURCE-ORDERED and never sorted — their order is semantic.
2. Derived structures. TablesByName and the FKGraph are rebuilt from the (now canonical) tables. Callers that mutate the table set — the group and source filters — rely on this to avoid carrying a stale graph.
3. Expression normalization (roadmap 1.2, activating full L1(a)). N-normalizes every expression-bearing field into the IR (defaults, CHECK expressions, index/exclusion predicates, policy USING/WITH CHECK, generated-column expressions, domain CHECK/default). This is what makes enc(a) = enc(b) iff a ≈_syn b hold over expressions, not just structure. N is best-effort total: an expression that does not parse (user SQL can be partial) is left VERBATIM (trimmed) rather than erroring, so schemas that Build accepted before still Build.
Canonicalize is idempotent: running it twice yields the same result.
#FKGraph.WalkCascade
func (g *FKGraph) WalkCascade(start string, dir WalkDirection, maxDepth int, follow func(edge FKEdge, firstHop bool) bool, visit func(path []FKEdge))WalkCascade explores every simple path out of start, following FK edges in the given direction. start is a TableKey(schema, name) key. maxDepth bounds the path length: when maxDepth > 0 the walk never extends a path beyond maxDepth edges; maxDepth <= 0 means unbounded. follow reports whether an edge may be traversed; firstHop is true for edges directly attached to start. visit is invoked at every step with the full edge path from start (len(path) >= 1); the slice is reused between calls, so callers must copy it if they retain it. Cycles are cut by never revisiting a table already on the current path. Exploring all simple paths is worst-case exponential, but FK graphs are small and sparse in practice.
#FKGraph.CascadeDepth
func (g *FKGraph) CascadeDepth(table string) intCascadeDepth returns the length of the longest ON DELETE CASCADE chain triggered by deleting rows from the given table. table is a TableKey(schema, name) key.
#FKGraph.CascadeBreadth
func (g *FKGraph) CascadeBreadth(table string) intCascadeBreadth returns the total count of distinct tables whose rows are deleted when rows are deleted from the given table (transitively, via CASCADE edges). Does NOT count the starting table. table is a TableKey(schema, name) key.
#FKGraph.CascadeChain
func (g *FKGraph) CascadeChain(table string) []stringCascadeChain returns the distinct tables affected by deleting rows from the given table, in first-reached DFS order, as TableKey(schema, name) keys. The argument is likewise a TableKey key. Does NOT include the starting table. Returns nil if no cascade edges exist.
#Schema.ReferencedTableKeys
func (s *Schema) ReferencedTableKeys() map[string]boolReferencedTableKeys returns the set of TableKey(schema, name) keys that are the target of at least one FK declared by an owned table. This is THE single union-aware orphan-detection helper (roadmap 7.3) consumed by both W002 (internal/validate) and C103 (cmd/pgdesign) — replacing the two divergent raw-string scans that keyed on fk.RefSchema+"."+fk.RefTable and so could mismatch the TableKey convention (leading-dot vs bare for empty schemas) and bypassed the import union. Each FK target is resolved through TableByName (the union of owned and imported tables) so an imported-FK target keys correctly and never causes a spuriously-orphaned local table; unresolved targets fall back to the raw (schema, name) key so a dangling FK is still counted as an incoming reference (E204 reports the dangling ref separately).
#Schema.BuildFKGraph
func (s *Schema) BuildFKGraph()BuildFKGraph constructs the FK graph from all tables. Safe to call multiple times; rebuilds each time. Called automatically by Build() and BuildMulti().
#FKGraph.Project
func (g *FKGraph) Project() FKGraphProjectionProject produces the deterministic projection of the graph. Edges are read from Forward (the authoritative edge set — every edge appears exactly once there) and sorted; nodes are the union of edge endpoints, each carrying its FanIn/FanOut from the graph.
#Schema.TableOrder
func (s *Schema) TableOrder() []TableTableOrder returns tables in dependency order (topo-sorted). Cycle group tables appear after their non-cyclic dependencies.
#Schema.TableByName
func (s *Schema) TableByName(schema, name string) *TableTableByName looks up a table by schema and name.
#Schema.FilterByGroups
func (s *Schema) FilterByGroups(groupNames []string) *SchemaFilterByGroups returns a shallow copy of the schema containing only tables that belong to at least one of the named groups. Other schema fields (enums, views, etc.) are preserved as-is. If groupNames is empty, the original schema is returned unchanged.
#Schema.FilterBySource
func (s *Schema) FilterBySource(sources []string) *SchemaFilterBySource returns a shallow copy of the schema containing only tables whose SourceFile basename matches one of the given source filenames. Other schema fields (enums, domains, views, etc.) are preserved as-is — types pass through because codegen needs them regardless of which source file defined them. If sources is empty, the original schema is returned unchanged.
#Table.HasIndexCovering
func (t *Table) HasIndexCovering(columns []string) boolHasIndexCovering returns true if any index's leading columns cover all of the given columns (prefix coverage).
#Table.CandidateKeys
func (t *Table) CandidateKeys() [][]stringCandidateKeys computes candidate keys from the table's functional dependencies. The result is cached after the first call.