/
app.go
333 lines (313 loc) · 5.94 KB
/
app.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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
package build
import (
"database/sql"
"fmt"
"math/rand"
_ "github.com/mattn/go-sqlite3"
)
// FIXME(paulsmith): package global db conn
var DB *sql.DB
// FIXME(paulsmith): relying on init() is not great from an app lifecycle POV
func init() {
dbPath := "./mypushupapp.db"
db, err := sql.Open("sqlite3", dbPath)
if err != nil {
panic(fmt.Errorf("opening SQLite db %s: %w", dbPath, err))
}
if err := initDb(db); err != nil {
panic(fmt.Errorf("initializing SQLite db: %w", err))
}
DB = db
}
var createTable = `
CREATE TABLE IF NOT EXISTS [albums] (
[id] INTEGER PRIMARY KEY,
[artist] TEXT,
[title] TEXT,
[released] INTEGER,
[length] INTEGER
);
`
func initDb(db *sql.DB) error {
if _, err := db.Exec(createTable); err != nil {
return fmt.Errorf("creating albums table: %w", err)
}
return nil
}
type album struct {
id int
artist string
title string
released int
length int
}
var insertAlbumRow = `
INSERT INTO [albums] ([artist], [title], [released], [length])
VALUES (?, ?, ?, ?)
RETURNING [id]
`
func addAlbum(db *sql.DB, a *album) error {
args := []any{
a.artist,
a.title,
a.released,
a.length,
}
if err := db.QueryRow(insertAlbumRow, args...).Scan(&a.id); err != nil {
return fmt.Errorf("inserting album: %w", err)
}
return nil
}
var selectAlbumById = `
SELECT [artist], [title], [released], [length]
FROM [albums]
WHERE [id] = ?
`
func getAlbumById(db *sql.DB, id int) (*album, error) {
a := album{id: id}
dest := []any{
&a.artist,
&a.title,
&a.released,
&a.length,
}
if err := db.QueryRow(selectAlbumById, id).Scan(dest...); err != nil {
return nil, fmt.Errorf("getting album by ID: %w", err)
}
return &a, nil
}
var selectAlbums = `
SELECT [id], [artist], [title], [released], [length]
FROM [albums]
ORDER BY id
`
func getAlbums(db *sql.DB, limit, offset int) ([]*album, error) {
query := selectAlbums
var args []any
if limit > 0 {
query += " LIMIT ?"
args = append(args, limit)
}
if offset > 0 {
query += " OFFSET ?"
args = append(args, offset)
}
rows, err := db.Query(query, args...)
if err != nil {
return nil, fmt.Errorf("getting albums: %v", err)
}
defer rows.Close()
var albums []*album
for rows.Next() {
var a album
dest := []any{
&a.id,
&a.artist,
&a.title,
&a.released,
&a.length,
}
if err := rows.Scan(dest...); err != nil {
return nil, fmt.Errorf("getting albums, scanning row: %w", err)
}
albums = append(albums, &a)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("getting albums, scan: %w", err)
}
return albums, nil
}
var updateAlbum = `
UPDATE [albums]
SET
[artist] = ?,
[title] = ?,
[released] = ?,
[length] = ?
WHERE [id] = ?
`
func editAlbum(db *sql.DB, id int, a *album) error {
args := []any{
&a.artist,
&a.title,
&a.released,
&a.length,
id,
}
if _, err := db.Exec(updateAlbum, args...); err != nil {
return fmt.Errorf("updating album: %v", err)
}
return nil
}
var deleteAlbum_ = `DELETE FROM [albums] WHERE [id] = ?`
func deleteAlbum(db *sql.DB, id int) error {
if _, err := db.Exec(deleteAlbum_, id); err != nil {
return fmt.Errorf("deleting album: %v", err)
}
return nil
}
var fakeNames = []string{
"Patty O’Furniture",
"Paddy O’Furniture",
"Olive Yew",
"Aida Bugg",
"Maureen Biologist",
"Teri Dactyl",
"Peg Legge",
"Allie Grater",
"Liz Erd",
"A. Mused",
"Constance Noring",
"Lois Di Nominator",
"Minnie Van Ryder",
"Lynn O’Leeum",
"P. Ann O’Recital",
"Ray O’Sun",
"Lee A. Sun",
"Ray Sin",
"Isabelle Ringing",
"Eileen Sideways",
"Rita Book",
"Paige Turner",
"Rhoda Report",
"Augusta Wind",
"Chris Anthemum",
"Anne Teak",
"U.R. Nice",
"Anita Bath",
"Harriet Upp",
"I.M. Tired",
"I. Missy Ewe",
"Ivana B. Withew",
"Anita Letterback",
"Hope Furaletter",
"B. Homesoon",
"Bea Mine",
"Bess Twishes",
"C. Yasoon",
"Audie Yose",
"Dee End",
"Amanda Hug",
"Ben Dover",
"Eileen Dover",
"Willie Makit",
"Willie Findit",
"Skye Blue",
"Staum Clowd",
"Addie Minstra",
"Anne Ortha",
"Dave Allippa",
"Dee Zynah",
"Hugh Mannerizorsa",
"Loco Lyzayta",
"Manny Jah",
"Mark Ateer",
"Reeve Ewer",
"Tex Ryta",
"Theresa Green",
"Barry Kade",
"Stan Dupp",
"Neil Down",
"Con Trariweis",
"Don Messwidme",
"Al Annon",
"Anna Domino",
"Clyde Stale",
"Anna Logwatch",
"Anna Littlical",
"Norma Leigh Absent",
"Sly Meebuggah",
"Saul Goodmate",
"Faye Clether",
"Sarah Moanees",
"Ty Ayelloribbin",
"Hugo First",
"Percy Vere",
"Jack Aranda",
"Olive Tree",
"Fran G. Pani",
"John Quil",
"Ev R. Lasting",
"Anne Thurium",
"Cherry Blossom",
"Glad I. Oli",
"Ginger Plant",
"Del Phineum",
"Rose Bush",
"Perry Scope",
"Frank N. Stein",
"Roy L. Commishun",
"Pat Thettick",
"Percy Kewshun",
"Rod Knee",
"Hank R. Cheef",
"Bridget Theriveaquai",
"Pat N. Toffis",
"Karen Onnabit",
"Col Fays",
"Fay Daway",
"Joe V. Awl",
"Wes Yabinlatelee",
"Colin Sik",
"Greg Arias",
"Toi Story",
"Gene Eva Convenshun",
"Jen Tile",
"Simon Sais",
"Peter Owt",
"Hugh N. Cry",
"Lee Nonmi",
"Lynne Gwafranca",
"Art Decco",
"Lynne Gwistic",
"Polly Ester Undawair",
"Oscar Nommanee",
"Laura Biding",
"Laura Norda",
"Des Ignayshun",
"Mike Rowe-Soft",
"Anne T. Kwayted",
"Wayde N. Thabalanz",
"Dee Mandingboss",
"Sly Meedentalfloss",
"Stanley Knife",
"Wynn Dozeaplikayshun",
"Mal Ajusted",
"Penny Black",
"Mal Nurrisht",
"Polly Pipe",
"Polly Wannakrakouer",
"Con Staninterupshuns",
"Fran Tick",
"Santi Argo",
"Carmen Goh",
"Carmen Sayid",
"Norma Stitts",
"Ester La Vista",
"Manuel Labor",
"Ivan Itchinos",
"Ivan Notheridiya",
"Mustafa Leek",
"Emma Grate",
"Annie Versaree",
"Tim Midsaylesman",
"Mary Krismass",
"Tim “Buck” Too",
"Lana Lynne Creem",
"Wiley Waites",
"Ty R. Leeva",
"Ed U. Cayshun",
"Anne T. Dote",
"Claude Strophobia",
"Anne Gloindian",
"Dulcie Veeta",
"Abby Normal",
}
var alphabet = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
func uid() string {
b := make([]rune, 16)
for i := range b {
b[i] = alphabet[rand.Intn(len(alphabet))]
}
return string(b)
}