This repository has been archived by the owner on Feb 3, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
initial partial implentation of SQLite implementation of UpdateStore
- Loading branch information
1 parent
d118e8b
commit c653fe5
Showing
2 changed files
with
191 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
// Package sqlitestore is a SQLite-backed implementation of the UpdateStore | ||
// interface. | ||
package sqlitestore | ||
|
||
import ( | ||
"database/sql" | ||
_ "github.com/mattn/go-sqlite3" | ||
"partisci/version" | ||
"time" | ||
) | ||
|
||
// SQLiteStore is an a SQLite-backed implementation of the UpdateStore interface. | ||
type SQLiteStore struct { | ||
db *sql.DB | ||
path string | ||
} | ||
|
||
// NewSQLiteStore returns a new, initialized SQLiteStore. | ||
func NewSQLiteStore(path string) (s *SQLiteStore, err error) { | ||
s = new(SQLiteStore) | ||
db, err := sql.Open("sqlite3", path) | ||
if err != nil { | ||
return nil, err | ||
} | ||
s.db = db | ||
err = s.checkInit() | ||
if err != nil { | ||
return nil, err | ||
} | ||
return s, nil | ||
} | ||
|
||
func (s *SQLiteStore) checkInit() (err error) { | ||
for _, sql := range sqls { | ||
_, err = s.db.Exec(sql) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func (s *SQLiteStore) Close() (err error) { | ||
err = s.db.Close() | ||
return | ||
} | ||
|
||
func (s *SQLiteStore) App(AppId string) (as version.AppSummary, ok bool) { | ||
row := s.db.QueryRow(` | ||
select app_id, max(app), max(last_update), count(host) | ||
from version | ||
where app_id = ? | ||
group by app_id`, AppId) | ||
err := row.Scan(&as.AppId, &as.App, &as.LastUpdate, &as.HostCount) | ||
if err != nil { | ||
// TODO: should App() & Host() return errors instead of ok? | ||
return as, false | ||
} | ||
return as, true | ||
} | ||
|
||
func (s *SQLiteStore) Apps() []version.AppSummary { | ||
as := make([]version.AppSummary, 0) | ||
return as | ||
} | ||
|
||
func (s *SQLiteStore) Host(Host string) (hs version.HostSummary, ok bool) { | ||
return | ||
} | ||
|
||
func (s *SQLiteStore) Hosts() []version.HostSummary { | ||
vs := make([]version.HostSummary, 0) | ||
return vs | ||
} | ||
|
||
func (s *SQLiteStore) Update(v version.Version) (err error) { | ||
tx, err := s.db.Begin() | ||
if err != nil { | ||
return | ||
} | ||
stmt, err := tx.Prepare( | ||
`insert into version(key, app_id, app, ver, host, | ||
instance, host_ip, last_update, exact_update) | ||
values(?, ?, ?, ?, ?, ?, ?, ?, ?)`) | ||
if err != nil { | ||
return | ||
} | ||
defer stmt.Close() | ||
|
||
_, err = stmt.Exec(v.Key(), v.AppId, v.App, v.Ver, v.Host, | ||
v.Instance, v.HostIP, v.LastUpdate, v.ExactUpdate.Format(time.RFC3339)) | ||
if err != nil { | ||
return | ||
} | ||
err = tx.Commit() | ||
if err != nil { | ||
return | ||
} | ||
return | ||
} | ||
|
||
func (s *SQLiteStore) Versions(app_id string, | ||
host string, ver string) []version.Version { | ||
v := make([]version.Version, 0) | ||
return v | ||
} | ||
|
||
func (s *SQLiteStore) Clear() { | ||
} | ||
|
||
func (s *SQLiteStore) Trim(t time.Time) (c uint64) { | ||
c = 0 | ||
return | ||
} | ||
|
||
var sqls = []string{ | ||
`create table if not exists version | ||
(key varchar not null on conflict replace primary key, | ||
app_id varchar not null, | ||
app varchar not null, | ||
ver varchar not null, | ||
host varchar not null, | ||
instance int not null, | ||
host_ip varchar not null, | ||
last_update int not null, | ||
exact_update datetime not null);`, | ||
`create index if not exists version_app_id on version (app_id);`, | ||
`create index if not exists version_ver on version (ver);`, | ||
`create index if not exists version_host on version (host);`, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package sqlitestore | ||
|
||
import ( | ||
"log" | ||
"os" | ||
"partisci/store" | ||
"path/filepath" | ||
"testing" | ||
) | ||
|
||
const dbPath = "partisci_testing_db.sqlite" | ||
|
||
func cleanup(path string) { | ||
err := os.Remove(path) | ||
if err != nil { | ||
if os.IsNotExist(err) { | ||
log.Print("cleanup(): didn't exist") | ||
} else { | ||
log.Print("cleanup(): ", err) | ||
} | ||
} else { | ||
log.Print("cleanup(): removed file") | ||
} | ||
} | ||
|
||
func TestNewSQLiteStore(t *testing.T) { | ||
path := filepath.Join(os.TempDir(), dbPath) | ||
log.Print(path) | ||
cleanup(path) | ||
s, err := NewSQLiteStore(path) | ||
if err != nil { | ||
t.Fatal(err) | ||
} else { | ||
s.Close() | ||
} | ||
// the sqlite database should be created | ||
if _, err := os.Stat(path); err != nil { | ||
if os.IsNotExist(err) { | ||
t.Fatal("SQLite db file not found: ", err) | ||
} else { | ||
t.Fatal(err) | ||
} | ||
} | ||
|
||
// ensure we can open it again, implying db init idempotency | ||
s2, err := NewSQLiteStore(path) | ||
if err != nil { | ||
t.Fatal(err) | ||
} else { | ||
s2.Close() | ||
} | ||
} | ||
|
||
func TestAppSummary(t *testing.T) { | ||
path := filepath.Join(os.TempDir(), dbPath) | ||
s, err := NewSQLiteStore(path) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
store.USTestAppSummary(s, t) | ||
} |