package database import ( "context" "fmt" "time" // Go has no UUID in the standard library as of go1.25 — checked // against this repo's toolchain, not assumed. Swap this import for // the stdlib package the moment one lands; nothing else here // depends on the implementation. "github.com/google/uuid" ) // timeFormat matches the strftime pattern the schema uses for its // defaults, so rows written by Go and rows written by a DEFAULT sort // against each other correctly. const timeFormat = "2006-01-02T15:04:05.000Z" // Widget is the example row type. It exists so that the migration // runner, the query layer, the templates and the tests all exercise // real data. Delete it when seeding a real project. type Widget struct { ID string Name string SizeBytes int64 CreatedAt time.Time } // CreateWidget inserts a widget and returns it as stored. func (d *Database) CreateWidget( ctx context.Context, name string, size int64, ) (*Widget, error) { w := &Widget{ ID: uuid.NewString(), Name: name, SizeBytes: size, CreatedAt: time.Now().UTC(), } _, err := d.db.ExecContext(ctx, `INSERT INTO widgets (id, name, size_bytes, created_at) VALUES (?, ?, ?, ?)`, w.ID, w.Name, w.SizeBytes, w.CreatedAt.Format(timeFormat), ) if err != nil { return nil, fmt.Errorf("inserting widget: %w", err) } return w, nil } // ListWidgets returns the most recently created widgets, newest first, // up to limit. func (d *Database) ListWidgets(ctx context.Context, limit int) ([]Widget, error) { rows, err := d.db.QueryContext(ctx, `SELECT id, name, size_bytes, created_at FROM widgets ORDER BY created_at DESC, id DESC LIMIT ?`, limit, ) if err != nil { return nil, fmt.Errorf("listing widgets: %w", err) } defer func() { _ = rows.Close() }() widgets := []Widget{} for rows.Next() { var ( w Widget createdAt string ) scanErr := rows.Scan(&w.ID, &w.Name, &w.SizeBytes, &createdAt) if scanErr != nil { return nil, fmt.Errorf("scanning widget: %w", scanErr) } w.CreatedAt, scanErr = time.Parse(timeFormat, createdAt) if scanErr != nil { return nil, fmt.Errorf("parsing widget created_at %q: %w", createdAt, scanErr) } widgets = append(widgets, w) } err = rows.Err() if err != nil { return nil, fmt.Errorf("iterating widgets: %w", err) } return widgets, nil } // CountWidgets returns the number of widgets stored. func (d *Database) CountWidgets(ctx context.Context) (int, error) { var n int err := d.db.QueryRowContext(ctx, `SELECT COUNT(*) FROM widgets`).Scan(&n) if err != nil { return 0, fmt.Errorf("counting widgets: %w", err) } return n, nil }