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  }