package database import ( "context" "database/sql" "fmt" ) // Settings returns every stored setting as a key/value map. func (db *DB) Settings(ctx context.Context) (map[string]string, error) { rows, err := db.QueryContext(ctx, `SELECT key, value FROM settings`) if err != nil { return nil, fmt.Errorf("load settings: %w", err) } defer rows.Close() out := map[string]string{} for rows.Next() { var k, v string if err := rows.Scan(&k, &v); err != nil { return nil, err } out[k] = v } return out, rows.Err() } // Setting reads a single setting. It returns ("", false, nil) when unset. func (db *DB) Setting(ctx context.Context, key string) (string, bool, error) { var v string err := db.QueryRowContext(ctx, `SELECT value FROM settings WHERE key = ?`, key).Scan(&v) switch { case err == sql.ErrNoRows: return "", false, nil case err != nil: return "", false, fmt.Errorf("read setting %s: %w", key, err) } return v, true, nil } // SetSetting writes one setting. func (db *DB) SetSetting(ctx context.Context, key, value string) error { _, err := db.ExecContext(ctx, ` INSERT INTO settings (key, value, updated_at) VALUES (?, ?, unixepoch()) ON CONFLICT (key) DO UPDATE SET value = excluded.value, updated_at = unixepoch()`, key, value) if err != nil { return fmt.Errorf("write setting %s: %w", key, err) } return nil } // SetSettings writes several settings atomically. func (db *DB) SetSettings(ctx context.Context, values map[string]string) error { if len(values) == 0 { return nil } return db.InTx(ctx, func(tx *sql.Tx) error { stmt, err := tx.PrepareContext(ctx, ` INSERT INTO settings (key, value, updated_at) VALUES (?, ?, unixepoch()) ON CONFLICT (key) DO UPDATE SET value = excluded.value, updated_at = unixepoch()`) if err != nil { return fmt.Errorf("prepare setting write: %w", err) } defer stmt.Close() for k, v := range values { if _, err := stmt.ExecContext(ctx, k, v); err != nil { return fmt.Errorf("write setting %s: %w", k, err) } } return nil }) } // DeleteSetting removes a setting, reverting it to its built-in default. func (db *DB) DeleteSetting(ctx context.Context, key string) error { _, err := db.ExecContext(ctx, `DELETE FROM settings WHERE key = ?`, key) return err }