Documentation
¶
Overview ¶
Package model allows Go structs to behave as database models.
While this package exports several types the only one you currently need to be concerned with is type Models. All of the examples in this package use a global instance of Models defined in the examples subpackage; you may refer to that global instance for an instantiation example.
Note that in the examples for this package when you see examples.Models or examples.DB_Insert() it is referring the examples subdirectory for this package and NOT the subdirectory for sqlh (i.e. both sqlh and sqlh/model have an examples subdirectory.)
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Model ¶
type Model struct {
// Table is the related database table.
Table schema.Table
// Statements are the SQL database statements.
Statements statements.Table
// V is a *set.Value of a model instance M.
V *set.Value
// VSlice is a *set.Value of a model slice []M.
VSlice *set.Value
// Mapping is the column to struct field mapping.
Mapping *set.Mapping
// BoundMapping is a cached BoundMapping of a zero value for
// the model. Gathering query arguments and scan targets will
// be faster when executing queries by performing the following:
// cp := Model.BoundMapping.Copy() // Copy the cached BoundMapping.
// cp.Rebind( modelInstance ) // Bind the copy to an instance of the model.
// cp.Fields( ... ) // Get a slice of query arguments by column name.
// cp.Assignable( ... ) // Get a slice of scan targets by column name.
BoundMapping set.BoundMapping
}
Model relates a Go type to its Table.
func (*Model) BindQuery ¶
func (me *Model) BindQuery(query *statements.Query) QueryBinding
BindQuery returns a QueryBinding that facilitates running queries against instaces of the model.
func (*Model) NewInstance ¶
func (me *Model) NewInstance() interface{}
NewInstance creates an instance of the model's zero value.
type Models ¶
type Models struct {
//
// Mapper defines how SQL column names map to fields in Go structs.
Mapper *set.Mapper
//
// Grammar defines the SQL grammar to use for SQL generation.
Grammar *grammar.Grammar
//
// Models is a map of Go types to Model instances. This member is automatically
// instantiated during calls to Register().
Models map[reflect.Type]*Model
//
// StructTag specifies the struct tag name to use when inspecting types
// during register. If not set will default to "model".
StructTag string
}
Models is a registry of Models and methods to manipulate them.
Example (Insert) ¶
package main
import (
"fmt"
"time"
"github.com/nofeaturesonlybugs/sqlh/model/examples"
)
func main() {
model := &examples.Address{
// Id, CreatedTime, ModifiedTime are not set and updated by the database.
Street: "1234 The Street",
City: "Small City",
State: "ST",
Zip: "98765",
}
// Create a mock database. Unlike a production database the mock DB tells us
// which values to expect when scanning back into models via returning.
db, returning, err := examples.DB_Insert(model)
if err != nil {
fmt.Println("err", err.Error())
return
}
// Insert our model. The values from returning (see above) are scanned into
// auto updating fields of the model (pk, created, modified).
if err := examples.Models.Insert(db, model); err != nil {
fmt.Println("err", err.Error())
return
}
// Check values from returning were scanned into the model.
if model.Id != returning[0][0].(int) {
fmt.Println("unexpected id")
}
if !model.CreatedTime.Equal(returning[0][1].(time.Time)) {
fmt.Println("unexpected created time")
}
if !model.ModifiedTime.Equal(returning[0][2].(time.Time)) {
fmt.Println("unexpected modified time")
}
fmt.Printf("Model inserted.")
}
Output: Model inserted.
Example (InsertSlice) ¶
package main
import (
"fmt"
"time"
"github.com/nofeaturesonlybugs/sqlh/model/examples"
)
func main() {
models := []*examples.Address{
// Id, CreatedTime, ModifiedTime are not set and updated by the database.
{
Street: "1234 The Street",
City: "Small City",
State: "ST",
Zip: "98765",
},
{
Street: "55 Here We Are",
City: "Big City",
State: "TS",
Zip: "56789",
},
}
// Create a mock database. Unlike a production database the mock DB tells us
// which values to expect when scanning back into models via returning.
db, returning, err := examples.DB_Insert(models)
if err != nil {
fmt.Println("err", err.Error())
return
}
// Insert our model. The values from returning (see above) are scanned into
// auto updating fields of the model (pk, created, modified).
if err := examples.Models.Insert(db, models); err != nil {
fmt.Println("err", err.Error())
return
}
// Check values from returning were scanned into the model.
for k, model := range models {
if model.Id != returning[k][0].(int) {
fmt.Println("unexpected id")
return
}
if model.CreatedTime != returning[k][1].(time.Time) {
fmt.Println("unexpected created time")
return
}
if model.ModifiedTime != returning[k][2].(time.Time) {
fmt.Println("unexpected modified time")
return
}
}
fmt.Printf("%v model(s) updated.", len(models))
}
Example (Update) ¶
package main
import (
"fmt"
"time"
"github.com/nofeaturesonlybugs/sqlh/model/examples"
)
func main() {
model := &examples.Address{
Id: 42,
CreatedTime: time.Now().Add(-1 * time.Hour),
// ModifiedTime is zero value; will be updated by database.
Street: "1234 The Street",
City: "Small City",
State: "ST",
Zip: "98765",
}
// Create a mock database. Unlike a production database the mock DB tells us
// which values to expect when scanning back into models via returning.
db, returning, err := examples.DB_Update(model)
if err != nil {
fmt.Println("err", err.Error())
return
}
// Update our model. The values from returning (see above) are scanned into
// auto updating fields of the model (modified).
if err := examples.Models.Update(db, model); err != nil {
fmt.Println("err", err.Error())
return
}
// Check values from returning were scanned into the model.
if !model.ModifiedTime.Equal(returning[0][0].(time.Time)) {
fmt.Println("unexpected modified time")
}
fmt.Printf("Model updated.")
}
Output: Model updated.
Example (UpdateSlice) ¶
package main
import (
"fmt"
"time"
"github.com/nofeaturesonlybugs/sqlh/model/examples"
)
func main() {
models := []*examples.Address{
// ModifiedTime is not set and updated by the database.
{
Id: 42,
CreatedTime: time.Now().Add(-2 * time.Hour),
Street: "1234 The Street",
City: "Small City",
State: "ST",
Zip: "98765",
},
{
Id: 62,
CreatedTime: time.Now().Add(-1 * time.Hour),
Street: "55 Here We Are",
City: "Big City",
State: "TS",
Zip: "56789",
},
}
// Create a mock database. Unlike a production database the mock DB tells us
// which values to expect when scanning back into models via returning.
db, returning, err := examples.DB_Update(models)
if err != nil {
fmt.Println("err", err.Error())
return
}
// Update our models. The values from returning (see above) are scanned into
// auto updating fields of the model (modified).
if err := examples.Models.Update(db, models); err != nil {
fmt.Println("err", err.Error())
return
}
// Check values from returning were scanned into the model.
for k, model := range models {
if model.ModifiedTime != returning[k][0].(time.Time) {
fmt.Println("unexpected modified time")
return
}
}
fmt.Printf("%v model(s) updated.", len(models))
}
Output: 2 model(s) updated.
func (*Models) Register ¶
func (me *Models) Register(value interface{}, opts ...interface{})
Register adds a Go type to the Models instance. As part of initialization your application should register all types T that need to interact with the database.
Register is not goroutine safe; implement locking in the application level if required.
type QueryBinding ¶
type QueryBinding interface {
// Query accepts either a single model M or a slice of models []M. It then
// runs and returns the result of QueryOne or QuerySlice.
Query(sqlh.IQueries, interface{}) error
// QueryOne runs the query against a single instance of the model.
QueryOne(sqlh.IQueries, interface{}) error
// QuerySlice runs the query against a slice of model instances.
QuerySlice(sqlh.IQueries, interface{}) error
}
QueryBinding binds a model with a query to facilitate running the query against instances of types described by the model.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package examples provides types and functions to facilitate the examples and test code in the model package.
|
Package examples provides types and functions to facilitate the examples and test code in the model package. |
|
Package statements builds uses a grammar to build SQL statements scoped to entities within the database.
|
Package statements builds uses a grammar to build SQL statements scoped to entities within the database. |