From cf085e93b7abc53b8ecc78c07210384e0ff8d516 Mon Sep 17 00:00:00 2001 From: Ewy~ Date: Tue, 31 Mar 2026 17:18:35 +0200 Subject: initial commit --- storage/sqlite/sqlite.go | 132 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 storage/sqlite/sqlite.go (limited to 'storage/sqlite') diff --git a/storage/sqlite/sqlite.go b/storage/sqlite/sqlite.go new file mode 100644 index 0000000..9372828 --- /dev/null +++ b/storage/sqlite/sqlite.go @@ -0,0 +1,132 @@ +package sqlite + +import ( + "database/sql" + "delayed.link/storage" + "encoding/json" + "errors" + "github.com/google/uuid" + _ "github.com/mattn/go-sqlite3" + "github.com/spf13/pflag" + "log" +) + +var ( + dbFile = pflag.StringP("dbfile", "d", "delayedlink.db", "") +) + +type SqliteStorage struct { + *sql.DB +} + +func (s *SqliteStorage) Close() error { + return s.DB.Close() +} + +func (s *SqliteStorage) Save(item storage.Link) (uuid.UUID, error) { + stmt, err := s.Prepare("INSERT INTO links VALUES (?, ?)") + if err != nil { + return storage.Null, err + } + id := uuid.New() + item.Id = id + obj, err := item.Serialize() + if err != nil { + return storage.Null, err + } + _, err = stmt.Exec(id, obj) + if err != nil { + return storage.Null, err + } + return id, nil +} + +const insertStatement = `SELECT (obj) FROM links WHERE id = ? LIMIT 1` + +func (s *SqliteStorage) Load(key uuid.UUID) (*storage.Link, error) { + stmt, err := s.DB.Prepare(insertStatement) + if err != nil { + return nil, err + } + rows, err := stmt.Query(key.String()) + if err != nil { + return nil, err + } + defer rows.Close() + var link *storage.Link + var data []byte + if !rows.Next() { + return nil, storage.NotFoundError + } + err = rows.Scan(&data) + if err != nil { + return nil, err + } + err = json.Unmarshal(data, &link) + if err != nil { + return nil, err + } + + return link, nil +} + +const creation_sql = `CREATE TABLE IF NOT EXISTS links ( + id UUID PRIMARY KEY, + obj JSONB NOT NULL +);` + +func New() *SqliteStorage { + db, err := sql.Open("sqlite3", *dbFile) + if err != nil { + log.Panic(err) + } + + _, err = db.Exec(creation_sql) + if err != nil { + panic(err) + } + + return &SqliteStorage{ + db, + } +} + +const deleteQuery = `DELETE FROM links WHERE id = ?` + +var NotFoundError = errors.New("entry not found") + +func (s *SqliteStorage) Delete(item storage.Link) error { + stmt, err := s.DB.Prepare(deleteQuery) + if err != nil { + return err + } + res, err := stmt.Exec(item.Id) + if err != nil { + return err + } + if aff, err := res.RowsAffected(); aff < 1 || err != nil { + if err == nil { + return NotFoundError + } + return err + } + return nil +} + +const updateQuery = `UPDATE links SET obj = ? WHERE id = ?` + +func (s *SqliteStorage) Update(item storage.Link) error { + stmt, err := s.DB.Prepare(updateQuery) + if err != nil { + return err + } + obj, err := item.Serialize() + if err != nil { + return err + } + _, err = stmt.Exec(item.Id, obj) + if err != nil { + return err + } + return nil +} -- cgit v1.3