-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpost.go
More file actions
109 lines (91 loc) · 2.42 KB
/
post.go
File metadata and controls
109 lines (91 loc) · 2.42 KB
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
package main
import (
"context"
"database/sql"
"time"
"github.com/andrewpillar/database"
"github.com/andrewpillar/database/query"
)
const PostSchema = `CREATE TABLE IF NOT EXISTS posts (
id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
title VARCHAR NOT NULL,
content TEXT NOT NULL,
created_at TIMESTAMP NOT NULL,
updated_at TIMESTAMP NULL,
PRIMARY KEY (id),
FOREIGN KEY (user_id) REFERENCES users(id)
);
CREATE TABLE IF NOT EXISTS post_tags (
post_id VARCHAR NOT NULL,
name VARCHAR NOT NULL,
PRIMARY KEY (post_id, name)
);`
type Post struct {
ID int64
User *User `db:"user_id:id,users.*:*"`
Title string
Content string
CreatedAt time.Time `db:"created_at"`
UpdatedAt sql.Null[time.Time] `db:"updated_at"`
Tags []string `db:"-"`
}
func (p *Post) Table() string { return "posts" }
func (p *Post) PrimaryKey() *database.PrimaryKey {
return &database.PrimaryKey{
Columns: []string{"id"},
Values: []any{p.ID},
}
}
func (p *Post) Params() database.Params {
return database.Params{
"id": database.CreateOnlyParam(p.ID),
"user_id": database.CreateOnlyParam(p.User.ID),
"title": database.CreateOnlyParam(p.Title),
"content": database.MutableParam(p.Content),
"created_at": database.CreateOnlyParam(p.CreatedAt),
"updated_at": database.UpdateOnlyParam(p.UpdatedAt),
}
}
func LoadTags(ctx context.Context, db *sql.DB, pp []*Post) error {
// Table to look up the post's position in the given slice. The key is the
// post's ID.
tab := make(map[int64]int)
for i, p := range pp {
tab[p.ID] = i
}
q := query.Select(
query.Columns("post_id", "name"),
query.From("post_tags"),
query.WhereIn("post_id", database.List("id", pp...)),
)
rows, err := db.QueryContext(ctx, q.Build(), q.Args()...)
if err != nil {
return err
}
defer rows.Close()
var (
postId int64
tag string
)
for rows.Next() {
if err := rows.Scan(&postId, &tag); err != nil {
return err
}
if pos, ok := tab[postId]; ok {
pp[pos].Tags = append(pp[pos].Tags, tag)
}
}
return nil
}
func WhereTag(tag string) query.Option {
return func(q *query.Query) *query.Query {
// We specify the column as "posts.id" because of its use in a JOIN
// column names will end up being ambiguous.
return query.WhereIn("posts.id", query.Select(
query.Columns("post_id"),
query.From("post_tags"),
query.WhereEq("name", query.Arg(tag)),
))(q)
}
}