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.Connect() 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 ¶
- Variables
- type Model
- type Models
- func (me *Models) Insert(Q sqlh.IQueries, value interface{}) error
- func (me *Models) Lookup(value interface{}) (m *Model, err error)
- func (me *Models) Register(value interface{}, opts ...interface{})
- func (me *Models) Save(Q sqlh.IQueries, value interface{}) error
- func (me *Models) Update(Q sqlh.IQueries, value interface{}) error
- func (me *Models) Upsert(Q sqlh.IQueries, value interface{}) error
- type QueryBinding
- type SaveMode
- type TableName
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrUnsupported error = errors.New("unsupported")
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 // SaveMode is set during model registration and inspected during Models.Save // to determine which of Insert, Update, or Upsert operations to use. // // SaveMode=InsertOrUpdate means InsertUpdatePaths is a non-empty slice of // key field traversal information. The key fields are examined and if // any are non-zero values then Update will be used otherwise Insert. SaveMode SaveMode InsertUpdatePaths []path.ReflectPath // Mapping is the column to struct field mapping. Mapping set.Mapping }
Model relates a Go type to its Table.
func (*Model) BindQuery ¶
func (me *Model) BindQuery(mapper *set.Mapper, query *statements.Query) QueryBinding
BindQuery returns a QueryBinding that facilitates running queries against instaces of the model.
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 (Relationship) ¶
package main import ( "fmt" "github.com/nofeaturesonlybugs/sqlh/model/examples" ) func main() { // This single example shows the common cases of INSERT|UPDATE|UPSERT as distinct code blocks. // examples.Relationship has a composite key and no auto-updating fields. { // Demonstrates INSERT of a single model. db, err := examples.Connect(examples.ExRelationshipInsert) if err != nil { fmt.Println(err.Error()) return } // A "value" model. value := examples.Relationship{ LeftId: 1, RightId: 10, Toggle: false, } // Pass "value" model by address. if err = examples.Models.Insert(db, &value); err != nil { fmt.Println(err) return } fmt.Println("Insert success.") } { // Demonstrates UPDATE of a single model. db, err := examples.Connect(examples.ExRelationshipUpdate) if err != nil { fmt.Println(err.Error()) return } // A pointer model. relate := &examples.Relationship{ LeftId: 1, RightId: 10, Toggle: true, } // Pass pointer model directly. if err = examples.Models.Update(db, relate); err != nil { fmt.Println(err) return } fmt.Println("Update success.") } { // Demonstrates UPSERT of a single model. db, err := examples.Connect(examples.ExRelationshipUpsert) if err != nil { fmt.Println(err.Error()) return } // relate := &examples.Relationship{ LeftId: 1, RightId: 10, Toggle: false, } if err = examples.Models.Upsert(db, relate); err != nil { fmt.Println(err) return } fmt.Println("Upsert success.") } }
Output: Insert success. Update success. Upsert success.
Example (RelationshipSlice) ¶
package main import ( "fmt" "github.com/nofeaturesonlybugs/sqlh/model/examples" ) func main() { // This single example shows the common cases of INSERT|UPDATE|UPSERT as distinct code blocks. // examples.Relationship has a composite key and no auto-updating fields. { // Demonstrates INSERT of a slice of models. db, err := examples.Connect(examples.ExRelationshipInsertSlice) if err != nil { fmt.Println(err.Error()) return } // Slice of "values". relate := []examples.Relationship{ { LeftId: 1, RightId: 10, Toggle: false, }, { LeftId: 2, RightId: 20, Toggle: true, }, { LeftId: 3, RightId: 30, Toggle: false, }, } // Pass slice of "values" directly. if err = examples.Models.Insert(db, relate); err != nil { fmt.Println(err) return } fmt.Println("Insert success.") } { // Demonstrates UPDATE of a slice of models. db, err := examples.Connect(examples.ExRelationshipUpdateSlice) if err != nil { fmt.Println(err.Error()) return } // Slice of pointers. relate := []*examples.Relationship{ { LeftId: 1, RightId: 10, Toggle: true, }, { LeftId: 2, RightId: 20, Toggle: false, }, { LeftId: 3, RightId: 30, Toggle: true, }, } // Pass slice of pointers directly. if err = examples.Models.Update(db, relate); err != nil { fmt.Println(err) return } fmt.Println("Update success.") } { // Demonstrates UPSERT of a slice of models. db, err := examples.Connect(examples.ExRelationshipUpsertSlice) if err != nil { fmt.Println(err.Error()) return } // relate := []*examples.Relationship{ { LeftId: 1, RightId: 10, Toggle: false, }, { LeftId: 2, RightId: 20, Toggle: true, }, { LeftId: 3, RightId: 30, Toggle: false, }, } if err = examples.Models.Upsert(db, relate); err != nil { fmt.Println(err) return } fmt.Println("Upsert success.") } }
Output: Insert success. Update success. Upsert success.
func (*Models) Insert ¶
Insert attempts to persist values via INSERTs.
Example ¶
package main import ( "fmt" "time" "github.com/nofeaturesonlybugs/sqlh/model/examples" ) func main() { var zero time.Time // // Create a mock database. db, err := examples.Connect(examples.ExAddressInsert) if err != nil { fmt.Println("err", err.Error()) return } WasInserted := func(id int, created time.Time, modified time.Time) error { if id == 0 || zero.Equal(created) || zero.Equal(modified) { return fmt.Errorf("Record not inserted.") } return nil } // A "value" record. byVal := examples.Address{ // Id, CreatedTime, ModifiedTime are updated by the database. Street: "1234 The Street", City: "Small City", State: "ST", Zip: "98765", } // A pointer record. byPtr := &examples.Address{ // Id, CreatedTime, ModifiedTime are updated by the database. Street: "4321 The Street", City: "Big City", State: "TS", Zip: "56789", } // Pass the address of the "value" record. if err := examples.Models.Insert(db, &byVal); err != nil { fmt.Println("err", err.Error()) return } if err := WasInserted(byVal.Id, byVal.CreatedTime, byVal.ModifiedTime); err != nil { fmt.Println("err", err.Error()) return } // The pointer record can be passed directly. if err := examples.Models.Insert(db, byPtr); err != nil { fmt.Println("err", err.Error()) return } if err := WasInserted(byPtr.Id, byPtr.CreatedTime, byPtr.ModifiedTime); err != nil { fmt.Println("err", err.Error()) return } fmt.Println("Models inserted.") }
Output: Models inserted.
Example (Slice) ¶
package main import ( "fmt" "time" "github.com/nofeaturesonlybugs/sqlh/model/examples" ) func main() { var zero time.Time // // Create a mock database. db, err := examples.Connect(examples.ExAddressInsertSlice) if err != nil { fmt.Println("err", err.Error()) return } WasInserted := func(id int, created time.Time, modified time.Time) error { if id == 0 || zero.Equal(created) || zero.Equal(modified) { return fmt.Errorf("Record not inserted.") } return nil } // A slice of values. values := []examples.Address{ // Id, CreatedTime, ModifiedTime are 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", }, } // A slice of pointers. pointers := []*examples.Address{ // Id, CreatedTime, ModifiedTime are 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", }, } // Slices of values can be passed directly. if err := examples.Models.Insert(db, values); err != nil { fmt.Println("err", err.Error()) return } for _, model := range values { if err := WasInserted(model.Id, model.CreatedTime, model.ModifiedTime); err != nil { fmt.Println("err", err.Error()) return } } // Slices of pointers can be passed directly. if err := examples.Models.Insert(db, pointers); err != nil { fmt.Println("err", err.Error()) return } for _, model := range pointers { if err := WasInserted(model.Id, model.CreatedTime, model.ModifiedTime); err != nil { fmt.Println("err", err.Error()) return } } fmt.Println("Models inserted.") }
Output: Models inserted.
func (*Models) Register ¶
func (me *Models) Register(value interface{}, opts ...interface{})
Register adds a Go type to the Models instance.
Register is not goroutine safe; implement locking in the store or application level if required.
When Register is called with a type T the following registrations are made:
T, *T, []T, & []*T
As a convenience register can be called with a reflect.Type as the value.
Example ¶
package main import ( "fmt" "time" "github.com/nofeaturesonlybugs/set" "github.com/nofeaturesonlybugs/sqlh/grammar" "github.com/nofeaturesonlybugs/sqlh/model" ) func main() { // This example demonstrates model registration. var Models *model.Models = &model.Models{ // Mapper and its fields control how Go structs are traversed and mapped to // database column names. Mapper: &set.Mapper{ Join: "_", Tags: []string{"db", "json"}, }, Grammar: grammar.Postgres, // StructTag defines the tag name to use when inspecting models. // StructTag: "", // Blank defaults to "model" } // // Simple model examples // // tablename=strings // strings.pk ↣ auto incrementing key // strings.value type StringModel struct { // This field specifies the table name in the database. // json:"-" tells encoding/json to ignore this field when marshalling // model:"strings" means the table name is "strings" in the database. model.TableName `json:"-" model:"strings"` // An auto incrementing primary key field. // // The mapper is configured to use `db` tag before `json` tag; // therefore this maps to strings.pk in the database but json // marshals as id // // `json:"id" db:"pk" model:"key,auto"` // ^-- auto incrementing // ^-- field is the key or part of composite key // ^-- maps to strings.pk column // ^-- json marshals to id Id int `json:"id" db:"pk" model:"key,auto"` // json marshals as value // maps to database column strings.value Value string `json:"value"` } // tablename=numbers // numbers.pk ↣ auto incrementing key // numbers.value type NumberModel struct { // This model does not include the model.TableName embed; the table name // must be specified during registration (see below). // model.TableName `json:"-" model:"numbers"` Id int `json:"id" db:"pk" model:"key,auto"` Value int `json:"value"` } // tablename=companies // companies.pk ↣ auto incrementing key // companies.created ↣ updates on INSERT // companies.modified ↣ updates on INSERT and UPDATE // companies.name type CompanyModel struct { Id int `json:"id" db:"pk" model:"key,auto"` // Models can have fields that update during INSERT or UPDATE statements. // `json:"created" model:"inserted"` // ^-- this column updates on insert // `json:"modified" model:"inserted,updated"` // ^-- this column updates on insert and updates CreatedTime time.Time `json:"created" model:"inserted"` ModifiedTime time.Time `json:"modified" model:"inserted,updated"` Name int `json:"name"` } // // Model registration // + Models that embed model.TableName do not need to specify the tablename during registration. Models.Register(StringModel{}) Models.Register(NumberModel{}, model.TableName("numbers")) Models.Register(CompanyModel{}, model.TableName("companies")) fmt.Println("all done") }
Output: all done
func (*Models) Save ¶ added in v0.5.0
Save inspects the incoming model and delegates to Insert, Update, or Upsert method according to the model's SaveMode value, which is determined during registration.
Models with at least one key field defined as "key" (i.e. not "key,auto") use Upsert.
Models with zero "key" and "key,auto" fields use Insert.
Otherwise the model has only "key,auto" fields and will use Update if any such field is a non-zero value and Insert otherwise.
If value is a slice []M then the first element is inspected to determine which of Insert, Update, or Upsert is applied to the entire slice.
Example ¶
package main import ( "fmt" "time" "github.com/nofeaturesonlybugs/sqlh/model/examples" ) func main() { // This example demonstrates using Models.Save when the models have only "key,auto" fields. // This means when models are first created and passed to Save an INSERT is performed. // Subsequent calls to Save with the model instances results in UPDATE queries. // Similar to other examples this example uses a "value" model and a pointer model. Note // the "value" model needs to be passed by address. var zero time.Time // // Create a mock database. db, err := examples.Connect(examples.ExAddressSave) if err != nil { fmt.Println("err", err.Error()) return } WasInserted := func(id int, created time.Time, modified time.Time) error { if id == 0 || zero.Equal(created) || !created.Equal(modified) { return fmt.Errorf("Record not inserted.") } return nil } WasUpdated := func(created time.Time, modified time.Time) error { if created.Equal(modified) { return fmt.Errorf("Record not updated.") } return nil } // A "value" instance. byVal := examples.Address{ Street: "1234 The Street", City: "Small City", State: "ST", Zip: "98765", } // A pointer instance. byPtr := &examples.Address{ Street: "55 Here We Are", City: "Big City", State: "TS", Zip: "56789", } // // Save the models; since these models only have "key,auto" fields they will first INSERT. if err := examples.Models.Save(db, &byVal); err != nil { fmt.Println("err", err.Error()) return } if err := WasInserted(byVal.Id, byVal.CreatedTime, byVal.ModifiedTime); err != nil { fmt.Println("err", err.Error()) return } if err := examples.Models.Save(db, byPtr); err != nil { fmt.Println("err", err.Error()) return } if err := WasInserted(byPtr.Id, byPtr.CreatedTime, byPtr.ModifiedTime); err != nil { fmt.Println("err", err.Error()) return } // Edit the model fields. byVal.Street = "1 New Street" byVal.Zip = "99111" byPtr.Street = "2 New Street" byPtr.Zip = "99222" // Save the models; since the key fields are no longer zero values they will UPDATE. if err := examples.Models.Save(db, &byVal); err != nil { fmt.Println("err", err.Error()) return } if err := WasUpdated(byVal.CreatedTime, byVal.ModifiedTime); err != nil { fmt.Println("err", err.Error()) return } if err := examples.Models.Save(db, byPtr); err != nil { fmt.Println("err", err.Error()) return } if err := WasUpdated(byPtr.CreatedTime, byPtr.ModifiedTime); err != nil { fmt.Println("err", err.Error()) return } fmt.Println("Models saved.") }
Output: Models saved.
Example (CompositeKeyUpserts) ¶
package main import ( "fmt" "github.com/nofeaturesonlybugs/sqlh/model/examples" ) func main() { // This example demonstrates using Models.Save when the models have only "key" key fields // and zero "key,auto" fields. Such models are saved with UPSERT. // // Create a mock database. db, err := examples.Connect(examples.ExRelationshipSave) if err != nil { fmt.Println("err", err.Error()) return } values := []examples.Relationship{ { LeftId: 1, // LeftId and RightId are the composite key RightId: 2, Toggle: false, }, { LeftId: 10, RightId: 20, Toggle: false, }, } // Save the models; since these models only have "key,auto" fields they will first INSERT. if err := examples.Models.Save(db, values); err != nil { fmt.Println("err", err.Error()) return } // Edit the model fields. values[0].Toggle = true values[1].Toggle = true // Save the models; since the key fields are no longer zero values they will UPDATE. if err := examples.Models.Save(db, values); err != nil { fmt.Println("err", err.Error()) return } fmt.Println("Models saved.") }
Output: Models saved.
Example (NoKeyFieldsInserts) ¶
package main import ( "fmt" "github.com/nofeaturesonlybugs/sqlh/model/examples" ) func main() { // This example demonstrates using Models.Save when the models do not have any // "key" or "key,auto" fields. Such models must INSERT. // // Note also that such a model could be a partial model of the actual database table // that does have key fields defined in the table schema. // // Create a mock database. db, err := examples.Connect(examples.ExLogEntrySave) if err != nil { fmt.Println("err", err.Error()) return } values := []examples.LogEntry{ {Message: "Hello, World!"}, {Message: "Foo, Bar!"}, {Message: "The llamas are escaping!"}, } // Save the models; since these models have no "key" or "key,auto" fields use INSERT. if err := examples.Models.Save(db, values); err != nil { fmt.Println("err", err.Error()) return } fmt.Println("Models saved.") }
Output: Models saved.
Example (Slice) ¶
package main import ( "fmt" "time" "github.com/nofeaturesonlybugs/sqlh/model/examples" ) func main() { // This example demonstrates using Models.Save when the models have only "key,auto" fields. // This means when models are first created and passed to Save an INSERT is performed. // Subsequent calls to Save with the model instances results in UPDATE queries. var zero time.Time // // Create a mock database. db, err := examples.Connect(examples.ExAddressSaveSlice) if err != nil { fmt.Println("err", err.Error()) return } WasInserted := func(id int, created time.Time, modified time.Time) error { if id == 0 || zero.Equal(created) || !created.Equal(modified) { return fmt.Errorf("Record not inserted.") } return nil } WasUpdated := func(created time.Time, modified time.Time) error { if created.Equal(modified) { return fmt.Errorf("Record not updated.") } return nil } values := []examples.Address{ { Street: "1234 The Street", City: "Small City", State: "ST", Zip: "98765", }, { Street: "55 Here We Are", City: "Big City", State: "TS", Zip: "56789", }, } // Save the models; since these models only have "key,auto" fields they will first INSERT. if err := examples.Models.Save(db, values); err != nil { fmt.Println("err", err.Error()) return } for _, value := range values { if err := WasInserted(value.Id, value.CreatedTime, value.ModifiedTime); err != nil { fmt.Println("err", err.Error()) return } } // Edit the model fields. values[0].Street = "1 New Street" values[0].Zip = "99111" values[1].Street = "2 New Street" values[1].Zip = "99222" // Save the models; since the key fields are no longer zero values they will UPDATE. if err := examples.Models.Save(db, values); err != nil { fmt.Println("err", err.Error()) return } for _, value := range values { if err := WasUpdated(value.CreatedTime, value.ModifiedTime); err != nil { fmt.Println("err", err.Error()) return } } fmt.Println("Models saved.") }
Output: Models saved.
func (*Models) Update ¶
Update attempts to persist values via UPDATESs.
Example ¶
package main import ( "fmt" "time" "github.com/nofeaturesonlybugs/sqlh/model/examples" ) func main() { var zero time.Time // // Create a mock database. db, err := examples.Connect(examples.ExAddressUpdate) if err != nil { fmt.Println("err", err.Error()) return } WasUpdated := func(modified time.Time) error { if zero.Equal(modified) { return fmt.Errorf("Record not updated.") } return nil } // A "value" record. byVal := 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", } // A pointer record. byPtr := &examples.Address{ Id: 42, CreatedTime: time.Now().Add(-1 * time.Hour), // ModifiedTime is zero value; will be updated by database. Street: "4321 The Street", City: "Big City", State: "TS", Zip: "56789", } // Pass "value" record by address. if err := examples.Models.Update(db, &byVal); err != nil { fmt.Println("err", err.Error()) return } if err := WasUpdated(byVal.ModifiedTime); err != nil { fmt.Println("err", err.Error()) return } // Pass pointer record directly. if err := examples.Models.Update(db, byPtr); err != nil { fmt.Println("err", err.Error()) return } if err := WasUpdated(byPtr.ModifiedTime); err != nil { fmt.Println("err", err.Error()) return } fmt.Printf("Models updated.") }
Output: Models updated.
Example (Slice) ¶
package main import ( "fmt" "time" "github.com/nofeaturesonlybugs/sqlh/model/examples" ) func main() { var zero time.Time // // Create a mock database. db, err := examples.Connect(examples.ExAddressUpdateSlice) if err != nil { fmt.Println("err", err.Error()) return } WasUpdated := func(modified time.Time) error { if zero.Equal(modified) { return fmt.Errorf("Record not updated.") } return nil } // Slice of values. values := []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", }, } // Slice of pointers. pointers := []*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", }, } // Slice of values can be passed directly. if err := examples.Models.Update(db, values); err != nil { fmt.Println("err", err.Error()) return } for _, model := range values { if err := WasUpdated(model.ModifiedTime); err != nil { fmt.Println("err", err.Error()) return } } // Slice of pointers can be passed directly. if err := examples.Models.Update(db, pointers); err != nil { fmt.Println("err", err.Error()) return } for _, model := range pointers { if err := WasUpdated(model.ModifiedTime); err != nil { fmt.Println("err", err.Error()) return } } fmt.Println("Models updated.") }
Output: Models updated.
func (*Models) Upsert ¶ added in v0.3.0
Upsert attempts to persist values via UPSERTs.
Upsert only works on primary keys that are defined as "key"; in other words columns tagged with "key,auto" are not used in the generated query.
Upsert only supports primary keys; currently there is no support for upsert on UNIQUE indexes that are not primary keys.
Example ¶
package main import ( "fmt" "time" "github.com/nofeaturesonlybugs/sqlh/model/examples" ) func main() { var zero time.Time // // Create a mock database. db, err := examples.Connect(examples.ExUpsert) if err != nil { fmt.Println("err", err.Error()) return } WasUpserted := func(created time.Time, modified time.Time) error { if zero.Equal(created) || zero.Equal(modified) { return fmt.Errorf("Record not upserted.") } return nil } // A "value" record. byVal := examples.Upsertable{ Id: "some-unique-string", String: "Hello, World!", Number: 42, } // A pointer record. byPtr := &examples.Upsertable{ Id: "other-unique-string", String: "Foo, Bar!", Number: 100, } // Pass "value" record by address. if err := examples.Models.Upsert(db, &byVal); err != nil { fmt.Println("err", err.Error()) return } if err := WasUpserted(byVal.CreatedTime, byVal.ModifiedTime); err != nil { fmt.Println("err", err.Error()) return } // Pass pointer record directly. if err := examples.Models.Upsert(db, byPtr); err != nil { fmt.Println("err", err.Error()) return } if err := WasUpserted(byPtr.CreatedTime, byPtr.ModifiedTime); err != nil { fmt.Println("err", err.Error()) return } fmt.Printf("Models upserted.") }
Output: Models upserted.
Example (Slice) ¶
package main import ( "fmt" "time" "github.com/nofeaturesonlybugs/sqlh/model/examples" ) func main() { var zero time.Time // // Create a mock database. db, err := examples.Connect(examples.ExUpsertSlice) if err != nil { fmt.Println("err", err.Error()) return } WasUpserted := func(created time.Time, modified time.Time) error { if zero.Equal(created) || zero.Equal(modified) { return fmt.Errorf("Record not upserted.") } return nil } // Slice of values. values := []examples.Upsertable{ { Id: "some-unique-string", String: "Hello, World!", Number: 42, }, { Id: "other-unique-string", String: "Goodbye, World!", Number: 10, }, } // Slice of pointers. pointers := []*examples.Upsertable{ { Id: "some-unique-string", String: "Hello, World!", Number: 42, }, { Id: "other-unique-string", String: "Goodbye, World!", Number: 10, }, } // Pass "values" directly. if err := examples.Models.Upsert(db, values); err != nil { fmt.Println("err", err.Error()) return } for _, model := range values { if err := WasUpserted(model.CreatedTime, model.ModifiedTime); err != nil { fmt.Println("err", err.Error()) return } } // Pass pointers directly. if err := examples.Models.Upsert(db, pointers); err != nil { fmt.Println("err", err.Error()) return } for _, model := range pointers { if err := WasUpserted(model.CreatedTime, model.ModifiedTime); err != nil { fmt.Println("err", err.Error()) return } } fmt.Println("Models upserted.") }
Output: Models upserted.
type QueryBinding ¶
type QueryBinding struct {
// contains filtered or unexported fields
}
QueryBinding binds a model together with a specific query.
func (QueryBinding) Query ¶
func (me QueryBinding) Query(q sqlh.IQueries, value interface{}) error
Query accepts either a single model M or a slice of models []M. It then runs and returns the result of QueryOne or QuerySlice.
func (QueryBinding) QueryOne ¶
func (me QueryBinding) QueryOne(q sqlh.IQueries, value interface{}) error
QueryOne runs the query against a single instance of the model.
As a special case value can be an instance of reflect.Value.
func (QueryBinding) QuerySlice ¶
func (me QueryBinding) QuerySlice(q sqlh.IQueries, values interface{}) error
QuerySlice runs the query against a slice of model instances.
type SaveMode ¶ added in v0.5.0
type SaveMode int
SaveMode describes how a model should be saved when passed to Models.Save method.
const ( // Models with zero key fields can only be inserted. Insert SaveMode // Models with only key,auto fields use insert or update depending // on the current values of the key fields. If any key,auto field // is not the zero value then update otherwise insert. InsertOrUpdate // Models with at least one key field that is not auto must use upsert. Upsert )
Source Files ¶
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. |