github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/sqx/daoopt.go (about) 1 package sqx 2 3 import ( 4 "context" 5 "database/sql" 6 "fmt" 7 "reflect" 8 9 "github.com/bingoohuang/gg/pkg/defaults" 10 "github.com/bingoohuang/gg/pkg/reflector" 11 ) 12 13 // CreateDaoOpt defines the options for CreateDao. 14 type CreateDaoOpt struct { 15 Error *error 16 Ctx context.Context 17 QueryMaxRows int `default:"-1"` 18 RowScanInterceptor RowScanInterceptor 19 DotSQL func(name string) (SQLPart, error) 20 Logger DaoLogger 21 ErrSetter func(err error) 22 DBGetter DBGetter 23 } 24 25 // CreateDaoOpter defines the option pattern interface for CreateDaoOpt. 26 type CreateDaoOpter interface { 27 ApplyCreateOpt(*CreateDaoOpt) 28 } 29 30 // CreateDaoOptFn defines the func prototype to option applying. 31 type CreateDaoOptFn func(*CreateDaoOpt) 32 33 // ApplyCreateOpt applies the option. 34 func (c CreateDaoOptFn) ApplyCreateOpt(opt *CreateDaoOpt) { c(opt) } 35 36 // WithError specifies the err pointer to receive error. 37 func WithError(err *error) CreateDaoOpter { 38 return CreateDaoOptFn(func(opt *CreateDaoOpt) { opt.Error = err }) 39 } 40 41 // WithCtx specifies the context.Context to sdb execution processes. 42 func WithCtx(ctx context.Context) CreateDaoOpter { 43 return CreateDaoOptFn(func(opt *CreateDaoOpt) { opt.Ctx = ctx }) 44 } 45 46 // WithLimit specifies the max rows to be fetched when execute query. 47 func WithLimit(maxRows int) CreateDaoOpter { 48 return CreateDaoOptFn(func(opt *CreateDaoOpt) { opt.QueryMaxRows = maxRows }) 49 } 50 51 // WithSQLFile imports SQL queries from the file. 52 func WithSQLFile(sqlFile string) CreateDaoOpter { 53 return CreateDaoOptFn(func(opt *CreateDaoOpt) { 54 ds, err := DotSQLLoadFile(sqlFile) 55 if err != nil { 56 panic(err) 57 } 58 59 opt.DotSQL = ds.Raw 60 }) 61 } 62 63 // WithDB imports a db. 64 func WithDB(db *sql.DB) CreateDaoOpter { 65 return CreateDaoOptFn(func(opt *CreateDaoOpt) { opt.DBGetter = &StdDB{db: db} }) 66 } 67 68 // WithSQLStr imports SQL queries from the string. 69 func WithSQLStr(s string) CreateDaoOpter { 70 return CreateDaoOptFn(func(opt *CreateDaoOpt) { 71 ds, err := DotSQLLoadString(s) 72 if err != nil { 73 panic(err) 74 } 75 76 opt.DotSQL = ds.Raw 77 }) 78 } 79 80 // WithRowScanInterceptor specifies the RowScanInterceptor after a row fetched. 81 func WithRowScanInterceptor(interceptor RowScanInterceptor) CreateDaoOpter { 82 return CreateDaoOptFn(func(opt *CreateDaoOpt) { opt.RowScanInterceptor = interceptor }) 83 } 84 85 // RowScanInterceptor defines the interceptor after a row scanning. 86 type RowScanInterceptor interface { 87 After(rowIndex int, v ...interface{}) (bool, error) 88 } 89 90 // RowScanInterceptorFn defines the interceptor function after a row scanning. 91 type RowScanInterceptorFn func(rowIndex int, v ...interface{}) (bool, error) 92 93 // After is revoked after a row scanning. 94 func (r RowScanInterceptorFn) After(rowIndex int, v ...interface{}) (bool, error) { 95 return r(rowIndex, v...) 96 } 97 98 func applyCreateDaoOption(createDaoOpts []CreateDaoOpter) (*CreateDaoOpt, error) { 99 opt := &CreateDaoOpt{} 100 if err := defaults.Set(opt); err != nil { 101 return nil, fmt.Errorf("failed to set defaults for CreateDaoOpt error %w", err) 102 } 103 104 for _, v := range createDaoOpts { 105 v.ApplyCreateOpt(opt) 106 } 107 108 if opt.Ctx == nil { 109 opt.Ctx = context.Background() 110 } 111 112 if opt.DotSQL == nil { 113 opt.DotSQL = func(string) (SQLPart, error) { return nil, nil } 114 } 115 116 return opt, nil 117 } 118 119 func createErrorSetter(v reflect.Value, option *CreateDaoOpt) { 120 for i := 0; i < v.NumField(); i++ { 121 fv := v.Field(i) 122 f := v.Type().Field(i) 123 124 if f.PkgPath != "" /* not exportable? */ { 125 continue 126 } 127 128 if !reflector.IsError(f.Type) { 129 continue 130 } 131 132 option.ErrSetter = func(err error) { 133 if option.Error != nil { 134 *option.Error = err 135 } 136 137 if fv.IsNil() && err == nil { 138 return 139 } 140 141 if err == nil { 142 fv.Set(reflect.Zero(f.Type)) 143 } else { 144 fv.Set(reflect.ValueOf(err)) 145 } 146 } 147 148 return 149 } 150 151 option.ErrSetter = func(err error) { 152 if option.Error != nil { 153 *option.Error = err 154 } 155 } 156 }