1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 |
package store
import (
"context"
"database/sql"
"errors"
"time"
)
// Snapshot is one observed state of a page's file.
type Snapshot struct {
ID int64
PageID int64
Seq int
ObservedAt time.Time
SourceMtime *time.Time
SourceRef string // git commit in git mode
RawHash string
ContentHash string
Raw string // normalized file text
FrontmatterJSON string
Title string
Note string
Kind string
Maturity string
}
const snapshotCols = `id, page_id, seq, observed_at, source_mtime, source_ref, raw_hash, content_hash, raw, frontmatter_json, title, note, kind, maturity`
func scanSnapshot(row interface{ Scan(...any) error }) (*Snapshot, error) {
var s Snapshot
var observed string
var mtime sql.NullString
if err := row.Scan(&s.ID, &s.PageID, &s.Seq, &observed, &mtime, &s.SourceRef, &s.RawHash, &s.ContentHash,
&s.Raw, &s.FrontmatterJSON, &s.Title, &s.Note, &s.Kind, &s.Maturity); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, ErrNotFound
}
return nil, err
}
var err error
if s.ObservedAt, err = parseTime(observed); err != nil {
return nil, err
}
if s.SourceMtime, err = parseTimePtr(mtime); err != nil {
return nil, err
}
return &s, nil
}
// InsertSnapshot stores a snapshot as the page's next one and sets ID and Seq.
func (q *Queries) InsertSnapshot(ctx context.Context, s *Snapshot) error {
if err := q.q.QueryRowContext(ctx, `SELECT COALESCE(MAX(seq), 0) + 1 FROM snapshots WHERE page_id = ?`, s.PageID).Scan(&s.Seq); err != nil {
return err
}
res, err := q.q.ExecContext(ctx,
`INSERT INTO snapshots (page_id, seq, observed_at, source_mtime, source_ref, raw_hash, content_hash, raw, frontmatter_json, title, note, kind, maturity)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
s.PageID, s.Seq, fmtTime(s.ObservedAt), fmtTimePtr(s.SourceMtime), s.SourceRef, s.RawHash, s.ContentHash,
s.Raw, s.FrontmatterJSON, s.Title, s.Note, s.Kind, s.Maturity)
if err != nil {
return err
}
s.ID, err = res.LastInsertId()
return err
}
// Snapshot returns a snapshot by id.
func (q *Queries) Snapshot(ctx context.Context, id int64) (*Snapshot, error) {
return scanSnapshot(q.q.QueryRowContext(ctx, `SELECT `+snapshotCols+` FROM snapshots WHERE id = ?`, id))
}
// LastSnapshot returns the page's most recent snapshot.
func (q *Queries) LastSnapshot(ctx context.Context, pageID int64) (*Snapshot, error) {
return scanSnapshot(q.q.QueryRowContext(ctx,
`SELECT `+snapshotCols+` FROM snapshots WHERE page_id = ? ORDER BY seq DESC LIMIT 1`, pageID))
}
// SnapshotCount counts a page's snapshots, silent ones included.
func (q *Queries) SnapshotCount(ctx context.Context, pageID int64) (int, error) {
var n int
err := q.q.QueryRowContext(ctx, `SELECT COUNT(*) FROM snapshots WHERE page_id = ?`, pageID).Scan(&n)
return n, err
}
|