Files
2026-08-16 21:18:45 -05:00

80 lines
2.2 KiB
Go

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
}