Skip to content

Commit acb856c

Browse files
vm-001webhookx-x
authored andcommitted
perf(dao): cache columns
1 parent a3e2a46 commit acb856c

File tree

2 files changed

+59
-57
lines changed

2 files changed

+59
-57
lines changed

db/dao/dao.go

Lines changed: 27 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ type DAO[T any] struct {
4545

4646
workspace bool
4747
opts Options
48+
columns []string
4849
}
4950

5051
type Options struct {
@@ -63,6 +64,12 @@ func NewDAO[T any](db *sqlx.DB, bus *eventbus.EventBus, opts Options) *DAO[T] {
6364
workspace: opts.Workspace,
6465
opts: opts,
6566
}
67+
EachField(new(T), func(f reflect.StructField, _ reflect.Value, column string) {
68+
if column == "created_at" || column == "updated_at" {
69+
return
70+
}
71+
dao.columns = append(dao.columns, column)
72+
})
6673
return &dao
6774
}
6875

@@ -213,46 +220,22 @@ func (dao *DAO[T]) List(ctx context.Context, q query.Queryer) (list []*T, err er
213220
return
214221
}
215222

216-
func travel(entity interface{}, fn func(field reflect.StructField, value reflect.Value)) {
217-
t := reflect.TypeOf(entity)
218-
if t.Kind() == reflect.Ptr {
219-
t = t.Elem()
220-
}
221-
v := reflect.ValueOf(entity)
222-
if v.Kind() == reflect.Ptr {
223-
v = v.Elem()
224-
}
225-
for i := 0; i < t.NumField(); i++ {
226-
field := t.Field(i)
227-
value := v.Field(i)
228-
if field.Anonymous {
229-
travel(value.Interface(), fn)
230-
} else {
231-
fn(field, value)
232-
}
233-
}
234-
}
235-
236223
func (dao *DAO[T]) Insert(ctx context.Context, entity *T) error {
237224
ctx, span := tracing.Start(ctx, fmt.Sprintf("dao.%s.insert", dao.opts.Table), trace.WithSpanKind(trace.SpanKindServer))
238225
defer span.End()
239226

240-
columns := make([]string, 0)
241227
values := make([]interface{}, 0)
242-
travel(entity, func(f reflect.StructField, v reflect.Value) {
243-
column := utils.DefaultIfZero(f.Tag.Get("db"), strings.ToLower(f.Name))
244-
switch column {
245-
case "created_at", "updated_at": // ignore
246-
default:
247-
columns = append(columns, column)
248-
value := v.Interface()
249-
if column == "ws_id" && dao.workspace {
250-
value = ucontext.GetWorkspaceID(ctx)
251-
}
252-
values = append(values, value)
228+
EachField(entity, func(f reflect.StructField, v reflect.Value, column string) {
229+
if column == "created_at" || column == "updated_at" {
230+
return
231+
}
232+
value := v.Interface()
233+
if column == "ws_id" && dao.workspace {
234+
value = ucontext.GetWorkspaceID(ctx)
253235
}
236+
values = append(values, value)
254237
})
255-
statement, args := psql.Insert(dao.opts.Table).Columns(columns...).Values(values...).
238+
statement, args := psql.Insert(dao.opts.Table).Columns(dao.columns...).Values(values...).
256239
Suffix("RETURNING *").
257240
MustSql()
258241
dao.debugSQL(statement, args)
@@ -274,30 +257,19 @@ func (dao *DAO[T]) BatchInsert(ctx context.Context, entities []*T) error {
274257
return nil
275258
}
276259

277-
builder := psql.Insert(dao.opts.Table)
278-
travel(entities[0], func(f reflect.StructField, v reflect.Value) {
279-
column := utils.DefaultIfZero(f.Tag.Get("db"), strings.ToLower(f.Name))
280-
switch column {
281-
case "created_at", "updated_at": // ignore
282-
default:
283-
builder = builder.Columns(column)
284-
}
285-
})
260+
builder := psql.Insert(dao.opts.Table).Columns(dao.columns...)
286261

287262
for _, entity := range entities {
288263
values := make([]interface{}, 0)
289-
travel(entity, func(f reflect.StructField, v reflect.Value) {
290-
column := utils.DefaultIfZero(f.Tag.Get("db"), strings.ToLower(f.Name))
291-
switch column {
292-
case "created_at", "updated_at":
293-
// ignore
294-
default:
295-
value := v.Interface()
296-
if column == "ws_id" && dao.workspace {
297-
value = ucontext.GetWorkspaceID(ctx)
298-
}
299-
values = append(values, value)
264+
EachField(entity, func(f reflect.StructField, v reflect.Value, column string) {
265+
if column == "created_at" || column == "updated_at" {
266+
return
300267
}
268+
value := v.Interface()
269+
if column == "ws_id" && dao.workspace {
270+
value = ucontext.GetWorkspaceID(ctx)
271+
}
272+
values = append(values, value)
301273
})
302274
builder = builder.Values(values...)
303275
}
@@ -340,8 +312,7 @@ func (dao *DAO[T]) Update(ctx context.Context, entity *T) error {
340312

341313
var id string
342314
builder := psql.Update(dao.opts.Table)
343-
travel(entity, func(f reflect.StructField, v reflect.Value) {
344-
column := utils.DefaultIfZero(f.Tag.Get("db"), strings.ToLower(f.Name))
315+
EachField(entity, func(f reflect.StructField, v reflect.Value, column string) {
345316
switch column {
346317
case "id":
347318
id = v.Interface().(string)
@@ -369,8 +340,7 @@ func (dao *DAO[T]) Upsert(ctx context.Context, fields []string, entity *T) error
369340
now := time.Now()
370341
columns := make([]string, 0)
371342
values := make([]interface{}, 0)
372-
travel(entity, func(f reflect.StructField, v reflect.Value) {
373-
column := utils.DefaultIfZero(f.Tag.Get("db"), strings.ToLower(f.Name))
343+
EachField(entity, func(f reflect.StructField, v reflect.Value, column string) {
374344
switch column {
375345
case "created_at", "updated_at":
376346
columns = append(columns, column)

db/dao/utils.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package dao
2+
3+
import (
4+
"github.com/webhookx-io/webhookx/utils"
5+
"reflect"
6+
"strings"
7+
)
8+
9+
// EachField traverse each database field
10+
func EachField(entity interface{}, fn func(field reflect.StructField, value reflect.Value, column string)) {
11+
t := reflect.TypeOf(entity)
12+
if t.Kind() == reflect.Ptr {
13+
t = t.Elem()
14+
}
15+
v := reflect.ValueOf(entity)
16+
if v.Kind() == reflect.Ptr {
17+
v = v.Elem()
18+
}
19+
for i := 0; i < t.NumField(); i++ {
20+
field := t.Field(i)
21+
value := v.Field(i)
22+
column := utils.DefaultIfZero(field.Tag.Get("db"), strings.ToLower(field.Name))
23+
if column == "-" {
24+
continue
25+
}
26+
if field.Anonymous {
27+
EachField(value.Interface(), fn)
28+
} else {
29+
fn(field, value, column)
30+
}
31+
}
32+
}

0 commit comments

Comments
 (0)