Documentation
¶
Overview ¶
Package emit renders generated Go code from a proven mapping.
It discovers nothing. Every fact it needs — which table an entity maps to, which columns it exposes, what each column's PostgreSQL type is and whether it is nullable — was established by gen/reconcile and arrives in a model.Mapping. The emitter's whole job is to write that down in Go, which is why it can be tested against a mapping built by hand and why generation can never disagree with the check that preceded it.
What gets generated ¶
For each entity package, three files:
orm_tables.gen.go the table descriptor and its typed columns orm_meta.gen.go the entity metadata and its scanner orm_db.gen.go the DB struct that wires repositories to metadata
Capabilities come from PostgreSQL ¶
Which descriptor a column receives is decided by its PostgreSQL type, not by whatever Go type sits opposite it. A jsonb column does not get Gt merely because some Go representation of it happens to be comparable, and a text column gets ILike because PostgreSQL has ILIKE, not because Go strings have methods. The capability lattice is the schema's, and the generator is where that is enforced.
Determinism ¶
Two runs over the same structs and the same schema produce identical bytes. Entities and columns come out in a fixed order, imports are sorted, no map is ranged without sorting, and nothing carries a timestamp or a version. The output is formatted with go/format before it is written, so a formatting change in the emitter cannot show up as a diff.
Index ¶
Constants ¶
const ( // DBTypeName is the generated per-package database handle. DBTypeName = "DB" // DBCtorName constructs it. DBCtorName = "New" )
The naming policy.
Public names come from the table, private ones from the entity. That split is not arbitrary: the descriptor a caller writes — Users.Email — reads as the table it queries, and the table is the thing PostgreSQL owns. The internal identifiers are per-entity because two entities that generate into one directory under one name is exactly what E014 reports, and deriving them from the entity keeps that check honest.
entity User, table public.users Users the table descriptor value (from the table) DB.Users the repository field (from the table) usersSource the table occurrence Users reads (from the table) userTable the descriptor's type (from the entity) newUserTable builds descriptors for one alias (from the entity) userMeta the generated entity metadata (from the entity) userDest the generated scanner (from the entity) userValue the generated value accessor (from the entity)
Nothing is renamed to avoid a clash. A generated identifier that collides with one the author already wrote is reported, because silently becoming Users2 would leave the caller reading documentation that describes Users.
const Header = "// Code generated by orm. DO NOT EDIT."
Header marks every generated file. The convention is the one the Go tool itself recognises, so tooling that skips generated code skips these.
Variables ¶
var GeneratedFiles = []string{tablesFile, metaFile, relFile, dbFile}
GeneratedFiles are the names emit writes into a package. Callers that need to tell generated code from hand-written code — the collision check does — use this rather than guessing.
Functions ¶
func IsGenerated ¶
IsGenerated reports whether a file name is one emit writes.
Types ¶
type File ¶
type File struct {
// Path is where the file belongs.
Path string
// Content is formatted Go source.
Content []byte
}
File is one rendered, formatted source file.
func Generate ¶
Generate renders every generated file for every package in the mapping.
It renders all of them or none. A caller that wrote the first file and then discovered the second could not be generated would leave a package that no longer compiles, which is a worse state than the one it started in.
type Input ¶
type Input struct {
Mapping *model.Mapping
// Reserved lists, per package path, the identifiers the author's own files
// already declare. A generated name that collides with one of them is
// reported rather than renamed.
Reserved map[string][]string
}
Input is what generation needs. Everything in it was established by reconciliation; nothing here is discovered.