Documentation ¶
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type DB ¶
DB wraps sql.DB FIXME Pointer type nesting is messy here...
func GetDB ¶
func GetDB() *DB
GetDB returns a db connection, reusing the same connection if one already exists.
func (*DB) GetCurrentVersion ¶
GetCurrentVersion returns the current schema version as an integer, or nil with an error
func (*DB) Migrate ¶
Migrate ensures the db supports migration, loads bootstrap info, and applies as many migrations as it can in order until there are no migrations left to run, or a migration produces an error.
func (DB) Transaction ¶
Transaction runs your function in a new transaction
Example ¶
err := GetTestDB().Transaction(func(tx *Tx) error { q := `CREATE TABLE bogus_transaction_test (id integer)` _, err := tx.Exec(q) if err != nil { return err } q = `INSERT INTO bogus_transaction_test VALUES (42)` _, err = tx.Exec(q) if err != nil { return err } q = `SELECT id FROM bogus_transaction_test` r := tx.QueryRow(q) var i int64 err = r.Scan(&i) if err != nil { return err } if i != 42 { return errors.New("i != 42") } return errors.New("OK. I've had my fun, but I don't really want that table") }) fmt.Println(err) err = GetTestDB().Transaction(func(tx *Tx) error { q := `SELECT id FROM bogus_transaction_test` r := tx.QueryRow(q) var i int64 err = r.Scan(&i) return err }) fmt.Println(err)
Output: OK. I've had my fun, but I don't really want that table pq: relation "bogus_transaction_test" does not exist
Example (DestructiveOperationRollback) ¶
// Create table with one value err := GetTestDB().Transaction(func(tx *Tx) error { q := `CREATE TABLE bogus_transaction_test (id integer)` _, err := tx.Exec(q) if err != nil { return err } q = `INSERT INTO bogus_transaction_test VALUES (42)` _, err = tx.Exec(q) if err != nil { return err } return nil }) if err != nil { fmt.Println(err) return } fmt.Println("Table created") // Truncate table in transaction that rolls back err = GetTestDB().Transaction(func(tx *Tx) error { q := `TRUNCATE TABLE bogus_transaction_test` _, err = tx.Exec(q) if err != nil { fmt.Println(err) } return errors.New("Truncate rolled back") }) fmt.Println(err) // Verify data is still there err = GetTestDB().Transaction(func(tx *Tx) error { q := `SELECT id FROM bogus_transaction_test` r := tx.QueryRow(q) var i int64 err = r.Scan(&i) if err != nil { return err } if i != 42 { return errors.New("i != 42") } return nil }) if err != nil { fmt.Println(err) } else { fmt.Println("Data still exists in table") } // Clean up err = GetTestDB().Transaction(func(tx *Tx) error { q := `DROP TABLE bogus_transaction_test` _, err = tx.Exec(q) if err != nil { fmt.Println(err) } return nil }) if err != nil { fmt.Println(err) }
Output: Table created Truncate rolled back Data still exists in table
type OrderDirection ¶
type OrderDirection int
OrderDirection ...
const ( // OrderAscending ... OrderAscending OrderDirection = iota // OrderDescending ... OrderDescending )
type Scanner ¶ added in v1.0.1
type Scanner interface {
Scan(dest ...interface{}) error
}
Scanner is a stand-in for sql.Row or sql.Rows. It allows for writing model methods that handle the call to Scan to populate the struct.
Example ¶
package main import ( "errors" "fmt" ) type Model struct { ID int Name string } func (m *Model) scan(s Scanner) error { return s.Scan(&m.ID, &m.Name) } func main() { err := GetTestDB().Transaction(func(tx *Tx) error { q := `CREATE TABLE models (id integer, name text)` _, err := tx.Exec(q) if err != nil { return err } q = `INSERT INTO models VALUES (23, 'skidoo')` _, err = tx.Exec(q) if err != nil { return err } q = `SELECT id, name FROM models` r := tx.QueryRow(q) var m Model err = m.scan(r) if err != nil { return err } if m.ID != 23 { return errors.New("m.ID != 23") } if m.Name != "skidoo" { return errors.New("m.Name != skidoo") } return errors.New("Rolling back.") }) fmt.Println(err) }
Output: Rolling back.
type TestDB ¶
type TestDB struct {
*DB
}
TestDB is the same as DB, but provides clean up methods that should never be used in production.
func GetTestDB ¶
func GetTestDB() *TestDB
GetTestDB returns a connection to the TEST_DATABASE_URL, reusing the same connection if one already exists.
func (*TestDB) TruncateTable ¶
TruncateTable does horrible things which is why it's only allowed on test databases
type Transacter ¶
Transacter interface allows us to specify that we don't care if it's a DB or a Tx