github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/depends/kit/sqlx/builder/builder_expr.go (about) 1 package builder 2 3 import ( 4 "bytes" 5 "context" 6 "database/sql/driver" 7 "fmt" 8 "reflect" 9 "strings" 10 11 "github.com/machinefi/w3bstream/pkg/depends/x/reflectx" 12 ) 13 14 type SqlExpr interface { 15 IsNil() bool 16 Ex(ctx context.Context) *Ex 17 } 18 19 func IsNilExpr(e SqlExpr) bool { return e == nil || e.IsNil() } 20 21 func Expr(query string, args ...interface{}) *Ex { 22 if query != "" { 23 return &Ex{b: *bytes.NewBufferString(query), args: args} 24 } 25 return &Ex{args: args} 26 } 27 28 func ExprBy(build func(context.Context) *Ex) SqlExpr { 29 return &by{build: build} 30 } 31 32 func ExactlyExpr(query string, args ...interface{}) *Ex { 33 if query != "" { 34 return &Ex{b: *(bytes.NewBufferString(query)), args: args, exactly: true} 35 } 36 return &Ex{args: args, exactly: true} 37 } 38 39 type ValueExpr interface { 40 ValueEx() string 41 } 42 43 type Ex struct { 44 b bytes.Buffer 45 args []interface{} 46 err error 47 exactly bool 48 } 49 50 func (e *Ex) IsNil() bool { return e == nil || e.b.Len() == 0 } 51 52 func (e *Ex) Query() string { 53 if e == nil { 54 return "" 55 } 56 return e.b.String() 57 } 58 59 func (e *Ex) Args() []interface{} { 60 if e == nil || len(e.args) == 0 { 61 return nil 62 } 63 return e.args 64 } 65 66 func (e *Ex) Err() error { return e.err } 67 68 func (e *Ex) AppendArgs(args ...interface{}) { e.args = append(e.args, args...) } 69 70 func (e *Ex) ArgsLen() int { return len(e.args) } 71 72 func (e *Ex) SetExactly(exactly bool) { e.exactly = exactly } 73 74 func (e *Ex) Grow(n int) { 75 if n > 0 && cap(e.args)-len(e.args) < n { 76 args := make([]interface{}, len(e.args), 2*cap(e.args)+n) 77 copy(args, e.args) 78 e.args = args 79 } 80 } 81 82 func (e *Ex) WriteExpr(expr SqlExpr) { 83 if !IsNilExpr(expr) { 84 e.WriteHolder(0) 85 e.AppendArgs(expr) 86 } 87 } 88 89 func (e *Ex) WriteHolder(idx int) { 90 if idx > 0 { 91 e.b.WriteByte(',') 92 } 93 e.b.WriteByte('?') 94 } 95 96 func (e *Ex) WriteQuery(query string) { _, _ = e.b.WriteString(query) } 97 98 func (e *Ex) WriteQueryByte(b byte) { _ = e.b.WriteByte(b) } 99 100 func (e *Ex) WriteQueryRune(r rune) { _, _ = e.b.WriteRune(r) } 101 102 func (e *Ex) WriteGroup(f func(e *Ex)) { 103 e.WriteQueryByte('(') 104 f(e) 105 e.WriteQueryByte(')') 106 } 107 108 func (e *Ex) WriteComments(comments []byte) { 109 e.WriteQuery("/* ") 110 _, _ = e.b.Write(comments) 111 e.WriteQuery(" */") 112 } 113 114 func (e *Ex) WriteEnd() { e.WriteQueryByte(';') } 115 116 func (e *Ex) Ex(ctx context.Context) *Ex { 117 if e.IsNil() { 118 return nil 119 } 120 args, argc := e.args, len(e.args) 121 122 er := Expr("") 123 er.Grow(argc) 124 125 query := e.Query() 126 if e.exactly { 127 er.WriteQuery(query) 128 er.AppendArgs(args...) 129 er.exactly = true 130 return er 131 } 132 133 if shouldResolve := preprocessArgs(args); !shouldResolve { 134 er.WriteQuery(query) 135 er.AppendArgs(args...) 136 er.SetExactly(true) 137 return er 138 } 139 140 qc := 0 141 for i := range query { 142 switch c := query[i]; c { 143 default: 144 er.WriteQueryByte(c) 145 case '?': 146 if qc >= argc { 147 panic(fmt.Errorf("missing arg %d of %s", qc, query)) 148 } 149 switch arg := args[qc].(type) { 150 case SqlExpr: 151 if !IsNilExpr(arg) { 152 sub := arg.Ex(ctx) 153 if sub != er && !IsNilExpr(sub) { 154 er.WriteQuery(sub.Query()) 155 er.AppendArgs(sub.Args()...) 156 } 157 } 158 default: 159 er.WriteHolder(0) 160 er.AppendArgs(arg) 161 } 162 qc++ 163 } 164 } 165 er.SetExactly(true) 166 return er 167 } 168 169 func preprocessArgs(args []interface{}) bool { 170 shouldResolve := false 171 172 sliceArgEx := func(vs []interface{}) *Ex { 173 if n := len(vs); n > 0 { 174 return ExactlyExpr(strings.Repeat(",?", n)[1:], vs...) 175 } 176 return ExactlyExpr("") 177 } 178 179 for i := range args { 180 switch arg := args[i].(type) { 181 case ValueExpr: 182 args[i] = ExactlyExpr(arg.ValueEx(), arg) 183 shouldResolve = true 184 case SqlExpr: 185 shouldResolve = true 186 case driver.Valuer: 187 case []interface{}: 188 args[i] = sliceArgEx(arg) 189 shouldResolve = true 190 default: 191 if t := reflect.TypeOf(arg); t.Kind() == reflect.Slice { 192 if !reflectx.IsBytes(arg) { 193 args[i] = sliceArgEx(toInterfaceSlice(arg)) 194 shouldResolve = true 195 } 196 } 197 } 198 } 199 return shouldResolve 200 } 201 202 func toInterfaceSlice(v interface{}) []interface{} { 203 switch x := (v).(type) { 204 case []bool: 205 values := make([]interface{}, len(x)) 206 for i := range values { 207 values[i] = x[i] 208 } 209 return values 210 case []string: 211 values := make([]interface{}, len(x)) 212 for i := range values { 213 values[i] = x[i] 214 } 215 return values 216 case []float32: 217 values := make([]interface{}, len(x)) 218 for i := range values { 219 values[i] = x[i] 220 } 221 return values 222 case []float64: 223 values := make([]interface{}, len(x)) 224 for i := range values { 225 values[i] = x[i] 226 } 227 return values 228 case []int: 229 values := make([]interface{}, len(x)) 230 for i := range values { 231 values[i] = x[i] 232 } 233 return values 234 case []int8: 235 values := make([]interface{}, len(x)) 236 for i := range values { 237 values[i] = x[i] 238 } 239 return values 240 case []int16: 241 values := make([]interface{}, len(x)) 242 for i := range values { 243 values[i] = x[i] 244 } 245 return values 246 case []int32: 247 values := make([]interface{}, len(x)) 248 for i := range values { 249 values[i] = x[i] 250 } 251 return values 252 case []int64: 253 values := make([]interface{}, len(x)) 254 for i := range values { 255 values[i] = x[i] 256 } 257 return values 258 case []uint: 259 values := make([]interface{}, len(x)) 260 for i := range values { 261 values[i] = x[i] 262 } 263 return values 264 case []uint8: 265 values := make([]interface{}, len(x)) 266 for i := range values { 267 values[i] = x[i] 268 } 269 return values 270 case []uint16: 271 values := make([]interface{}, len(x)) 272 for i := range values { 273 values[i] = x[i] 274 } 275 return values 276 case []uint32: 277 values := make([]interface{}, len(x)) 278 for i := range values { 279 values[i] = x[i] 280 } 281 return values 282 case []uint64: 283 values := make([]interface{}, len(x)) 284 for i := range values { 285 values[i] = x[i] 286 } 287 return values 288 case []interface{}: 289 return x 290 } 291 sliceRv := reflect.ValueOf(v) 292 values := make([]interface{}, sliceRv.Len()) 293 for i := range values { 294 values[i] = sliceRv.Index(i).Interface() 295 } 296 return values 297 } 298 299 func Multi(es ...SqlExpr) SqlExpr { 300 return MultiWith(" ", es...) 301 } 302 303 func MultiWith(connector string, es ...SqlExpr) SqlExpr { 304 return ExprBy(func(ctx context.Context) *Ex { 305 e := Expr("") 306 e.Grow(len(es)) 307 for i := range es { 308 if i != 0 { 309 e.WriteQuery(connector) 310 } 311 e.WriteExpr(es[i]) 312 } 313 return e.Ex(ctx) 314 }) 315 } 316 317 func ResolveExpr(v interface{}) *Ex { 318 return ResolveExprContext(context.Background(), v) 319 } 320 321 func ResolveExprContext(ctx context.Context, v interface{}) *Ex { 322 switch e := v.(type) { 323 case nil: 324 return nil 325 case SqlExpr: 326 if IsNilExpr(e) { 327 return nil 328 } 329 return e.Ex(ctx) 330 } 331 return nil 332 }