@@ -45,6 +45,7 @@ type DAO[T any] struct {
4545
4646 workspace bool
4747 opts Options
48+ columns []string
4849}
4950
5051type 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-
236223func (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 )
0 commit comments