2016-01-29 10:00:41 +08:00
|
|
|
// Package store abstracts the persistent storage used by elvish.
|
2014-10-01 06:57:38 +08:00
|
|
|
package store
|
|
|
|
|
|
|
|
import (
|
|
|
|
"database/sql"
|
2014-10-02 04:46:17 +08:00
|
|
|
"fmt"
|
2014-10-01 06:57:38 +08:00
|
|
|
"net/url"
|
2016-02-20 09:32:12 +08:00
|
|
|
"sync"
|
2014-10-01 06:57:38 +08:00
|
|
|
|
2016-02-20 10:04:44 +08:00
|
|
|
_ "github.com/mattn/go-sqlite3" // enable the "sqlite3" SQL driver
|
2014-10-01 06:57:38 +08:00
|
|
|
)
|
|
|
|
|
2016-02-08 06:23:16 +08:00
|
|
|
// Store is the permanent storage backend for elvish.
|
2014-10-01 06:57:38 +08:00
|
|
|
type Store struct {
|
2016-02-20 09:32:12 +08:00
|
|
|
db *sql.DB
|
|
|
|
Waits sync.WaitGroup
|
2014-10-01 06:57:38 +08:00
|
|
|
}
|
|
|
|
|
2016-02-13 07:21:46 +08:00
|
|
|
var initTable = map[string](func(*sql.DB) error){}
|
2014-10-01 06:57:38 +08:00
|
|
|
|
|
|
|
// DefaultDB returns the default database for storage.
|
2016-02-13 07:35:33 +08:00
|
|
|
func DefaultDB(dbname string) (*sql.DB, error) {
|
|
|
|
uri := "file:" + url.QueryEscape(dbname) +
|
2014-10-01 06:57:38 +08:00
|
|
|
"?mode=rwc&cache=shared&vfs=unix-dotfile"
|
|
|
|
return sql.Open("sqlite3", uri)
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewStore creates a new Store with the default database.
|
2016-02-13 07:35:33 +08:00
|
|
|
func NewStore(dbname string) (*Store, error) {
|
|
|
|
db, err := DefaultDB(dbname)
|
2014-10-01 06:57:38 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return NewStoreDB(db)
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewStoreDB creates a new Store with a custom database. The database must be
|
|
|
|
// a SQLite database.
|
|
|
|
func NewStoreDB(db *sql.DB) (*Store, error) {
|
2016-02-20 09:32:12 +08:00
|
|
|
st := &Store{db, sync.WaitGroup{}}
|
2014-10-02 04:46:17 +08:00
|
|
|
|
2016-02-13 07:21:46 +08:00
|
|
|
for name, fn := range initTable {
|
|
|
|
err := fn(db)
|
2014-10-02 04:46:17 +08:00
|
|
|
if err != nil {
|
2016-02-13 07:21:46 +08:00
|
|
|
return nil, fmt.Errorf("failed to initialize table %s: %v", name, err)
|
2014-10-02 04:46:17 +08:00
|
|
|
}
|
2014-10-01 06:57:38 +08:00
|
|
|
}
|
2014-10-02 04:46:17 +08:00
|
|
|
|
|
|
|
return st, nil
|
2014-10-01 06:57:38 +08:00
|
|
|
}
|
2016-02-15 21:13:50 +08:00
|
|
|
|
|
|
|
func (s *Store) Close() error {
|
2016-02-20 09:27:26 +08:00
|
|
|
if s == nil || s.db == nil {
|
2016-02-20 08:37:38 +08:00
|
|
|
return nil
|
|
|
|
}
|
2016-02-20 09:32:12 +08:00
|
|
|
s.Waits.Wait()
|
2016-02-15 21:13:50 +08:00
|
|
|
return s.db.Close()
|
|
|
|
}
|