85 lines
1.9 KiB
Go
85 lines
1.9 KiB
Go
package datastore
|
|
|
|
import (
|
|
"log"
|
|
"sync"
|
|
|
|
"github.com/jmoiron/modl"
|
|
"github.com/jmoiron/sqlx"
|
|
_ "github.com/lib/pq"
|
|
)
|
|
|
|
// DB is the global database
|
|
var DB = &modl.DbMap{Dialect: modl.PostgresDialect{}}
|
|
|
|
// DBH is a modl.SqlExecutor interface to DB, the global database. It is better to
|
|
// use DBH instead of DB because it prevents you from calling methods that could
|
|
// not later be wrapped in a transaction.
|
|
var DBH modl.SqlExecutor = DB
|
|
|
|
var connectOnce sync.Once
|
|
|
|
// Connect connects to the PostgreSQL database specified by the PG* environment
|
|
// variables. It calls log.Fatal if it encounters an error.
|
|
func Connect() {
|
|
connectOnce.Do(func() {
|
|
var err error
|
|
DB.Dbx, err = sqlx.Open("postgres", "sslmode=disable")
|
|
if err != nil {
|
|
log.Fatal("Error connecting to PostgreSQL database (using PG* environment variables): ", err)
|
|
}
|
|
DB.Db = DB.Dbx.DB
|
|
})
|
|
}
|
|
|
|
var createSQL []string
|
|
|
|
// Create the database schema. It calls log.Fatal if it encounters an error.
|
|
func Create() {
|
|
if err := DB.CreateTablesIfNotExists(); err != nil {
|
|
log.Fatal("Error creating tables: ", err)
|
|
}
|
|
for _, query := range createSQL {
|
|
if _, err := DB.Exec(query); err != nil {
|
|
log.Fatalf("Error running query %q: %s", query, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Drop the database schema
|
|
func Drop() {
|
|
// TODO(mrd): raise errors.
|
|
DB.DropTables()
|
|
}
|
|
|
|
// transact calls fn in a DB transaction. If dbh is a transaction, then it just calls
|
|
// the function. Otherwise, it begins a transaction, rolling back on failure and
|
|
// committing on success.
|
|
func transact(dbh modl.SqlExecutor, fn func(fbh modl.SqlExecutor) error) error {
|
|
var sharedTx bool
|
|
tx, sharedTx := dbh.(*modl.Transaction)
|
|
if !sharedTx {
|
|
var err error
|
|
tx, err = dbh.(*modl.DbMap).Begin()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer func() {
|
|
if err != nil {
|
|
tx.Rollback()
|
|
}
|
|
}()
|
|
}
|
|
|
|
if err := fn(tx); err != nil {
|
|
return err
|
|
}
|
|
|
|
if !sharedTx {
|
|
if err := tx.Commit(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|