Documentation ¶
Overview ¶
The `model` package essentially provides a lightweight object relational model (ORM) based on sqlite3 intended to support the needs of the `container` package. Each entity (table) is modeled by a struct. Each field (column) is Described using tags:
sql: "-" The field is omitted. `sql:"pk"` The primary key. `sql:"pk(field;field;..)"` The generated primary key. `sql:"key"` The field is part of the natural key. `sql:"fk(table flags...)"` Foreign key with optional flags: +must = referenced model must exist. +cascade = cascade delete. `sql:"unique(G)"` Unique index. `G` = unique-together fields. `sql:"index(G)"` Non-unique index. `G` = unique-together fields. `sql:"const"` The field is immutable and not included on update. `sql:"virtual"` The field is read-only and managed internally by the DB. `sql:"dn"` The field detail level. n = level number. `sql:incremented` The field is auto-incremented.
Each struct must implement the `Model` interface. Basic CRUD operations may be performed on each model using the `DB` interface which together with the `Model` interface provides value-added features and optimizations.
Examples:
Define a model.
type Person struct { ID string `sql:"pk"` First string `sql:"key"` Last string `sql:"key" Age int } func (p *Person) Pk() string { return p.ID }
Insert the model:
person := &Person{ First: "Elmer", Last: "Fudd", Age: 55, } err := DB.Insert(person)
In the event the primary key (PK) field is not populated, the DB will derive (generate) its value as a sha1 of the natural key fields.
Update the model:
person.Age = 62 err := DB.Update(person)
Delete the model by natural key:
person := &Person{ First: "Elmer", Last: "Fudd", } err := DB.Delete(person)
Get (fetch) a single model by natural key. This will populate the fields with data from the DB.
person := &Person{ First: "Elmer", Last: "Fudd", } err := DB.Get(person)
List (fetch) all models.
persons := []Person{} err := DB.List(&persons, ListOptions{})
List (fetch) specific models. The `ListOptions` may be used to qualify or paginate the List() result set. All predicates may be combined.
Count (only):
err := DB.List(&persons, ListOptions{Count: true})
Paginate the result:
err := DB.List( &persons, ListOptions{ Page: { Offset: 3, // page 3. Limit: 10, // 10 models per page. }, })
List specific models. List persons with the last name of "Fudd" and legal to vote.
err := DB.List( &persons, ListOptions{ Predicate: And( Eq("Name", "Fudd"), Gt("Age": 17), }, })
Index ¶
- Constants
- Variables
- func Describe(model Model) (s string)
- type AndPredicate
- type Base
- type Client
- func (r *Client) Begin(labels ...string) (tx *Tx, error error)
- func (r *Client) Close(delete bool) (err error)
- func (r *Client) Count(model Model, predicate Predicate) (n int64, err error)
- func (r *Client) Delete(model Model) (err error)
- func (r *Client) EndWatch(watch *Watch)
- func (r *Client) Execute(sql string) (result sql.Result, err error)
- func (r *Client) Find(model interface{}, options ListOptions) (itr fb.Iterator, err error)
- func (r *Client) Get(model Model) (err error)
- func (r *Client) Insert(model Model) (err error)
- func (r *Client) List(list interface{}, options ListOptions) (err error)
- func (r *Client) Open(delete bool) (err error)
- func (r *Client) Update(model Model) (err error)
- func (r *Client) Watch(model Model, handler EventHandler) (w *Watch, err error)
- type CompoundPredicate
- type DB
- type DBTX
- type DataModel
- func (r *DataModel) Add(md *Definition)
- func (r *DataModel) DDL() (list []string, err error)
- func (r *DataModel) Definitions() (list Definitions)
- func (r *DataModel) Deleted(tx *Tx, model interface{}) (cascaded fb.Iterator, err error)
- func (r *DataModel) Find(kind string) (md *Definition, found bool)
- func (r *DataModel) FindWith(model interface{}) (md *Definition, found bool)
- type Definition
- func (r *Definition) Field(name string) *Field
- func (r *Definition) Fks() []*FK
- func (r *Definition) IsKind(kind string) bool
- func (r *Definition) KeyFields() []*Field
- func (r *Definition) MutableFields() []*Field
- func (r *Definition) NewModel() (m interface{})
- func (r *Definition) PkField() *Field
- func (r *Definition) RealFields(fields []*Field) []*Field
- type Definitions
- func (r *Definitions) Append(md *Definition)
- func (r *Definitions) Delete(index int)
- func (r *Definitions) Head(delete bool) (md *Definition)
- func (r *Definitions) Pop() (md *Definition)
- func (r *Definitions) Push(md *Definition)
- func (r *Definitions) Reverse()
- func (r *Definitions) Top() (md *Definition)
- type EqPredicate
- type Event
- type EventHandler
- type FK
- type Field
- func (f *Field) AsValue(object interface{}) (value interface{}, err error)
- func (f *Field) DDL() string
- func (f *Field) Detail() (level int)
- func (f *Field) Encoded() (encoded bool)
- func (f *Field) Fk() (fk *FK)
- func (f *Field) Incremented() bool
- func (f *Field) Index() []string
- func (f *Field) Key() bool
- func (f *Field) MatchDetail(level int) bool
- func (f *Field) Mutable() bool
- func (f *Field) Param() string
- func (f *Field) Pk() (matched bool)
- func (f *Field) Ptr() interface{}
- func (f *Field) Pull() interface{}
- func (f *Field) Push()
- func (f *Field) Unique() []string
- func (f *Field) Validate() error
- func (f *Field) Virtual() bool
- func (f *Field) WithFields() (withFields map[string]bool)
- type FkRef
- type FkRelation
- type GtPredicate
- type Journal
- type Label
- type LabelPredicate
- type Labeled
- type Labeler
- type Labels
- type ListOptions
- type LtPredicate
- type Model
- type NeqPredicate
- type OrPredicate
- type Page
- type Pool
- type Predicate
- type Row
- type Serial
- type Session
- type SimplePredicate
- type StockEventHandler
- func (r *StockEventHandler) Created(Event)
- func (r *StockEventHandler) Deleted(Event)
- func (r *StockEventHandler) End()
- func (r *StockEventHandler) Error(error)
- func (r *StockEventHandler) Options() WatchOptions
- func (r *StockEventHandler) Parity()
- func (r *StockEventHandler) Started(uint64)
- func (r *StockEventHandler) Updated(Event)
- type Table
- func (t Table) Constraints(md *Definition, dm *DataModel) (constraints []string, err error)
- func (t Table) Count(model interface{}, predicate Predicate) (count int64, err error)
- func (t Table) DDL(model interface{}, dm *DataModel) (list []string, err error)
- func (t Table) Delete(model interface{}) (err error)
- func (t Table) EnsurePk(md *Definition)
- func (t Table) Find(model interface{}, options ListOptions) (itr fb.Iterator, err error)
- func (t Table) Get(model interface{}) (err error)
- func (t Table) IndexDDL(md *Definition) (list []string, err error)
- func (t Table) Insert(model interface{}) (err error)
- func (t Table) KeyIndexDDL(md *Definition) (list []string, err error)
- func (t Table) List(list interface{}, options ListOptions) (err error)
- func (t Table) Name(model interface{}) string
- func (t Table) Params(md *Definition) (list []interface{})
- func (t Table) TableDDL(md *Definition, dm *DataModel) (list []string, err error)
- func (t Table) Update(model interface{}) (err error)
- type TmplData
- type Tx
- func (r *Tx) Commit() (err error)
- func (r *Tx) Count(model Model, predicate Predicate) (n int64, err error)
- func (r *Tx) Delete(model Model) (err error)
- func (r *Tx) End() (err error)
- func (r *Tx) Execute(sql string) (result sql.Result, err error)
- func (r *Tx) Find(model interface{}, options ListOptions) (itr fb.Iterator, err error)
- func (r *Tx) Get(model Model) (err error)
- func (r *Tx) Insert(model Model) (err error)
- func (r *Tx) List(list interface{}, options ListOptions) (err error)
- func (r *Tx) Update(model Model) (err error)
- type Watch
- type WatchOptions
Constants ¶
const ( // SQL tag. Tag = "sql" // Max detail level. MaxDetail = 9 )
Variables ¶
var ( Started uint8 = 0x00 Parity uint8 = 0x01 Error uint8 = 0x02 End uint8 = 0x04 Created uint8 = 0x10 Updated uint8 = 0x20 Deleted uint8 = 0x40 )
Event Actions.
var ( // Must have PK. MustHavePkErr = errors.New("must have PK field") // Parameter must be pointer error. MustBePtrErr = errors.New("must be pointer") // Must be slice pointer. MustBeSlicePtrErr = errors.New("must be slice pointer") // Parameter must be struct error. MustBeObjectErr = errors.New("must be object") // Field type error. FieldTypeErr = errors.New("field type must be (int, str, bool") // PK field type error. PkTypeErr = errors.New("pk field must be (int, str)") // Generated PK error. GenPkTypeErr = errors.New("PK field must be `str` when generated") // Invalid field referenced in predicate. PredicateRefErr = errors.New("predicate referenced unknown field") // Invalid predicate for type of field. PredicateTypeErr = errors.New("predicate type not valid for field") // Invalid predicate value. PredicateValueErr = errors.New("predicate value not valid") // Invalid detail level. DetailErr = errors.New("detail level must be <= MaxDetail") )
Errors
var DefaultDetail = 0
The default (field) detail level when listing models. Applications using custom detail levels must adjust to highest level used. Example:
func init() { model.DefaultDetail = 2 }
var DeleteSQL = `
DELETE FROM {{.Table}}
WHERE
{{ .Pk.Name }} = {{ .Pk.Param }}
;
`
var DetailRegex = regexp.MustCompile(`(d)([0-9]+)`)
Regex used for detail.
var FkRegex = regexp.MustCompile(`(fk)(\()(.+)(\))`)
Regex used for `fk(table)` tags.
var GetSQL = `` /* 143-byte string literal not displayed */
var IndexDDL = `` /* 141-byte string literal not displayed */
var IndexRegex = regexp.MustCompile(`(index)(\()(.+)(\))`)
Regex used for `index(group)` tags.
var InsertSQL = `` /* 196-byte string literal not displayed */
SQL templates.
var LabelSQL = `` /* 246-byte string literal not displayed */
Label SQL.
var ListSQL = `` /* 434-byte string literal not displayed */
var NotFound = sql.ErrNoRows
Errors.
var PkRegex = regexp.MustCompile(`(pk)((\()(.+)(\)))?`)
Regex used for `pk(fields)` tags.
var TableDDL = `` /* 177-byte string literal not displayed */
DDL templates.
var UniqueRegex = regexp.MustCompile(`(unique)(\()(.+)(\))`)
Regex used for `unique(group)` tags.
var UpdateSQL = `` /* 159-byte string literal not displayed */
Functions ¶
Types ¶
type Base ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Database client.
func (*Client) Find ¶ added in v0.6.0
func (r *Client) Find(model interface{}, options ListOptions) (itr fb.Iterator, err error)
Find models.
func (*Client) List ¶
func (r *Client) List(list interface{}, options ListOptions) (err error)
List models. The `list` must be: *[]Model.
func (*Client) Open ¶
Create the database. Build the schema to support the specified models. See: Pool.Open().
type CompoundPredicate ¶
type CompoundPredicate struct { // List of predicates. Predicates []Predicate }
Compound predicate.
type DB ¶
type DB interface { // Open and build the schema. Open(bool) error // Close. Close(bool) error // Execute SQL. Execute(sql string) (sql.Result, error) // Get the specified model. Get(Model) error // List models based on the type of slice. List(interface{}, ListOptions) error // Find models. Find(interface{}, ListOptions) (fb.Iterator, error) // Count based on the specified model. Count(Model, Predicate) (int64, error) // Begin a transaction. Begin(...string) (*Tx, error) // Insert a model. Insert(Model) error // Update a model. Update(Model) error // Delete a model. Delete(Model) error // Watch a model collection. Watch(Model, EventHandler) (*Watch, error) // End a watch. EndWatch(watch *Watch) }
Database client.
type DBTX ¶
type DBTX interface { Exec(string, ...interface{}) (sql.Result, error) Query(string, ...interface{}) (*sql.Rows, error) QueryRow(string, ...interface{}) *sql.Row }
Database client interface. Support model methods taking either sql.DB or sql.Tx.
type DataModel ¶ added in v0.7.0
type DataModel struct {
// contains filtered or unexported fields
}
DataModel. Map of definitions.
func (*DataModel) Definitions ¶ added in v0.7.0
func (r *DataModel) Definitions() (list Definitions)
Definitions.
func (*DataModel) Find ¶ added in v0.7.0
func (r *DataModel) Find(kind string) (md *Definition, found bool)
Find by kind.
func (*DataModel) FindWith ¶ added in v0.7.0
func (r *DataModel) FindWith(model interface{}) (md *Definition, found bool)
Find with model.
type Definition ¶ added in v0.7.0
Model definition.
func Inspect ¶ added in v0.7.0
func Inspect(model interface{}) (md *Definition, err error)
func (*Definition) Field ¶ added in v0.7.0
func (r *Definition) Field(name string) *Field
Field by name.
func (*Definition) Fks ¶ added in v0.7.0
func (r *Definition) Fks() []*FK
Get foreign keys for the model.
func (*Definition) IsKind ¶ added in v0.7.0
func (r *Definition) IsKind(kind string) bool
Match (case-insensitive) by kind.
func (*Definition) KeyFields ¶ added in v0.7.0
func (r *Definition) KeyFields() []*Field
Get the natural key `Fields` for the model.
func (*Definition) MutableFields ¶ added in v0.7.0
func (r *Definition) MutableFields() []*Field
Get the mutable `Fields` for the model.
func (*Definition) NewModel ¶ added in v0.7.0
func (r *Definition) NewModel() (m interface{})
New model for kind.
func (*Definition) PkField ¶ added in v0.7.0
func (r *Definition) PkField() *Field
Get the PK field.
func (*Definition) RealFields ¶ added in v0.7.0
func (r *Definition) RealFields(fields []*Field) []*Field
Get the non-virtual `Fields` for the model.
type Definitions ¶ added in v0.7.0
type Definitions []*Definition
Model definitions.
func (*Definitions) Append ¶ added in v0.7.0
func (r *Definitions) Append(md *Definition)
Append model definition.
func (*Definitions) Delete ¶ added in v0.7.0
func (r *Definitions) Delete(index int)
Delete model definition.
func (*Definitions) Head ¶ added in v0.7.0
func (r *Definitions) Head(delete bool) (md *Definition)
Head (first) model definition. Returns: nil when empty.
func (*Definitions) Pop ¶ added in v0.7.0
func (r *Definitions) Pop() (md *Definition)
Pop model definition. Returns: nil when empty.
func (*Definitions) Push ¶ added in v0.7.0
func (r *Definitions) Push(md *Definition)
Push model definition.
func (*Definitions) Top ¶ added in v0.7.0
func (r *Definitions) Top() (md *Definition)
Top (last) model definition. Returns: nil when empty.
type Event ¶
type Event struct { // ID. ID uint64 // Labels. Labels []string // The event subject. Model Model // The event action (created|updated|deleted). Action uint8 // The updated model. Updated Model }
Model event.
type EventHandler ¶
type EventHandler interface { // Watch options. Options() WatchOptions // Watch has started. Started(watchID uint64) // Parity marker. // The watch has delivered the initial set // of `Created` events. Parity() // A model has been created. Created(Event) // A model has been updated. Updated(Event) // A model has been deleted. Deleted(Event) // An error has occurred delivering an event. Error(error) // An event watch has ended. End() }
Event handler.
type FK ¶
type FK struct { // FK owner. Owner *Field // Target table name. Table string // Target field name. Field string // +must option enforced by constraint. Must bool // +cascade delete option. Cascade bool }
FK constraint.
type Field ¶
type Field struct { // reflect.Type of the field. Type *reflect.StructField // reflect.Value of the field. Value *reflect.Value // Field name. Name string // SQL tag. Tag string // contains filtered or unexported fields }
Model (struct) Field
func (*Field) Detail ¶ added in v0.2.5
Detail level. Defaults:
Key fields = 0. Other = DefaultDetail
func (*Field) Fk ¶
Get whether the field is a foreign key. Format: fk(table flags..) where flags are optional. Flags:
+must = referenced model must exist. +cascade = cascade delete.
func (*Field) Incremented ¶ added in v0.4.3
Get whether field is auto-incremented.
func (*Field) MatchDetail ¶ added in v0.2.5
Match detail level.
func (*Field) Pull ¶
func (f *Field) Pull() interface{}
Pull from model. Populate the appropriate `staging` field using the model field value.
func (*Field) Push ¶
func (f *Field) Push()
Push to the model. Set the model field value using the `staging` field.
func (*Field) Virtual ¶ added in v0.2.5
Get whether field is virtual. A `virtual` field is read-only and managed internally in the DB.
func (*Field) WithFields ¶ added in v0.4.3
Fields used to generate the primary key. Map of lower-cased field names. May be empty when generation is not enabled.
type FkRef ¶ added in v0.7.0
type FkRef struct {
// contains filtered or unexported fields
}
FK reference.
type FkRelation ¶ added in v0.7.0
type FkRelation struct {
// contains filtered or unexported fields
}
FK relation.
func (*FkRelation) DDL ¶ added in v0.7.0
func (r *FkRelation) DDL(md *Definition) (ddl []string, err error)
Build constraint DDL.
func (*FkRelation) Definitions ¶ added in v0.7.0
func (r *FkRelation) Definitions() (list Definitions)
Model definitions dependency-sorted as needed to be created.
func (*FkRelation) Referencing ¶ added in v0.7.0
func (r *FkRelation) Referencing(md *Definition) (list []*FkRef)
Find model definitions that reference the specified definition.
type Journal ¶
type Journal struct {
// contains filtered or unexported fields
}
DB journal. Provides model watch events.
type Label ¶
type Label struct { PK string `sql:"pk(parent;kind;name)"` Parent string `sql:"key"` Kind string `sql:"key"` Name string `sql:"key"` Value string `sql:""` }
Label model
type LabelPredicate ¶
type LabelPredicate struct { // Labels Labels // contains filtered or unexported fields }
Label predicate.
type Labeled ¶ added in v0.4.3
type Labeled interface { // Get labels. Labels() Labels }
Labeled model.
type Labeler ¶ added in v0.1.1
type Labeler struct {
// contains filtered or unexported fields
}
Labeler.
type ListOptions ¶
type ListOptions struct { // Pagination. Page *Page // Sort by field position. Sort []int // Field detail level. // Defaults: // 0 = primary and natural fields. // 1 = other fields. Detail int // Predicate Predicate Predicate // contains filtered or unexported fields }
List options.
func (*ListOptions) Build ¶
func (l *ListOptions) Build(md *Definition) (err error)
Validate options.
func (*ListOptions) Fields ¶ added in v0.2.5
func (l *ListOptions) Fields() (filtered []*Field)
Fields filtered by detail level.
func (*ListOptions) Param ¶
func (l *ListOptions) Param(name string, value interface{}) (p string)
Get an appropriate parameter name. Builds a parameter and adds it to the options.param list.
func (*ListOptions) Params ¶
func (l *ListOptions) Params() []interface{}
Get params referenced by the predicate.
type Model ¶
type Model interface { // Get the primary key. Pk() string }
Model Each model represents a table in the DB.
type Pool ¶ added in v0.5.0
type Pool struct {
// contains filtered or unexported fields
}
Session pool.
func (*Pool) Open ¶ added in v0.5.0
Open the pool. Create sessions with DB connections. For sqlite3:
Even with journal=WAL, nWriter must be (1) to prevent SQLITE_LOCKED error.
type Predicate ¶
type Predicate interface { // Build the predicate. Build(*ListOptions) error // Get the SQL expression. Expr() string }
List predicate.
type Row ¶
type Row interface {
Scan(...interface{}) error
}
Database interface. Support model `Scan` taking either sql.Row or sql.Rows.
type Serial ¶ added in v0.3.5
type Serial struct {
// contains filtered or unexported fields
}
Serial number pool.
type Session ¶ added in v0.5.0
type Session struct {
// contains filtered or unexported fields
}
DB session. Encapsulates the sql.DB.
type SimplePredicate ¶
type SimplePredicate struct { // Field name. Field string // Field value. Value interface{} // contains filtered or unexported fields }
Simple predicate.
type StockEventHandler ¶ added in v0.3.1
type StockEventHandler struct{}
Stock event handler. Provides default event methods.
func (*StockEventHandler) Created ¶ added in v0.3.1
func (r *StockEventHandler) Created(Event)
A model has been created.
func (*StockEventHandler) Deleted ¶ added in v0.3.1
func (r *StockEventHandler) Deleted(Event)
A model has been deleted.
func (*StockEventHandler) End ¶ added in v0.3.1
func (r *StockEventHandler) End()
An event watch has ended.
func (*StockEventHandler) Error ¶ added in v0.3.1
func (r *StockEventHandler) Error(error)
An error has occurred delivering an event.
func (*StockEventHandler) Options ¶ added in v0.4.2
func (r *StockEventHandler) Options() WatchOptions
Watch options.
func (*StockEventHandler) Parity ¶ added in v0.3.1
func (r *StockEventHandler) Parity()
Watch has parity.
func (*StockEventHandler) Started ¶ added in v0.3.1
func (r *StockEventHandler) Started(uint64)
Watch has started.
func (*StockEventHandler) Updated ¶ added in v0.3.1
func (r *StockEventHandler) Updated(Event)
A model has been updated.
type Table ¶
type Table struct { // Database connection. DB DBTX }
Represents a table in the DB. Using reflect, the model is inspected to determine the table name and columns. The column definition is specified using field tags:
pk - Primary key. key - Natural key. fk:<table>(field) - Foreign key. unique(<group>) - Unique constraint collated by <group>. const - Not updated.
func (Table) Constraints ¶
func (t Table) Constraints(md *Definition, dm *DataModel) (constraints []string, err error)
Get constraint DDL.
func (Table) Count ¶
Count the models in the DB. Qualified by the model field values and list options. Else, ALL models are counted.
func (Table) EnsurePk ¶ added in v0.4.3
func (t Table) EnsurePk(md *Definition)
Ensure PK is generated as specified/needed.
func (Table) Find ¶ added in v0.6.0
func (t Table) Find(model interface{}, options ListOptions) (itr fb.Iterator, err error)
Find models in the DB. Qualified by the list options.
func (Table) Get ¶
Get the model in the DB. Expects the primary key (PK) to be set. Fetch the row and populate the fields in the model.
func (Table) IndexDDL ¶ added in v0.3.7
func (t Table) IndexDDL(md *Definition) (list []string, err error)
Build non-unique index DDL.
func (Table) KeyIndexDDL ¶ added in v0.3.7
func (t Table) KeyIndexDDL(md *Definition) (list []string, err error)
Build natural key index DDL.
func (Table) List ¶
func (t Table) List(list interface{}, options ListOptions) (err error)
List the model in the DB. Qualified by the list options.
func (Table) Params ¶
func (t Table) Params(md *Definition) (list []interface{})
Get the `Fields` referenced as param in SQL.
type TmplData ¶
type TmplData struct { // Table name. Table string // Index name. Index string // Fields. Fields []*Field // Constraint DDL. Constraints []string // Natural key fields. Keys []*Field // Primary key. Pk *Field // List options. Options *ListOptions // Count Count bool }
Template data.
type Tx ¶
type Tx struct {
// contains filtered or unexported fields
}
Database transaction.
func (*Tx) Commit ¶
Commit a transaction. Staged changes are committed in the DB. The transaction is ended and the session returned.
func (*Tx) Find ¶ added in v0.6.0
func (r *Tx) Find(model interface{}, options ListOptions) (itr fb.Iterator, err error)
List models.
func (*Tx) List ¶ added in v0.1.1
func (r *Tx) List(list interface{}, options ListOptions) (err error)
List models. The `list` must be: *[]Model.
type Watch ¶
type Watch struct { // Model to be watched. Model Model // Event handler. Handler EventHandler // contains filtered or unexported fields }
Model event watch.
type WatchOptions ¶ added in v0.4.2
type WatchOptions struct { // Initial snapshot. // List models and report as `Created` events. Snapshot bool }
Watch options.