Documentation
¶
Overview ¶
Package model reads tanGO models: plain Go structs whose fields, through their tango:"…" struct tags, describe a table's columns, primary key, unique and indexed columns, and foreign keys.
Apps register their models with a Registry, which validates each one and records its ModelMeta and FieldMeta. The rest of tanGO (the store, the migration generator and the admin) works from that metadata. See https://tangoframework.com/docs/guides/models-and-tags/.
Index ¶
- Constants
- Variables
- type Date
- func (d Date) AddDays(n int) (Date, error)
- func (d Date) After(other Date) bool
- func (d Date) Before(other Date) bool
- func (d Date) Compare(other Date) int
- func (d Date) Day() int
- func (d Date) Equal(other Date) bool
- func (d Date) In(loc *time.Location) time.Time
- func (d Date) IsZero() bool
- func (d Date) MarshalJSON() ([]byte, error)
- func (d Date) MarshalText() ([]byte, error)
- func (d Date) Month() time.Month
- func (d *Date) Scan(src any) error
- func (d Date) String() string
- func (d *Date) UnmarshalJSON(data []byte) error
- func (d *Date) UnmarshalText(text []byte) error
- func (d Date) Value() (driver.Value, error)
- func (d Date) Year() int
- type FieldMeta
- type ModelMeta
- type Registry
- type RelationMeta
Constants ¶
const MaxVarcharLength = 10485760
MaxVarcharLength is the largest length tango:"varchar=n" accepts: the largest VARCHAR(n) PostgreSQL allows, so tanGO adds no ceiling of its own.
Variables ¶
var ErrDuplicateModel = errors.New("tango: duplicate model name")
ErrDuplicateModel is returned by Registry.Register when a model with the same derived Name has already been registered.
var ErrEmbeddedField = errors.New("tango: embedded fields are not supported")
ErrEmbeddedField is returned by Registry.Register when a struct has an embedded (anonymous) field. Embedded fields are rejected outright, not flattened.
var ErrInvalidDate = errors.New("tango: invalid date")
ErrInvalidDate is returned for a calendar date that does not exist, for a year outside 0001 through 9999, and for text that is not exactly YYYY-MM-DD.
var ErrInvalidFieldTag = errors.New("tango: invalid field tag")
ErrInvalidFieldTag is returned by Registry.Register when a field's tango tag declares a string length wrongly: varchar without a positive length, a length beyond MaxVarcharLength, varchar together with text, a repeated varchar or text, or either on a field that is not a string. The error names the model and field.
var ErrInvalidRelation = errors.New("tango: invalid relation")
ErrInvalidRelation is returned by Registry.Register when a belongs_to or has_many tag sits on a field of the wrong Go type, is combined with another tango option, or has no value; and by Registry.ValidateRelations when a declared relation names a target or foreign key that does not match it. The error names the model and field.
var ErrMultiplePrimaryKeys = errors.New("tango: model has multiple primary key fields")
ErrMultiplePrimaryKeys is returned by Registry.Register when a struct has more than one field tagged tango:"pk".
var ErrNoPrimaryKey = errors.New("tango: model has no primary key field")
ErrNoPrimaryKey is returned by Registry.Register when a struct has no field tagged tango:"pk".
var ErrUnknownForeignKeyTarget = errors.New("tango: foreign key targets an unregistered model")
ErrUnknownForeignKeyTarget is returned by ValidateForeignKeys when a field's tango:"fk=X" tag names a model X that no installed app ever registered.
var ErrUnsupportedField = errors.New("tango: unsupported field type")
ErrUnsupportedField is returned by Registry.Register when a field's kind isn't supported by the metadata layer.
Functions ¶
This section is empty.
Types ¶
type Date ¶ added in v0.9.0
type Date struct {
// contains filtered or unexported fields
}
Date is a calendar date with no time of day and no zone. Its fields are unexported, so only the constructors build one and every Date is a real day. The zero value means no date and is distinct from 0001-01-01. Dates are comparable with ==.
func DateOf ¶ added in v0.9.0
DateOf returns the calendar date that t shows in its own location, as t.Date() reports it. It never converts t to UTC. It returns ErrInvalidDate when that year is outside 0001 through 9999.
func MustDate ¶ added in v0.9.0
MustDate is NewDate for literals and tests. It panics on an invalid date.
func NewDate ¶ added in v0.9.0
NewDate returns the date year-month-day, or ErrInvalidDate if no such date exists or the year is outside 0001 through 9999.
func ParseDate ¶ added in v0.9.0
ParseDate parses exactly YYYY-MM-DD. It rejects every other form, including a datetime, unpadded fields and an empty string.
func (Date) AddDays ¶ added in v0.9.0
AddDays returns the date n days after d. The zero Date stays zero. It returns ErrInvalidDate when the result leaves years 0001 through 9999.
func (Date) Before ¶ added in v0.9.0
Before, After and Equal report the order of d relative to other.
func (Date) Compare ¶ added in v0.9.0
Compare returns -1, 0 or 1 as d is before, the same as, or after other. The zero Date sorts before every real date.
func (Date) In ¶ added in v0.9.0
In returns midnight at the start of d's calendar date in loc. The zero Date returns the zero time.Time. To take today's date in a zone, use DateOf(time.Now().In(loc)).
func (Date) IsZero ¶ added in v0.9.0
IsZero reports whether d is the zero value, which means no date.
func (Date) MarshalJSON ¶ added in v0.9.0
MarshalJSON writes the zero Date as null and any other as "YYYY-MM-DD".
func (Date) MarshalText ¶ added in v0.9.0
MarshalText writes the zero Date as the empty string and any other as YYYY-MM-DD.
func (*Date) Scan ¶ added in v0.9.0
Scan implements sql.Scanner. It accepts NULL (the zero Date), a time.Time (the calendar components in that value's own location, with no zone conversion), and an exact YYYY-MM-DD string or bytes. Anything else is an error, including a datetime string.
func (Date) String ¶ added in v0.9.0
String returns YYYY-MM-DD, and the empty string for the zero Date.
func (*Date) UnmarshalJSON ¶ added in v0.9.0
UnmarshalJSON reads null as the zero Date and otherwise requires an exact "YYYY-MM-DD" string. The empty string is rejected.
func (*Date) UnmarshalText ¶ added in v0.9.0
UnmarshalText reads the empty string as the zero Date and otherwise requires an exact YYYY-MM-DD.
type FieldMeta ¶
type FieldMeta struct {
Name string
Type reflect.Type
PrimaryKey bool
Unique bool
Indexed bool
Editable bool
ForeignKey string // target model name from tango:"fk=<Name>"; "" if not a foreign key
// MaxLength is the most runes a bounded string may hold, from
// tango:"varchar=n"; 0 means unbounded (a bare string or tango:"text").
MaxLength int
// JSON is true for a string field declared tango:"json": it holds JSON
// text, which Store.Create and Store.Update check is valid. The column is
// ordinary text.
JSON bool
}
FieldMeta describes an exported Go struct field.
type ModelMeta ¶
type ModelMeta struct {
Name string
App string
Type reflect.Type
Fields []FieldMeta
// Relations are the fields declared with tango:"belongs_to=…" or
// tango:"has_many=…". They are not columns and never appear in Fields.
Relations []RelationMeta
}
ModelMeta describes a registered Go struct model.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry stores model metadata by Go type name.
func NewRegistry ¶
func NewRegistry() *Registry
NewRegistry returns an empty, ready-to-use model Registry.
func (*Registry) All ¶
All returns every registered model's metadata, sorted by Name for a deterministic order.
func (*Registry) Register ¶
Register introspects a struct value and stores its model metadata. It returns an error, and registers nothing, if the struct's derived name is already registered, if it has zero or multiple primary key fields, if it has an embedded field, or if any field's kind is unsupported.
func (*Registry) SetCurrentApp ¶
SetCurrentApp records the name of the App currently registering models, populating ModelMeta.App for every model Register call that follows, until the next SetCurrentApp call. It is intended to be called by tango.Registry.RunRegistration immediately before invoking each app's Register callback, not by app authors directly.
func (*Registry) ValidateForeignKeys ¶
ValidateForeignKeys checks that every registered field's tango:"fk=X" tag names a model X that is also registered in this same Registry. It is intended to run once, after every installed app has finished registering (e.g. from tango.Check), not per-model at Register time — so InstalledApps order never constrains which app may declare a foreign key relative to the app that registers its target.
func (*Registry) ValidateRelations ¶ added in v0.9.0
ValidateRelations checks every relation recorded in ModelMeta.Relations against the registered models: the target must be registered, a belongs_to key must be an fk= to that target, a has_many key must be an fk= back to the owner, and each key's Go type must equal the primary key type it refers to. Like ValidateForeignKeys it runs once, after every installed app has registered, so registration order does not matter.
type RelationMeta ¶ added in v0.9.0
type RelationMeta struct {
Name string // Go field name, e.g. "Account"
Direction string // the tag keyword: "belongs_to" or "has_many"
// ForeignKey is the field the tag names. For belongs_to it is the owner's
// field holding the target's key; for has_many it is the target's field
// that refers back to the owner.
ForeignKey string
Target string // target model name, the Go type name of the related struct
Type reflect.Type // the field's Go type: *Account or []Comment
TargetType reflect.Type // the related struct type: Account or Comment
}
RelationMeta describes a relation field: a pointer to a struct tagged belongs_to, or a slice of structs tagged has_many.