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:"pk"` The primary key. `sql:"key"` The field is part of the natural key. `sql:"fk:T(F)"` Foreign key `T` = model type, `F` = model field. `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 (0-9).
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 `sql:""` } func (p *Person) Pk() string {...} func (p *Person) Equals(other Model) bool {...} func (p *Person) Labels() {...} func (p *Person) String() string {...}
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() (*Tx, error)
- func (r *Client) Close(purge bool) error
- func (r *Client) Count(model Model, predicate Predicate) (n int64, err error)
- func (r *Client) Delete(model Model) error
- func (r *Client) EndWatch(watch *Watch)
- func (r *Client) Execute(sql string) (sql.Result, error)
- func (r *Client) Get(model Model) (err error)
- func (r *Client) Insert(model Model) error
- func (r *Client) Iter(model interface{}, options ListOptions) (itr fb.Iterator, err error)
- func (r *Client) List(list interface{}, options ListOptions) (err error)
- func (r *Client) Open(purge bool) (err error)
- func (r *Client) Update(model Model) error
- func (r *Client) Watch(model Model, handler EventHandler) (w *Watch, err error)
- type CompoundPredicate
- type DB
- type DBTX
- 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
- 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 GtPredicate
- type Journal
- func (r *Journal) Close() (err error)
- func (r *Journal) Committed()
- func (r *Journal) Created(model Model, committed bool) (err error)
- func (r *Journal) Deleted(model Model, committed bool) (err error)
- func (r *Journal) End(watch *Watch)
- func (r *Journal) Reset()
- func (r *Journal) Updated(model Model, updated Model, committed bool) (err error)
- func (r *Journal) Watch(model Model, handler EventHandler) (*Watch, error)
- type Label
- type LabelPredicate
- type Labeled
- type Labeler
- type Labels
- type ListOptions
- type LtPredicate
- type Model
- type NeqPredicate
- type OrPredicate
- type Page
- type Predicate
- type Row
- type Serial
- 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(fields []*Field) []string
- func (t Table) Count(model interface{}, predicate Predicate) (int64, error)
- func (t Table) DDL(model interface{}) (list []string, err error)
- func (t Table) Delete(model interface{}) error
- func (t Table) EnsurePk(fields []*Field)
- func (t Table) Fields(model interface{}) ([]*Field, error)
- func (t Table) Get(model interface{}) error
- func (t Table) IndexDDL(model interface{}, fields []*Field) (list []string, err error)
- func (t Table) Insert(model interface{}) error
- func (t Table) Iter(model interface{}, options ListOptions) (itr fb.Iterator, err error)
- func (t Table) KeyFields(fields []*Field) []*Field
- func (t Table) KeyIndexDDL(model interface{}, fields []*Field) (list []string, err error)
- func (t Table) List(list interface{}, options ListOptions) error
- func (t Table) MutableFields(fields []*Field) []*Field
- func (t Table) Name(model interface{}) string
- func (t Table) Params(fields []*Field) []interface{}
- func (t Table) PkField(fields []*Field) *Field
- func (t Table) RealFields(fields []*Field) []*Field
- func (t Table) TableDDL(model interface{}, fields []*Field) (list []string, err error)
- func (t Table) Update(model interface{}) error
- func (t Table) Validate(fields []*Field) 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) error
- func (r *Tx) End() (err error)
- func (r *Tx) Get(model Model) (err error)
- func (r *Tx) Insert(model Model) error
- func (r *Tx) Iter(model interface{}, options ListOptions) (itr fb.Iterator, err error)
- func (r *Tx) List(list interface{}, options ListOptions) (err error)
- func (r *Tx) Update(model Model) error
- type Watch
- type WatchOptions
Constants ¶
const ( // SQL tag. Tag = "sql" // Max detail level. MaxDetail = 10 )
const (
Pragma = "PRAGMA foreign_keys = ON"
)
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") )
Errors
var DeleteSQL = `
DELETE FROM {{.Table}}
WHERE
{{ .Pk.Name }} = {{ .Pk.Param }}
;
`
var FkRegex = regexp.MustCompile(`(fk):(.+)(\()(.+)(\))`)
Regex used for `fk:<table>(field)` 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) Begin ¶
Begin a transaction. Example:
tx, _ := client.Begin() defer tx.End() client.Insert(model) client.Insert(model) tx.Commit()
func (*Client) Iter ¶ added in v0.3.4
func (r *Client) Iter(model interface{}, options ListOptions) (itr fb.Iterator, err error)
List models.
func (*Client) List ¶
func (r *Client) List(list interface{}, options ListOptions) (err error)
List models. The `list` must be: *[]Model.
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 // List models. Iter(interface{}, ListOptions) (fb.Iterator, error) // Count based on the specified model. Count(Model, Predicate) (int64, error) // Begin a transaction. Begin() (*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 Event ¶
type Event struct { // ID. ID uint64 // 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 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 Tags:
`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:T(F)"` Foreign key `T` = model type, `F` = model field. `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 (0-9). `sql:incremented` The field is auto-incremented.
func (*Field) Detail ¶ added in v0.2.5
Detail level. Defaults:
0 = primary and natural fields. 1 = other fields.
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 Journal ¶
type Journal struct {
// contains filtered or unexported fields
}
DB journal. Provides model watch events.
func (*Journal) Committed ¶ added in v0.3.4
func (r *Journal) Committed()
Transaction committed. Recorded (staged) events are forwarded to watches.
func (*Journal) Reset ¶ added in v0.3.4
func (r *Journal) Reset()
Reset the journal. Discard recorded (staged) 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(table string, fields []*Field) 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{}) 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 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 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) Count ¶
Count the models in the DB. Qualified by the model field values and list options. Expects natural keys to be set. Else, ALL models counted.
func (Table) Delete ¶
Delete the model in the DB. Expects the primary key (PK) or natural keys to be set.
func (Table) Get ¶
Get the model in the DB. Expects the primary key (PK) or natural keys to be set. Fetch the row and populate the fields in the model.
func (Table) Iter ¶ added in v0.3.4
func (t Table) Iter(model interface{}, options ListOptions) (itr fb.Iterator, err error)
List the model in the DB. Qualified by the list options.
func (Table) KeyIndexDDL ¶ added in v0.3.7
Build natural key index DDL.
func (Table) List ¶
func (t Table) List(list interface{}, options ListOptions) error
List the model in the DB. Qualified by the list options.
func (Table) MutableFields ¶
Get the mutable `Fields` for the model.
func (Table) RealFields ¶ added in v0.2.5
Get the non-virtual `Fields` for the model.
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. This will end the transaction.
func (*Tx) Iter ¶ added in v0.3.6
func (r *Tx) Iter(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.