planner/plan/storage/sqlite/sync.go

111 lines
2.8 KiB
Go
Raw Normal View History

2024-10-07 11:11:18 +02:00
package sqlite
import (
"database/sql"
2024-12-20 15:37:52 +01:00
"encoding/json"
2024-10-07 11:11:18 +02:00
"fmt"
"time"
"go-mod.ewintr.nl/planner/item"
)
type SqliteSync struct {
db *sql.DB
}
func NewSqliteSync(db *sql.DB) *SqliteSync {
return &SqliteSync{db: db}
}
func (s *SqliteSync) FindAll() ([]item.Item, error) {
2024-12-20 15:37:52 +01:00
rows, err := s.db.Query("SELECT id, kind, updated, deleted, recurrer, body FROM items")
2024-10-07 11:11:18 +02:00
if err != nil {
return nil, fmt.Errorf("%w: failed to query items: %v", ErrSqliteFailure, err)
}
defer rows.Close()
var items []item.Item
for rows.Next() {
var i item.Item
2024-12-20 15:37:52 +01:00
var updatedStr, recurStr string
err := rows.Scan(&i.ID, &i.Kind, &updatedStr, &i.Deleted, &recurStr, &i.Body)
2024-10-07 11:11:18 +02:00
if err != nil {
return nil, fmt.Errorf("%w: failed to scan item: %v", ErrSqliteFailure, err)
}
i.Updated, err = time.Parse(time.RFC3339, updatedStr)
if err != nil {
2024-12-20 15:37:52 +01:00
return nil, fmt.Errorf("failed to parse updated time: %v", err)
}
if recurStr != "" {
var recurrer item.Recur
if err := json.Unmarshal([]byte(recurStr), &recurrer); err != nil {
return nil, fmt.Errorf("failed to unmarshal recurrer: %v", err)
}
i.Recurrer = &recurrer
2024-10-07 11:11:18 +02:00
}
items = append(items, i)
}
if err = rows.Err(); err != nil {
2024-12-20 15:37:52 +01:00
return nil, fmt.Errorf("error iterating over rows: %v", err)
2024-10-07 11:11:18 +02:00
}
return items, nil
}
func (s *SqliteSync) Store(i item.Item) error {
// Ensure we have a valid time
if i.Updated.IsZero() {
i.Updated = time.Now()
}
2024-12-20 15:37:52 +01:00
var recurStr string
if i.Recurrer != nil {
recurBytes, err := json.Marshal(i.Recurrer)
if err != nil {
return fmt.Errorf("failed to marshal recurrer: %v", err)
}
recurStr = string(recurBytes)
}
2024-10-07 11:11:18 +02:00
_, err := s.db.Exec(
2024-12-20 15:37:52 +01:00
"INSERT OR REPLACE INTO items (id, kind, updated, deleted, recurrer, body) VALUES (?, ?, ?, ?, ?, ?)",
2024-10-07 11:11:18 +02:00
i.ID,
i.Kind,
i.Updated.UTC().Format(time.RFC3339),
i.Deleted,
2024-12-20 15:37:52 +01:00
recurStr,
2024-10-07 11:11:18 +02:00
sql.NullString{String: i.Body, Valid: i.Body != ""}, // This allows empty string but not NULL
)
if err != nil {
return fmt.Errorf("%w: failed to store item: %v", ErrSqliteFailure, err)
}
return nil
}
func (s *SqliteSync) DeleteAll() error {
_, err := s.db.Exec("DELETE FROM items")
if err != nil {
return fmt.Errorf("%w: failed to delete all items: %v", ErrSqliteFailure, err)
}
return nil
}
func (s *SqliteSync) LastUpdate() (time.Time, error) {
var updatedStr sql.NullString
err := s.db.QueryRow("SELECT MAX(updated) FROM items").Scan(&updatedStr)
if err != nil {
return time.Time{}, fmt.Errorf("%w: failed to get last update: %v", ErrSqliteFailure, err)
}
if !updatedStr.Valid {
return time.Time{}, nil // Return zero time if NULL or no rows
}
lastUpdate, err := time.Parse(time.RFC3339, updatedStr.String)
if err != nil {
return time.Time{}, fmt.Errorf("%w: failed to parse last update time: %v", ErrSqliteFailure, err)
}
return lastUpdate, nil
}