Documentation ¶
Overview ¶
Package rebecca is lightweight convenience library for work with database
See github README for instructions: https://github.com/waterlink/rebecca#rebecca
See examples: https://godoc.org/github.com/waterlink/rebecca#pkg-examples
Simple example:
type Person struct { rebecca.ModelMetadata `tablename:"people"` ID int `rebecca:"id" rebecca_primary:"true"` Name string `rebecca:"name"` Age int `rebecca:"age"` } // Create new record p := &Person{Name: "John", Age: 34} if err := rebecca.Save(p); err != nil { // handle error here } fmt.Print(p) // Update existing record p.Name = "John Smith" if err := rebecca.Save(p); err != nil { // handle error here } fmt.Print(p) // Get record by its primary key p = &Person{} if err := rebecca.Get(p, 25); err != nil { // handle error here } fmt.Print(p)
Index ¶
- func All(records interface{}) error
- func Exec(query string, args ...interface{}) error
- func First(record interface{}, where string, args ...interface{}) error
- func Get(record interface{}, ID interface{}) error
- func Remove(record interface{}) error
- func Save(record interface{}) error
- func SetupDriver(d driver.Driver)
- func Transact(fn func(tx *Transaction) error) (err error)
- func Where(records interface{}, where string, args ...interface{}) error
- type Context
- func (c *Context) All(records interface{}) error
- func (c *Context) First(record interface{}, query string, args ...interface{}) error
- func (c *Context) GetGroup() string
- func (c *Context) GetLimit() int
- func (c *Context) GetOrder() string
- func (c *Context) GetSkip() int
- func (c *Context) GetTx() interface{}
- func (c *Context) SetGroup(group string) context.Context
- func (c *Context) SetLimit(limit int) context.Context
- func (c *Context) SetOrder(order string) context.Context
- func (c *Context) SetSkip(skip int) context.Context
- func (c *Context) SetTx(tx interface{}) context.Context
- func (c *Context) Where(records interface{}, query string, args ...interface{}) error
- type ModelMetadata
- type Recovered
- type Transaction
- func (tx *Transaction) All(records interface{}) error
- func (tx *Transaction) Commit() error
- func (tx *Transaction) Context(ctx *Context) *Context
- func (tx *Transaction) Exec(query string, args ...interface{}) error
- func (tx *Transaction) First(record interface{}, where string, args ...interface{}) error
- func (tx *Transaction) Get(record interface{}, ID interface{}) error
- func (tx *Transaction) Remove(record interface{}) error
- func (tx *Transaction) Rollback()
- func (tx *Transaction) Save(record interface{}) error
- func (tx *Transaction) Where(records interface{}, where string, args ...interface{}) error
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func All ¶
func All(records interface{}) error
All is for fetching all records
Example ¶
package main import ( "fmt" "github.com/waterlink/rebecca" ) func main() { type Person struct { // ... } people := []Person{} if err := rebecca.All(&people); err != nil { panic(err) } // At this point people contains all Person records. fmt.Print(people) }
Output:
func Exec ¶
Exec is for executing arbitrary query and discarding its result
Example ¶
package main import ( "github.com/waterlink/rebecca" ) func main() { ID := 25 if err := rebecca.Exec("UPDATE counters SET value = value + 1 WHERE id = $1", ID); err != nil { panic(err) } }
Output:
func First ¶
First is for fetching only one specific record
Example ¶
package main import ( "fmt" "github.com/waterlink/rebecca" ) func main() { type Person struct { // ... } person := &Person{} if err := rebecca.First(person, "name = $1", "John Smith"); err != nil { panic(err) } // At this point person contains first record from the database that has // name="John Smith". fmt.Print(person) }
Output:
func Get ¶
func Get(record interface{}, ID interface{}) error
Get is for fetching one record
Example ¶
package main import ( "fmt" "github.com/waterlink/rebecca" ) func main() { type Person struct { // ... } person := &Person{} if err := rebecca.Get(person, 25); err != nil { panic(err) } // At this point person contains record with primary key equal to 25. fmt.Print(person) }
Output:
func Remove ¶
func Remove(record interface{}) error
Remove is for removing the record
Example ¶
package main import ( "github.com/waterlink/rebecca" ) func main() { type Person struct { // ... } // First lets find person with primary key = 25 person := &Person{} if err := rebecca.Get(person, 25); err != nil { panic(err) } // And then, lets remove it if err := rebecca.Remove(person); err != nil { panic(err) } // At this point person with primary key = 25 was removed from database. }
Output:
func Save ¶
func Save(record interface{}) error
Save is for saving one record (either creating or updating)
Example ¶
package main import ( "fmt" "github.com/waterlink/rebecca" ) func main() { // Lets first define our model: type Person struct { // the table name is people rebecca.ModelMetadata `tablename:"people"` // ID is of type int, in database it is mapped to `id` and it is a primary // key. // Name is of type string, in database it is mapped to `name`. // Age is of type int, in database it is mapped to `age`. ID int `rebecca:"id" rebecca_primary:"true"` Name string `rebecca:"name"` Age int `rebecca:"age"` } // And now, lets create new record: person := &Person{Name: "John", Age: 28} // And finally, lets save it to the database if err := rebecca.Save(person); err != nil { panic(err) } // At this point, record was saved to database as a new record and its ID // field was updated accordingly. fmt.Print(person) // Now lets modify our record: person.Name = "John Smith" // And save it if err := rebecca.Save(person); err != nil { panic(err) } // At this point, original record was update with new data. fmt.Print(person) }
Output:
func Transact ¶
func Transact(fn func(tx *Transaction) error) (err error)
Transact is for abstracting transaction handling. It commits transaction if fn returned nil, otherwise it rolls transaction back.
Example ¶
package main import ( "fmt" "github.com/waterlink/rebecca" ) func main() { type Person struct { // ... } rebecca.Transact(func(tx *rebecca.Transaction) error { // Now you can use `tx` the same way as `rebecca` package, i.e.: people := []Person{} if err := tx.Where(&people, "name = $1 AND age > $2", "James", 25); err != nil { // returning non-nil result here will make transaction roll back return err // panicking will achieve the same result // panic(err) } // At this point people contains all Person records with name="James" and // with age > 25. fmt.Print(people) // This way you can use all main exported functions of rebecca package as // methods on `tx`: // - tx.All(records) // - tx.First(record, where, args...) // - tx.Get(record, ID) // - tx.Remove(record) // - tx.Save(record) // - tx.Where(records, where, args...) // For example: record := &Person{} return tx.Save(record) }) }
Output:
func Where ¶
Where is for fetching specific records
Example ¶
package main import ( "fmt" "github.com/waterlink/rebecca" ) func main() { type Person struct { // ... } teenagers := []Person{} if err := rebecca.Where(teenagers, "age < $1", 21); err != nil { panic(err) } // At this point teenagers contains all Person records with age < 21. fmt.Print(teenagers) }
Output:
Types ¶
type Context ¶
type Context struct { // Defines ordering of the query Order string // Defines grouping criteria of the query Group string // Defines maximum amount of records requested for the query Limit int // Defines starting record for the query Skip int Offset int // alias of Skip // contains filtered or unexported fields }
Context is for storing query context
func (*Context) All ¶
All is for fetching all records
Example ¶
package main import ( "fmt" "github.com/waterlink/rebecca" ) func main() { type Person struct { // ... } ctx := rebecca.Context{Limit: 20, Skip: 40} people := []Person{} if err := ctx.All(&people); err != nil { panic(err) } // At this point people contains 20 Person records starting from 41th from // the database. fmt.Print(people) }
Output:
Example (SkipOffsetAlias) ¶
package main import ( "fmt" "github.com/waterlink/rebecca" ) func main() { type Person struct { // ... } ctx := rebecca.Context{Limit: 20, Offset: 40} people := []Person{} if err := ctx.All(&people); err != nil { panic(err) } // At this point people contains 20 Person records starting from 41th from // the database. fmt.Print(people) }
Output:
func (*Context) First ¶
First is for fetching only one specific record
Example ¶
package main import ( "fmt" "github.com/waterlink/rebecca" ) func main() { type Person struct { // ... } ctx := rebecca.Context{Order: "age DESC"} oldestTeenager := &Person{} if err := ctx.First(oldestTeenager, "age < $1", 21); err != nil { panic(err) } // At this point oldestTeenager will contain a Person record that is of // maximum age and that is of age < 21. fmt.Print(oldestTeenager) }
Output:
func (*Context) GetSkip ¶
GetSkip is for fetching context's Skip. Also it fetches Offset if present, hence the alias. Used by drivers
func (*Context) GetTx ¶
func (c *Context) GetTx() interface{}
GetTx is for fetching context's driver transaction state. Used by drivers
func (*Context) SetOrder ¶
SetOrder is for setting context's Order, it creates new Context. Used by drivers
func (*Context) Where ¶
Where is for fetching specific records
Example ¶
package main import ( "fmt" "github.com/waterlink/rebecca" ) func main() { type Person struct { // ... } ctx := rebecca.Context{Order: "age DESC"} teenagers := []Person{} if err := ctx.Where(&teenagers, "age < $1", 21); err != nil { panic(err) } // At this point teenagers will contain a list of Person records sorted by // age in descending order and where age < 21. fmt.Print(teenagers) }
Output:
type ModelMetadata ¶
type ModelMetadata struct{}
ModelMetadata is for storing any metadata for the whole model
Example ¶
package main import ( "fmt" "github.com/waterlink/rebecca" ) func main() { type Person struct { // ModelMetadata allows to provide table name for the model rebecca.ModelMetadata `tablename:"people"` ID int `rebecca:"id" rebecca_primary:"true"` Name string `rebecca:"name"` Age int `rebecca:"age"` } type PostsOfPerson struct { // Additionally you can have any expression as a table name, that your // driver will allow, for example, simple join: rebecca.ModelMetadata `tablename:"people JOIN posts ON posts.author_id = people.id"` // .. fields are defined here .. } type PersonCountByAge struct { rebecca.ModelMetadata `tablename:"people"` // Additionally you can use any expressions as a database mapping for // fields, that your driver will allow, for example, // count(distinct(field_name)): Count int `rebecca:"count(distinct(id))"` Age int `rebecca:"age"` } // PersonCountByAge is useful, because it can be nicely used with // aggregation: byAge := []PersonCountByAge{} ctx := rebecca.Context{Group: "age"} if err := ctx.All(&byAge); err != nil { panic(err) } // At this point byAge contains counts of people per each distinct age. // Ordering depends on your chosen driver and database. fmt.Print(byAge) }
Output:
type Transaction ¶
type Transaction struct {
// contains filtered or unexported fields
}
Transaction is for managing transactions for drivers that allow it
func Begin ¶
func Begin() (*Transaction, error)
Begin is for creating proper transaction
Example ¶
package main import ( "fmt" "github.com/waterlink/rebecca" ) func main() { type Person struct { // ... } // Lets begin transaction: tx, err := rebecca.Begin() if err != nil { // Handle error when unable to begin transaction here. panic(err) } // Lets make sure, that transaction gets rolled back if we return prematurely: defer tx.Rollback() // Now you can use `tx` the same way as `rebecca` package, i.e.: people := []Person{} if err := tx.Where(&people, "name = $1 AND age > $2", "James", 25); err != nil { panic(err) } // At this point people contains all Person records with name="James" and // with age > 25. fmt.Print(people) // This way you can use all main exported functions of rebecca package as // methods on `tx`: // - tx.All(records) // - tx.First(record, where, args...) // - tx.Get(record, ID) // - tx.Remove(record) // - tx.Save(record) // - tx.Where(records, where, args...) // - tx.Exec(query, args...) }
Output:
func (*Transaction) All ¶
func (tx *Transaction) All(records interface{}) error
All is for fetching all records
func (*Transaction) Commit ¶
func (tx *Transaction) Commit() error
Commit is for committing the transaction
Example ¶
package main import ( "github.com/waterlink/rebecca" ) func main() { tx, err := rebecca.Begin() if err != nil { panic(err) } defer tx.Rollback() // .. doing some hard work with tx .. // And finally, lets commit the transaction: if err := tx.Commit(); err != nil { // Handle error, when transaction can not be committed, here. panic(err) } // At this point transaction `tx` is committed and should not be used // further. }
Output:
func (*Transaction) Context ¶
func (tx *Transaction) Context(ctx *Context) *Context
Context is for instantiating proper context for transaction
Example ¶
package main import ( "fmt" "github.com/waterlink/rebecca" ) func main() { type Person struct { // ... } tx, err := rebecca.Begin() if err != nil { panic(err) } defer tx.Rollback() // When you need to use rebecca.Context features (like Order or Limit/Skip, // or even Group) together with transaction, you can instantiate // rebecca.Context using transaction method Context: ctx := tx.Context(&rebecca.Context{Order: "age ASC", Limit: 30, Skip: 90}) // And then use `ctx` as usual: people := []Person{} if err := ctx.All(&people); err != nil { panic(err) } fmt.Print(people) }
Output:
func (*Transaction) Exec ¶
func (tx *Transaction) Exec(query string, args ...interface{}) error
Exec is for executing a query within transaction and discarding its result
func (*Transaction) First ¶
func (tx *Transaction) First(record interface{}, where string, args ...interface{}) error
First is for fetching only one specific record
func (*Transaction) Get ¶
func (tx *Transaction) Get(record interface{}, ID interface{}) error
Get is for fetching one record
func (*Transaction) Remove ¶
func (tx *Transaction) Remove(record interface{}) error
Remove is for removing the record
func (*Transaction) Rollback ¶
func (tx *Transaction) Rollback()
Rollback is for rolling back the transaction
Example ¶
package main import ( "github.com/waterlink/rebecca" ) func main() { tx, err := rebecca.Begin() if err != nil { panic(err) } defer tx.Rollback() // Sometimes `defer tx.Rollback()` is not acceptable and you might need // better control, in that case, you can just call `tx.Rollback()` when // necessary: if someBadCondition() { tx.Rollback() } } func someBadCondition() bool { return true }
Output:
func (*Transaction) Save ¶
func (tx *Transaction) Save(record interface{}) error
Save is for saving one record (either creating or updating)
func (*Transaction) Where ¶
func (tx *Transaction) Where(records interface{}, where string, args ...interface{}) error
Where is for fetching specific records
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
fake
Package fake is a limited in-memory implementation of rebecca.Driver It does not implement any rebecca.Context features.
|
Package fake is a limited in-memory implementation of rebecca.Driver It does not implement any rebecca.Context features. |
pg
Package pg provides implementation of rebecca driver for postgres.
|
Package pg provides implementation of rebecca driver for postgres. |
pg/auto
Package auto allows one to setup rebecca/driver/pg in a convenient way from environment variables.
|
Package auto allows one to setup rebecca/driver/pg in a convenient way from environment variables. |