-
Notifications
You must be signed in to change notification settings - Fork 0
/
log.go
194 lines (186 loc) · 3.64 KB
/
log.go
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
package sqlite
import (
"context"
"database/sql"
"strings"
"github.com/imagvfx/forge"
)
func createLogsTable(tx *sql.Tx) error {
_, err := tx.Exec(`
CREATE TABLE IF NOT EXISTS logs (
id INTEGER PRIMARY KEY,
entry_id INTEGER,
user STRING NOT NULL,
action STRING NOT NULL,
ctg STRING NOT NULL,
name STRING NOT NULL,
typ STRING NOT NULL,
val STRING NOT NULL,
time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (entry_id) REFERENCES entries (id)
)
`)
if err != nil {
return err
}
_, err = tx.Exec(`CREATE INDEX IF NOT EXISTS index_logs_entry_id ON logs (entry_id)`)
if err != nil {
return err
}
_, err = tx.Exec(`CREATE INDEX IF NOT EXISTS index_logs_user ON logs (user)`)
return err
}
func FindLogs(db *sql.DB, ctx context.Context, find forge.LogFinder) ([]*forge.Log, error) {
tx, err := db.BeginTx(ctx, nil)
if err != nil {
return nil, err
}
defer tx.Rollback()
props, err := findLogs(tx, ctx, find)
if err != nil {
return nil, err
}
err = tx.Commit()
if err != nil {
return nil, err
}
return props, nil
}
// when id is empty, it will find logs of root.
func findLogs(tx *sql.Tx, ctx context.Context, find forge.LogFinder) ([]*forge.Log, error) {
keys := make([]string, 0)
vals := make([]any, 0)
if find.EntryPath != nil {
keys = append(keys, "entries.path=?")
vals = append(vals, *find.EntryPath)
}
if find.Category != nil {
keys = append(keys, "logs.ctg=?")
vals = append(vals, *find.Category)
}
if find.Name != nil {
keys = append(keys, "logs.name=?")
vals = append(vals, *find.Name)
}
where := ""
if len(keys) != 0 {
where = "WHERE " + strings.Join(keys, " AND ")
}
rows, err := tx.QueryContext(ctx, `
SELECT
logs.id,
entries.path,
logs.user,
logs.action,
logs.ctg,
logs.name,
logs.typ,
logs.val,
logs.time
FROM logs
LEFT JOIN entries ON logs.entry_id = entries.id
`+where,
vals...,
)
if err != nil {
return nil, err
}
defer rows.Close()
logs := make([]*forge.Log, 0)
for rows.Next() {
l := &forge.Log{}
err := rows.Scan(
&l.ID,
&l.EntryPath,
&l.User,
&l.Action,
&l.Category,
&l.Name,
&l.Type,
&l.Value,
&l.When,
)
if err != nil {
return nil, err
}
logs = append(logs, l)
}
return logs, nil
}
func GetLogs(db *sql.DB, ctx context.Context, path, ctg, name string) ([]*forge.Log, error) {
tx, err := db.BeginTx(ctx, nil)
if err != nil {
return nil, err
}
defer tx.Rollback()
log, err := getLogs(tx, ctx, path, ctg, name)
if err != nil {
return nil, err
}
err = tx.Commit()
if err != nil {
return nil, err
}
return log, nil
}
func getLogs(tx *sql.Tx, ctx context.Context, path, ctg, name string) ([]*forge.Log, error) {
logs, err := findLogs(tx, ctx, forge.LogFinder{
EntryPath: &path,
Category: &ctg,
Name: &name,
})
for _, l := range logs {
p := &forge.Property{
Type: l.Type,
RawValue: l.Value,
}
evalProperty(tx, ctx, p)
if p.ValueError != nil {
l.Value = "eval error: " + p.RawValue
continue
}
l.Value = p.Value
}
if err != nil {
return nil, err
}
if len(logs) == 0 {
return nil, forge.NotFound("log not found")
}
return logs, nil
}
func addLog(tx *sql.Tx, ctx context.Context, l *forge.Log) error {
entryID, err := getEntryID(tx, ctx, l.EntryPath)
if err != nil {
return err
}
result, err := tx.ExecContext(ctx, `
INSERT INTO logs (
entry_id,
user,
action,
ctg,
name,
typ,
val
)
VALUES (?, ?, ?, ?, ?, ?, ?)
`,
entryID,
l.User,
l.Action,
l.Category,
l.Name,
l.Type,
l.Value,
)
if err != nil {
return err
}
id, err := result.LastInsertId()
if err != nil {
return err
}
l.ID = int(id)
return nil
}