-
Notifications
You must be signed in to change notification settings - Fork 0
/
cats.go
151 lines (130 loc) · 4.51 KB
/
cats.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
package storage
import (
"fmt"
"database/sql"
apitypes "github.com/thewug/fsb/pkg/api/types"
)
type CatData struct {
Id int64
Merged apitypes.TTagData
First, Second *apitypes.TTagData
Marked bool
ReplaceId *int64
}
func (c CatData) String() string {
if c.First == nil || c.Second == nil {
return c.Merged.Name
} else {
return fmt.Sprintf("%-32s %s + %s", c.Merged.Name, c.First.Name, c.Second.Name)
}
}
func GetCats(d DBLike, yes, no bool) ([]CatData, []CatData, error) {
var out_yes, out_no []CatData
err := d.Enter(func(tx Queryable) error {
query :=
`SELECT cat_id, marked,
a.tag_id, a.tag_name, a.tag_type, a.tag_count,
b.tag_id, b.tag_name, b.tag_type, b.tag_count,
c.tag_id, c.tag_name, c.tag_type, c.tag_count
FROM cats_registered
LEFT JOIN tag_index AS a ON tag_id_merged = a.tag_id
LEFT JOIN tag_index AS b ON tag_id_1 = b.tag_id
LEFT JOIN tag_index AS c ON tag_id_2 = c.tag_id
WHERE ($1 AND marked)
OR ($2 AND NOT marked)`
rows, err := tx.Query(query, yes, no)
if err != nil { return err }
for rows.Next() {
var cat CatData
var id_1, id_2, id_merged *int
var name_1, name_2, name_merged *string
var type_1, type_2, type_merged *apitypes.TagCategory
var count_1, count_2, count_merged *int
err = rows.Scan(&cat.Id, &cat.Marked,
&id_merged, &name_merged, &type_merged, &count_merged,
&id_1, &name_1, &type_1, &count_1,
&id_2, &name_2, &type_2, &count_2)
if err != nil { return err }
cat.Merged = apitypes.TTagData{Id: *id_merged, Name: *name_merged, Type: *type_merged, Count: *count_merged}
if id_1 != nil &&id_2 != nil {
cat.First = &apitypes.TTagData{Id: *id_1, Name: *name_1, Type: *type_1, Count: *count_1}
cat.Second = &apitypes.TTagData{Id: *id_2, Name: *name_2, Type: *type_2, Count: *count_2}
}
if cat.Marked {
out_yes = append(out_yes, cat)
} else {
out_no = append(out_no, cat)
}
}
return nil
})
if err != nil {
out_yes, out_no = nil, nil
}
return out_yes, out_no, err
}
func SetCatByTagNames(d DBLike, cat CatData, marked, autofix bool) error {
merged, err := GetTagByName(d, cat.Merged.Name, true)
if err != nil { return err }
cat.Merged = *merged
// XXX squash these calls into a single database call, they don't need to be 3+ calls
if marked {
cat.First, err = GetTagByName(d, cat.First.Name, true)
if err != nil { return err }
cat.Second, err = GetTagByName(d, cat.Second.Name, true)
if err != nil { return err }
} else {
cat.First = nil
cat.Second = nil
}
cat.Marked = marked
query :=
`INSERT
INTO cats_registered (marked, tag_id_merged, tag_id_1, tag_id_2)
VALUES ($1, $2, $3, $4)
ON CONFLICT (tag_id_merged)
DO UPDATE SET
marked = EXCLUDED.marked,
tag_id_1 = EXCLUDED.tag_id_1,
tag_id_2 = EXCLUDED.tag_id_2
RETURNING cat_id, replace_id`
var row *sql.Row
err = d.Enter(func(tx Queryable) error {
if cat.First == nil || cat.Second == nil{
row = tx.QueryRow(query, cat.Marked, cat.Merged.Id, nil, nil)
} else {
row = tx.QueryRow(query, cat.Marked, cat.Merged.Id, cat.First.Id, cat.Second.Id)
}
return row.Scan(&cat.Id, &cat.ReplaceId)
})
if err != nil { return err } // you should get a row back, if that fails something is wrong
if cat.Marked {
if cat.ReplaceId == nil {
replacement := &Replacer{MatchSpec: cat.Merged.Name, ReplaceSpec: fmt.Sprintf("-%s %s %s", cat.Merged.Name, cat.First.Name, cat.Second.Name), Autofix: autofix}
replacement, err = AddReplacement(d, *replacement)
if err != nil { return err }
err = d.Enter(func(tx Queryable) error {
query := `UPDATE cats_registered SET replace_id = $2 WHERE cat_id = $1`
_, err := tx.Exec(query, cat.Id, replacement.Id)
return err
})
} else {
err = UpdateReplacement(d, Replacer{Id: *cat.ReplaceId, MatchSpec: cat.Merged.Name, ReplaceSpec: fmt.Sprintf("-%s %s %s", cat.Merged.Name, cat.First.Name, cat.Second.Name), Autofix: autofix})
}
} else if cat.ReplaceId != nil {
err = DeleteReplacement(d, *cat.ReplaceId)
}
return err
}
func DeleteCatByTagNames(d DBLike, cat CatData) error {
merged, err := GetTagByName(d, cat.Merged.Name, false)
if err != nil { return err }
if merged == nil { return nil }
cat.Merged = *merged
return d.Enter(func(tx Queryable) error {
_, err = tx.Exec(`DELETE FROM replacements WHERE replace_id = (SELECT replace_id FROM cats_registered WHERE tag_id_merged = $1)`, cat.Merged.Id)
if err != nil { return err }
_, err = tx.Exec(`DELETE FROM cats_registered WHERE tag_id_merged = $1`, cat.Merged.Id)
return err
})
}