diff --git a/sqlitestore_test.go b/sqlitestore_test.go deleted file mode 100644 index 9e40c8e..0000000 --- a/sqlitestore_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package store_test - -import ( - "testing" - - "github.com/gopatchy/store" - "github.com/stretchr/testify/require" -) - -func TestSQLiteStore(t *testing.T) { - t.Parallel() - - st, err := store.NewSQLiteStore("file:testStore?mode=memory&cache=shared") - require.NoError(t, err) - - defer st.Close() - - testStorer(t, st) -} - -func TestSQLiteDelete(t *testing.T) { - t.Parallel() - - st, err := store.NewSQLiteStore("file:testDelete?mode=memory&cache=shared") - require.NoError(t, err) - - defer st.Close() - - testDelete(t, st) -} - -func TestSQLiteList(t *testing.T) { - t.Parallel() - - st, err := store.NewSQLiteStore("file:testList?mode=memory&cache=shared") - require.NoError(t, err) - - defer st.Close() - - testList(t, st) -} diff --git a/sqlitestore.go b/store.go similarity index 54% rename from sqlitestore.go rename to store.go index 26b8e7f..764cd90 100644 --- a/sqlitestore.go +++ b/store.go @@ -11,11 +11,11 @@ import ( _ "github.com/mattn/go-sqlite3" ) -type SQLiteStore struct { +type Store struct { db *sql.DB } -func NewSQLiteStore(conn string) (*SQLiteStore, error) { +func NewStore(conn string) (*Store, error) { db, err := sql.Open("sqlite3", conn) if err != nil { return nil, err @@ -24,16 +24,16 @@ func NewSQLiteStore(conn string) (*SQLiteStore, error) { // TODO: Keep a set of prepared statements with PrepareContext() // TODO: Consider tuning per https://phiresky.github.io/blog/2020/sqlite-performance-tuning/ - return &SQLiteStore{ + return &Store{ db: db, }, nil } -func (sls *SQLiteStore) Close() { - sls.db.Close() +func (s *Store) Close() { + s.db.Close() } -func (sls *SQLiteStore) Write(ctx context.Context, t string, obj any) error { +func (s *Store) Write(ctx context.Context, t string, obj any) error { id := metadata.GetMetadata(obj).ID js, err := json.Marshal(obj) @@ -41,7 +41,7 @@ func (sls *SQLiteStore) Write(ctx context.Context, t string, obj any) error { return err } - err = sls.exec(ctx, "INSERT INTO `%s` (id, obj) VALUES (?,?) ON CONFLICT(id) DO UPDATE SET obj=?;", t, id, js, js) + err = s.exec(ctx, "INSERT INTO `%s` (id, obj) VALUES (?,?) ON CONFLICT(id) DO UPDATE SET obj=?;", t, id, js, js) if err != nil { return err } @@ -49,8 +49,8 @@ func (sls *SQLiteStore) Write(ctx context.Context, t string, obj any) error { return nil } -func (sls *SQLiteStore) Delete(ctx context.Context, t, id string) error { - err := sls.exec(ctx, "DELETE FROM `%s` WHERE id=?", t, id) +func (s *Store) Delete(ctx context.Context, t, id string) error { + err := s.exec(ctx, "DELETE FROM `%s` WHERE id=?", t, id) if err != nil { return err } @@ -58,8 +58,8 @@ func (sls *SQLiteStore) Delete(ctx context.Context, t, id string) error { return nil } -func (sls *SQLiteStore) Read(ctx context.Context, t, id string, factory func() any) (any, error) { - rows, err := sls.query(ctx, "SELECT obj FROM `%s` WHERE id=?;", t, id) +func (s *Store) Read(ctx context.Context, t, id string, factory func() any) (any, error) { + rows, err := s.query(ctx, "SELECT obj FROM `%s` WHERE id=?;", t, id) if err != nil { return nil, err } @@ -87,8 +87,8 @@ func (sls *SQLiteStore) Read(ctx context.Context, t, id string, factory func() a return obj, nil } -func (sls *SQLiteStore) List(ctx context.Context, t string, factory func() any) ([]any, error) { - rows, err := sls.query(ctx, "SELECT obj FROM `%s`;", t) +func (s *Store) List(ctx context.Context, t string, factory func() any) ([]any, error) { + rows, err := s.query(ctx, "SELECT obj FROM `%s`;", t) if err != nil { return nil, err } @@ -118,20 +118,20 @@ func (sls *SQLiteStore) List(ctx context.Context, t string, factory func() any) return ret, nil } -func (sls *SQLiteStore) exec(ctx context.Context, query, t string, args ...any) error { +func (s *Store) exec(ctx context.Context, query, t string, args ...any) error { query = fmt.Sprintf(query, t) - _, err := sls.db.ExecContext(ctx, query, args...) + _, err := s.db.ExecContext(ctx, query, args...) if err == nil { return nil } - _, err = sls.db.ExecContext(ctx, sls.tableSQL(t)) + _, err = s.db.ExecContext(ctx, s.tableSQL(t)) if err != nil { return err } - _, err = sls.db.ExecContext(ctx, query, args...) + _, err = s.db.ExecContext(ctx, query, args...) if err != nil { return err } @@ -139,22 +139,22 @@ func (sls *SQLiteStore) exec(ctx context.Context, query, t string, args ...any) return nil } -func (sls *SQLiteStore) query(ctx context.Context, query, t string, args ...any) (*sql.Rows, error) { +func (s *Store) query(ctx context.Context, query, t string, args ...any) (*sql.Rows, error) { query = fmt.Sprintf(query, t) - rows, err := sls.db.QueryContext(ctx, query, args...) + rows, err := s.db.QueryContext(ctx, query, args...) if err == nil { return rows, nil } - _, err = sls.db.ExecContext(ctx, sls.tableSQL(t)) + _, err = s.db.ExecContext(ctx, s.tableSQL(t)) if err != nil { return nil, err } - return sls.db.QueryContext(ctx, query, args...) + return s.db.QueryContext(ctx, query, args...) } -func (sls *SQLiteStore) tableSQL(t string) string { +func (s *Store) tableSQL(t string) string { return fmt.Sprintf("CREATE TABLE IF NOT EXISTS `%s` (id TEXT NOT NULL PRIMARY KEY, obj TEXT NOT NULL);", t) } diff --git a/storer_test.go b/store_test.go similarity index 74% rename from storer_test.go rename to store_test.go index f090cde..c5f8350 100644 --- a/storer_test.go +++ b/store_test.go @@ -2,17 +2,28 @@ package store_test import ( "context" + "fmt" "testing" + "github.com/dchest/uniuri" "github.com/gopatchy/metadata" "github.com/gopatchy/store" "github.com/stretchr/testify/require" ) -func testStorer(t *testing.T, st store.Storer) { +func TestStore(t *testing.T) { + t.Parallel() + ctx := context.Background() - err := st.Write(ctx, "storeTest", &storeTest{ + dbname := fmt.Sprintf("file:%s?mode=memory&cache=shared", uniuri.New()) + + st, err := store.NewStore(dbname) + require.NoError(t, err) + + defer st.Close() + + err = st.Write(ctx, "storeTest", &storeTest{ Metadata: metadata.Metadata{ ID: "id1", }, @@ -47,10 +58,19 @@ func testStorer(t *testing.T, st store.Storer) { require.Equal(t, "zig", out2.(*storeTest).Opaque) } -func testDelete(t *testing.T, st store.Storer) { +func TestDelete(t *testing.T) { + t.Parallel() + ctx := context.Background() - err := st.Write(ctx, "storeTest", &storeTest{ + dbname := fmt.Sprintf("file:%s?mode=memory&cache=shared", uniuri.New()) + + st, err := store.NewStore(dbname) + require.NoError(t, err) + + defer st.Close() + + err = st.Write(ctx, "storeTest", &storeTest{ Metadata: metadata.Metadata{ ID: "id1", }, @@ -70,9 +90,18 @@ func testDelete(t *testing.T, st store.Storer) { require.Nil(t, out2) } -func testList(t *testing.T, st store.Storer) { +func TestList(t *testing.T) { + t.Parallel() + ctx := context.Background() + dbname := fmt.Sprintf("file:%s?mode=memory&cache=shared", uniuri.New()) + + st, err := store.NewStore(dbname) + require.NoError(t, err) + + defer st.Close() + objs, err := st.List(ctx, "storeTest", func() any { return &storeTest{} }) require.NoError(t, err) require.Len(t, objs, 0) diff --git a/storer.go b/storer.go deleted file mode 100644 index dd658c4..0000000 --- a/storer.go +++ /dev/null @@ -1,11 +0,0 @@ -package store - -import "context" - -type Storer interface { - Close() - Write(context.Context, string, any) error - Delete(context.Context, string, string) error - Read(context.Context, string, string, func() any) (any, error) - List(context.Context, string, func() any) ([]any, error) -}