model

package
v0.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 1, 2020 License: Apache-2.0 Imports: 17 Imported by: 13

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:"const"`
    The field is immutable and not included on update.

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

View Source
const (
	Pragma = "PRAGMA foreign_keys = ON"
)
View Source
const (
	Tag = "sql"
)

Variables

View Source
var (
	Created int8 = 0x01
	Updated int8 = 0x02
	Deleted int8 = 0x04
)

Event Actions.

View Source
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

View Source
var DeleteSQL = `
DELETE FROM {{.Table}}
WHERE
{{ .Pk.Name }} = {{ .Pk.Param }}
;
`
View Source
var FkRegex = regexp.MustCompile(`(fk):(.+)(\()(.+)(\))`)

Regex used for `fk:<table>(field)` tags.

View Source
var GetSQL = `` /* 143-byte string literal not displayed */
View Source
var IndexDDL = `` /* 141-byte string literal not displayed */
View Source
var InsertSQL = `` /* 196-byte string literal not displayed */

SQL templates.

View Source
var LabelSQL = `` /* 246-byte string literal not displayed */

Label SQL.

View Source
var ListSQL = `` /* 426-byte string literal not displayed */
View Source
var NotFound = sql.ErrNoRows

Errors.

View Source
var TableDDL = `` /* 177-byte string literal not displayed */

DDL templates.

View Source
var UniqueRegex = regexp.MustCompile(`(unique)(\()(.+)(\))`)

Regex used for `unique(group)` tags.

View Source
var UpdateSQL = `` /* 159-byte string literal not displayed */

Functions

This section is empty.

Types

type AndPredicate

type AndPredicate struct {
	CompoundPredicate
}

And predicate.

func And

func And(predicates ...Predicate) *AndPredicate

AND predicate.

func (*AndPredicate) Build

func (p *AndPredicate) Build(options *ListOptions) error

Build.

func (*AndPredicate) Expr

func (p *AndPredicate) Expr() string

Render the expression.

type Base

type Base struct {
	// Primary key (digest).
	PK string `sql:"pk"`
	// The raw json-encoded k8s resource.
	Object string `sql:""`
}

func (*Base) Pk

func (m *Base) Pk() string

Get the primary key.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Database client.

func (*Client) Begin

func (r *Client) Begin() (*Tx, error)

Begin a transaction. Example:

tx, _ := client.Begin()
defer tx.End()
client.Insert(model)
client.Insert(model)
tx.Commit()

func (*Client) Close

func (r *Client) Close(purge bool) error

Close the database. Optionally purge (delete) the DB.

func (*Client) Count

func (r *Client) Count(model Model, predicate Predicate) (int64, error)

Count models.

func (*Client) Delete

func (r *Client) Delete(model Model) error

Delete the model.

func (*Client) EndWatch added in v0.1.1

func (r *Client) EndWatch(watch *Watch)

End watch.

func (*Client) Get

func (r *Client) Get(model Model) error

Get the model.

func (*Client) Insert

func (r *Client) Insert(model Model) error

Insert the model.

func (*Client) Journal

func (r *Client) Journal() *Journal

The associated journal.

func (*Client) List

func (r *Client) List(list interface{}, options ListOptions) error

List models. The `list` must be: *[]Model.

func (*Client) Open

func (r *Client) Open(purge bool) error

Create the database. Build the schema to support the specified models. Optionally `purge` (delete) the DB first.

func (*Client) Update

func (r *Client) Update(model Model) error

Update the model.

func (*Client) Watch

func (r *Client) Watch(model Model, handler EventHandler) (*Watch, error)

Watch model events.

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
	// Get the specified model.
	Get(Model) error
	// List models based on the type of slice.
	List(interface{}, ListOptions) 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)
	// The journal
	Journal() *Journal
}

Database client.

func New

func New(path string, models ...interface{}) DB

New database.

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 EqPredicate

type EqPredicate struct {
	SimplePredicate
}

Equals (=) predicate.

func Eq

func Eq(field string, value interface{}) *EqPredicate

New Eq (=) predicate.

func (*EqPredicate) Build

func (p *EqPredicate) Build(options *ListOptions) error

Build.

func (*EqPredicate) Expr

func (p *EqPredicate) Expr() string

Render the expression.

type Event

type Event struct {
	// The event subject.
	Model Model
	// The event action (created|updated|deleted).
	Action int8
	// The updated model.
	Updated Model
}

Model event.

type EventHandler

type EventHandler interface {
	// 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 {
	// Table name.
	Table string
	// Field name.
	Field string
}

FK constraint.

func (*FK) DDL

func (f *FK) DDL(field *Field) string

Get DDL.

type Field

type Field struct {
	// reflect.Value of the field.
	Value *reflect.Value
	// Tags.
	Tag string
	// Field name.
	Name string
	// contains filtered or unexported fields
}

Model (struct) Field 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:"const"`
    The field is immutable and not included on update.

func (*Field) AsValue

func (f *Field) AsValue(object interface{}) (value interface{}, err error)

Convert the specified `object` to a value (type) appropriate for the field.

func (*Field) DDL

func (f *Field) DDL() string

Column DDL.

func (*Field) Fk

func (f *Field) Fk() *FK

Get whether the field is a foreign key.

func (*Field) Key

func (f *Field) Key() bool

Get whether field is a natural key.

func (*Field) Mutable

func (f *Field) Mutable() bool

Get whether field is mutable. Only mutable fields will be updated.

func (*Field) Param

func (f *Field) Param() string

Get as SQL param.

func (*Field) Pk

func (f *Field) Pk() bool

Get whether field is the primary key.

func (*Field) Ptr

func (f *Field) Ptr() interface{}

Pointer used for Scan().

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) Unique

func (f *Field) Unique() []string

Get whether the field is unique.

func (*Field) Validate

func (f *Field) Validate() error

Validate.

type GtPredicate

type GtPredicate struct {
	SimplePredicate
}

Greater than (>) predicate.

func Gt

func Gt(field string, value interface{}) *GtPredicate

New Gt (>) predicate.

func (*GtPredicate) Build

func (p *GtPredicate) Build(options *ListOptions) error

Build.

func (*GtPredicate) Expr

func (p *GtPredicate) Expr() string

Render the expression.

type Journal

type Journal struct {
	// contains filtered or unexported fields
}

Event manager.

func (*Journal) Commit

func (r *Journal) Commit()

Commit staged events and notify handlers.

func (*Journal) Created

func (r *Journal) Created(model Model)

A model has been created. Queue an event.

func (*Journal) Deleted

func (r *Journal) Deleted(model Model)

A model has been deleted. Queue an event.

func (*Journal) Disable

func (r *Journal) Disable()

Disable the journal. End all watches and discard staged events.

func (*Journal) Enable

func (r *Journal) Enable()

Enable the journal.

func (*Journal) Enabled

func (r *Journal) Enabled() bool

The journal is enabled. Must be enabled for watch models.

func (*Journal) End

func (r *Journal) End(watch *Watch)

End watch.

func (*Journal) Unstage

func (r *Journal) Unstage()

Discard staged events.

func (*Journal) Updated

func (r *Journal) Updated(model Model, updated Model)

A model has been updated. Queue an event.

func (*Journal) Watch

func (r *Journal) Watch(model Model, handler EventHandler) (*Watch, error)

Watch a `watch` of the specified model. The returned watch has not been started. See: Watch.Start().

type Label

type Label struct {
	PK     string `sql:"pk"`
	Parent string `sql:"key"`
	Kind   string `sql:"key"`
	Name   string `sql:"key"`
	Value  string `sql:""`
}

Label model

func (*Label) Equals

func (l *Label) Equals(other Model) bool

func (*Label) Labels

func (l *Label) Labels() Labels

func (*Label) Pk

func (l *Label) Pk() string

func (*Label) String

func (l *Label) String() string

type LabelPredicate

type LabelPredicate struct {
	// Labels
	Labels
	// contains filtered or unexported fields
}

Label predicate.

func Match

func Match(labels Labels) *LabelPredicate

Label predicate.

func (*LabelPredicate) Build

func (p *LabelPredicate) Build(options *ListOptions) error

Build.

func (*LabelPredicate) Expr

func (p *LabelPredicate) Expr() string

Render the expression.

func (*LabelPredicate) Kind

func (p *LabelPredicate) Kind() string

Label (parent) kind.

func (*LabelPredicate) Len

func (p *LabelPredicate) Len() int

Get the number of labels.

func (*LabelPredicate) List

func (p *LabelPredicate) List() []Label

List of labels.

func (*LabelPredicate) Pk

func (p *LabelPredicate) Pk() *Field

PK field name.

type Labeler added in v0.1.1

type Labeler struct {
}

Labeler.

func (*Labeler) Delete added in v0.1.1

func (r *Labeler) Delete(table Table, model Model) error

Delete labels for a model in the DB.

func (*Labeler) Insert added in v0.1.1

func (r *Labeler) Insert(table Table, model Model) error

Insert labels for the model into the DB.

func (*Labeler) Replace added in v0.1.1

func (r *Labeler) Replace(table Table, model Model) error

Replace labels.

type Labels

type Labels map[string]string

Labels collection.

type ListOptions

type ListOptions struct {
	// Pagination.
	Page *Page
	// Sort by field position.
	Sort []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) 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 LtPredicate

type LtPredicate struct {
	SimplePredicate
}

Less than (<) predicate.

func Lt

func Lt(field string, value interface{}) *LtPredicate

New Lt (<) predicate.

func (*LtPredicate) Build

func (p *LtPredicate) Build(options *ListOptions) error

Build.

func (*LtPredicate) Expr

func (p *LtPredicate) Expr() string

Render the expression.

type Model

type Model interface {
	// Get the primary key.
	Pk() string
	// Get description of the model.
	String() string
	// Equal comparison.
	Equals(other Model) bool
	// Get labels.
	// Optional and may return nil.
	Labels() Labels
}

Model Each model represents a table in the DB.

type NeqPredicate

type NeqPredicate struct {
	SimplePredicate
}

NotEqual (!=) predicate.

func Neq

func Neq(field string, value interface{}) *NeqPredicate

New Neq (!=) predicate.

func (*NeqPredicate) Build

func (p *NeqPredicate) Build(options *ListOptions) error

Build.

func (*NeqPredicate) Expr

func (p *NeqPredicate) Expr() string

Render the expression.

type OrPredicate

type OrPredicate struct {
	CompoundPredicate
}

OR predicate.

func Or

func Or(predicates ...Predicate) *OrPredicate

OR predicate.

func (*OrPredicate) Build

func (p *OrPredicate) Build(options *ListOptions) error

Build.

func (*OrPredicate) Expr

func (p *OrPredicate) Expr() string

Render the expression.

type Page

type Page struct {
	// The page offset.
	Offset int
	// The number of items per/page.
	Limit int
}

Page. Support pagination.

func (*Page) Slice

func (p *Page) Slice(collection interface{})

Slice the collection according to the page definition. The `collection` must be a pointer to a `Slice` which is modified as needed.

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 SimplePredicate

type SimplePredicate struct {
	// Field name.
	Field string
	// Field value.
	Value interface{}
	// contains filtered or unexported fields
}

Simple predicate.

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(fields []*Field) []string

Get constraint DDL.

func (Table) Count

func (t Table) Count(model interface{}, predicate Predicate) (int64, error)

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) DDL

func (t Table) DDL(model interface{}) ([]string, error)

Get table and index create DDL.

func (Table) Delete

func (t Table) Delete(model interface{}) error

Delete the model in the DB. Expects the primary key (PK) or natural keys to be set.

func (Table) Fields

func (t Table) Fields(model interface{}) ([]*Field, error)

Get the `Fields` for the model.

func (Table) Get

func (t Table) Get(model interface{}) error

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) Insert

func (t Table) Insert(model interface{}) error

Insert the model in the DB. Expects the primary key (PK) to be set.

func (Table) KeyFields

func (t Table) KeyFields(fields []*Field) []*Field

Get the natural key `Fields` for the model.

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

func (t Table) MutableFields(fields []*Field) []*Field

Get the mutable `Fields` for the model.

func (Table) Name

func (t Table) Name(model interface{}) string

Get the table name for the model.

func (Table) Params

func (t Table) Params(fields []*Field) []interface{}

Get the `Fields` referenced as param in SQL.

func (Table) PkField

func (t Table) PkField(fields []*Field) *Field

Get the PK field.

func (Table) SetPk

func (t Table) SetPk(fields []*Field) error

Set PK Generated when not already set as sha1 of the (const) natural keys.

func (Table) Update

func (t Table) Update(model interface{}) error

Update the model in the DB. Expects the primary key (PK) or natural keys to be set.

func (Table) Validate

func (t Table) Validate(fields []*Field) error

Validate the model.

type TmplData

type TmplData struct {
	// Table name.
	Table 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.

func (TmplData) Page

func (t TmplData) Page() *Page

Pagination.

func (TmplData) Predicate

func (t TmplData) Predicate() Predicate

Predicate

func (TmplData) Sort

func (t TmplData) Sort() []int

Sort criteria

type Tx

type Tx struct {
	// contains filtered or unexported fields
}

Database transaction.

func (*Tx) Commit

func (r *Tx) Commit() (err error)

Commit a transaction. Staged changes are committed in the DB. This will end the transaction.

func (*Tx) Count added in v0.1.1

func (r *Tx) Count(model Model, predicate Predicate) (int64, error)

Count models.

func (*Tx) Delete added in v0.1.1

func (r *Tx) Delete(model Model) error

Delete the model.

func (*Tx) End

func (r *Tx) End() (err error)

End a transaction. Staged changes are discarded. See: Commit().

func (*Tx) Get added in v0.1.1

func (r *Tx) Get(model Model) error

Get the model.

func (*Tx) Insert added in v0.1.1

func (r *Tx) Insert(model Model) error

Insert the model.

func (*Tx) List added in v0.1.1

func (r *Tx) List(list interface{}, options ListOptions) error

List models. The `list` must be: *[]Model.

func (*Tx) Update added in v0.1.1

func (r *Tx) Update(model Model) error

Update the model.

type Watch

type Watch struct {
	// Model to be watched.
	Model Model
	// Event handler.
	Handler EventHandler
	// contains filtered or unexported fields
}

Model event watch.

func (*Watch) End

func (w *Watch) End()

End the watch.

func (*Watch) Match

func (w *Watch) Match(model Model) bool

Match by model `kind`.

func (*Watch) Start

func (w *Watch) Start()

Run the watch. Forward events to the `handler`.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL