Skip to content

Commit 0bbefd7

Browse files
committed
fix: repo query builder
1 parent e70184a commit 0bbefd7

File tree

2 files changed

+153
-6
lines changed

2 files changed

+153
-6
lines changed

pkg/repo/repo.go

+7-6
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,13 @@ func Update(tableName string, fields []string, where ...string) string {
7979
setFields[i] = fmt.Sprintf("%s = $%d", field, i+1)
8080
}
8181

82-
return fmt.Sprintf(
83-
"UPDATE %s SET %s %s",
84-
tableName,
85-
strings.Join(setFields, ", "),
86-
strings.Join(where, " AND "),
87-
)
82+
q := fmt.Sprintf("UPDATE %s SET %s", tableName, strings.Join(setFields, ", "))
83+
84+
if len(where) > 0 {
85+
q += " " + JoinWhere(where...)
86+
}
87+
88+
return q
8889
}
8990

9091
// BatchInsertQueryN creates a parameterized SQL query for batch inserting multiple values per row

pkg/repo/repo_test.go

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
package repo
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
func TestInsert(t *testing.T) {
10+
tests := []struct {
11+
name string
12+
tableName string
13+
fields []string
14+
returning []string
15+
want string
16+
}{
17+
{
18+
name: "basic insert",
19+
tableName: "users",
20+
fields: []string{"name", "email", "password"},
21+
returning: []string{"id", "created_at"},
22+
want: "INSERT INTO users (name, email, password) VALUES ($1, $2, $3) RETURNING id, created_at",
23+
},
24+
{
25+
name: "single field",
26+
tableName: "status",
27+
fields: []string{"value"},
28+
returning: []string{"id"},
29+
want: "INSERT INTO status (value) VALUES ($1) RETURNING id",
30+
},
31+
{
32+
name: "with schema",
33+
tableName: "public.products",
34+
fields: []string{"name", "price", "category_id"},
35+
returning: []string{"id", "created_at", "updated_at"},
36+
want: "INSERT INTO public.products (name, price, category_id) VALUES ($1, $2, $3) RETURNING id, created_at, updated_at",
37+
},
38+
}
39+
40+
for _, tt := range tests {
41+
t.Run(tt.name, func(t *testing.T) {
42+
got := Insert(tt.tableName, tt.fields, tt.returning...)
43+
assert.Equal(t, tt.want, got)
44+
})
45+
}
46+
}
47+
48+
func TestUpdate(t *testing.T) {
49+
tests := []struct {
50+
name string
51+
tableName string
52+
fields []string
53+
where []string
54+
want string
55+
}{
56+
{
57+
name: "basic update",
58+
tableName: "users",
59+
fields: []string{"name", "email"},
60+
where: []string{"id = $3"},
61+
want: "UPDATE users SET name = $1, email = $2 WHERE id = $3",
62+
},
63+
{
64+
name: "single field",
65+
tableName: "status",
66+
fields: []string{"value"},
67+
where: []string{"id = $2"},
68+
want: "UPDATE status SET value = $1 WHERE id = $2",
69+
},
70+
{
71+
name: "multiple conditions",
72+
tableName: "products",
73+
fields: []string{"name", "price", "updated_at"},
74+
where: []string{"id = $4", "category_id = $5"},
75+
want: "UPDATE products SET name = $1, price = $2, updated_at = $3 WHERE id = $4 AND category_id = $5",
76+
},
77+
{
78+
name: "with schema",
79+
tableName: "public.orders",
80+
fields: []string{"status", "updated_at"},
81+
where: []string{"id = $3"},
82+
want: "UPDATE public.orders SET status = $1, updated_at = $2 WHERE id = $3",
83+
},
84+
{
85+
name: "no conditions",
86+
tableName: "settings",
87+
fields: []string{"value", "updated_at"},
88+
where: []string{},
89+
want: "UPDATE settings SET value = $1, updated_at = $2",
90+
},
91+
}
92+
93+
for _, tt := range tests {
94+
t.Run(tt.name, func(t *testing.T) {
95+
got := Update(tt.tableName, tt.fields, tt.where...)
96+
assert.Equal(t, tt.want, got)
97+
})
98+
}
99+
}
100+
101+
func TestBatchInsertQueryN(t *testing.T) {
102+
tests := []struct {
103+
name string
104+
baseQuery string
105+
rows [][]interface{}
106+
wantQuery string
107+
wantArgs []interface{}
108+
}{
109+
{
110+
name: "empty rows",
111+
baseQuery: "INSERT INTO users (name, email) VALUES",
112+
rows: [][]interface{}{},
113+
wantQuery: "INSERT INTO users (name, email) VALUES",
114+
wantArgs: nil,
115+
},
116+
{
117+
name: "single row",
118+
baseQuery: "INSERT INTO users (name, email) VALUES",
119+
rows: [][]interface{}{
120+
{"John", "[email protected]"},
121+
},
122+
wantQuery: "INSERT INTO users (name, email) VALUES ($1,$2)",
123+
wantArgs: []interface{}{"John", "[email protected]"},
124+
},
125+
{
126+
name: "multiple rows",
127+
baseQuery: "INSERT INTO users (name, email) VALUES",
128+
rows: [][]interface{}{
129+
{"John", "[email protected]"},
130+
{"Jane", "[email protected]"},
131+
{"Bob", "[email protected]"},
132+
},
133+
wantQuery: "INSERT INTO users (name, email) VALUES ($1,$2),($3,$4),($5,$6)",
134+
wantArgs: []interface{}{"John", "[email protected]", "Jane", "[email protected]", "Bob", "[email protected]"},
135+
},
136+
}
137+
138+
for _, tt := range tests {
139+
t.Run(tt.name, func(t *testing.T) {
140+
gotQuery, gotArgs := BatchInsertQueryN(tt.baseQuery, tt.rows)
141+
assert.Equal(t, tt.wantQuery, gotQuery)
142+
assert.Equal(t, tt.wantArgs, gotArgs)
143+
})
144+
}
145+
}
146+

0 commit comments

Comments
 (0)