github.com/Ali-iotechsys/sqlboiler/v4@v4.0.0-20221208124957-6aec9a5f1f71/queries/reflect.go (about)

     1  package queries
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"database/sql"
     7  	"database/sql/driver"
     8  	"fmt"
     9  	"reflect"
    10  	"strconv"
    11  	"strings"
    12  	"sync"
    13  	"time"
    14  	"unicode"
    15  
    16  	"github.com/friendsofgo/errors"
    17  	"github.com/volatiletech/sqlboiler/v4/boil"
    18  	"github.com/volatiletech/strmangle"
    19  )
    20  
    21  // Identifies what kind of object we're binding to
    22  type bindKind int
    23  
    24  const (
    25  	kindStruct bindKind = iota
    26  	kindSliceStruct
    27  	kindPtrSliceStruct
    28  )
    29  
    30  const (
    31  	loadMethodPrefix       = "Load"
    32  	relationshipStructName = "R"
    33  	loaderStructName       = "L"
    34  	sentinel               = uint64(255)
    35  )
    36  
    37  // BindP executes the query and inserts the
    38  // result into the passed in object pointer.
    39  // It panics on error.
    40  // Also see documentation for Bind() and Query.Bind()
    41  func (q *Query) BindP(ctx context.Context, exec boil.Executor, obj interface{}) {
    42  	if err := q.Bind(ctx, exec, obj); err != nil {
    43  		panic(boil.WrapErr(err))
    44  	}
    45  }
    46  
    47  // BindG executes the query and inserts
    48  // the result into the passed in object pointer.
    49  // It uses the global executor.
    50  // Also see documentation for Bind() and Query.Bind()
    51  func (q *Query) BindG(ctx context.Context, obj interface{}) error {
    52  	return q.Bind(ctx, boil.GetDB(), obj)
    53  }
    54  
    55  // Bind inserts the rows into the passed in object pointer, because the caller
    56  // owns the rows it is imperative to note that the caller MUST both close the
    57  // rows and check for errors on the rows.
    58  //
    59  // If you neglect closing the rows your application may have a memory leak
    60  // if the rows are not implicitly closed by iteration alone.
    61  // If you neglect checking the rows.Err silent failures may occur in your
    62  // application.
    63  //
    64  // Valid types to bind to are: *Struct, []*Struct, and []Struct. Keep in mind
    65  // if you use []Struct that Bind will be doing copy-by-value as a method
    66  // of keeping heap memory usage low which means if your Struct contains
    67  // reference types/pointers you will see incorrect results, do not use
    68  // []Struct with a Struct with reference types.
    69  //
    70  // Bind rules:
    71  //   - Struct tags control bind, in the form of: `boil:"name,bind"`
    72  //   - If "name" is omitted the sql column names that come back are TitleCased
    73  //     and matched against the field name.
    74  //   - If the "name" part of the struct tag is specified, the given name will
    75  //     be used instead of the struct field name for binding.
    76  //   - If the "name" of the struct tag is "-", this field will not be bound to.
    77  //   - If the ",bind" option is specified on a struct field and that field
    78  //     is a struct itself, it will be recursed into to look for fields for
    79  //     binding.
    80  //   - If one or more boil struct tags are duplicated and there are multiple
    81  //     matching columns for those tags the behaviour of Bind will be undefined
    82  //     for those fields with duplicated struct tags.
    83  //
    84  // Example usage:
    85  //
    86  //   type JoinStruct struct {
    87  //     // User1 can have it's struct fields bound to since it specifies
    88  //     // ,bind in the struct tag, it will look specifically for
    89  //     // fields that are prefixed with "user." returning from the query.
    90  //     // For example "user.id" column name will bind to User1.ID
    91  //     User1      *models.User `boil:"user,bind"`
    92  //     // User2 will follow the same rules as noted above except it will use
    93  //     // "friend." as the prefix it's looking for.
    94  //     User2      *models.User `boil:"friend,bind"`
    95  //     // RandomData will not be recursed into to look for fields to
    96  //     // bind and will not be bound to because of the - for the name.
    97  //     RandomData myStruct     `boil:"-"`
    98  //     // Date will not be recursed into to look for fields to bind because
    99  //     // it does not specify ,bind in the struct tag. But it can be bound to
   100  //     // as it does not specify a - for the name.
   101  //     Date       time.Time
   102  //   }
   103  //
   104  //   models.Users(
   105  //     qm.InnerJoin("users as friend on users.friend_id = friend.id")
   106  //   ).Bind(&joinStruct)
   107  //
   108  // For custom objects that want to use eager loading, please see the
   109  // loadRelationships function.
   110  func Bind(rows *sql.Rows, obj interface{}) error {
   111  	structType, sliceType, singular, err := bindChecks(obj)
   112  	if err != nil {
   113  		return err
   114  	}
   115  
   116  	return bind(rows, obj, structType, sliceType, singular)
   117  }
   118  
   119  // Bind executes the query and inserts the
   120  // result into the passed in object pointer.
   121  //
   122  // If Context is non-nil it will upgrade the
   123  // Executor to a ContextExecutor and query with the passed context.
   124  // If Context is non-nil, any eager loading that's done must also
   125  // be using load* methods that support context as the first parameter.
   126  //
   127  // Also see documentation for Bind()
   128  func (q *Query) Bind(ctx context.Context, exec boil.Executor, obj interface{}) error {
   129  	structType, sliceType, bkind, err := bindChecks(obj)
   130  	if err != nil {
   131  		return err
   132  	}
   133  
   134  	var rows *sql.Rows
   135  	if ctx != nil {
   136  		rows, err = q.QueryContext(ctx, exec.(boil.ContextExecutor))
   137  	} else {
   138  		rows, err = q.Query(exec)
   139  	}
   140  	if err != nil {
   141  		return errors.Wrap(err, "bind failed to execute query")
   142  	}
   143  	if err = bind(rows, obj, structType, sliceType, bkind); err != nil {
   144  		if innerErr := rows.Close(); innerErr != nil {
   145  			return errors.Wrapf(err, "error on rows.Close after bind error: %+v", innerErr)
   146  		}
   147  
   148  		return err
   149  	}
   150  	if err = rows.Close(); err != nil {
   151  		return errors.Wrap(err, "failed to clean up rows in bind")
   152  	}
   153  	if err = rows.Err(); err != nil {
   154  		return errors.Wrap(err, "error from rows in bind")
   155  	}
   156  
   157  	if len(q.load) != 0 {
   158  		return eagerLoad(ctx, exec, q.load, q.loadMods, obj, bkind)
   159  	}
   160  
   161  	return nil
   162  }
   163  
   164  // bindChecks resolves information about the bind target, and errors if it's not an object
   165  // we can bind to.
   166  func bindChecks(obj interface{}) (structType reflect.Type, sliceType reflect.Type, bkind bindKind, err error) {
   167  	typ := reflect.TypeOf(obj)
   168  	kind := typ.Kind()
   169  
   170  	setErr := func() {
   171  		err = errors.Errorf("obj type should be *Type, *[]Type, or *[]*Type but was %q", reflect.TypeOf(obj).String())
   172  	}
   173  
   174  	for i := 0; ; i++ {
   175  		switch i {
   176  		case 0:
   177  			if kind != reflect.Ptr {
   178  				setErr()
   179  				return
   180  			}
   181  		case 1:
   182  			switch kind {
   183  			case reflect.Struct:
   184  				structType = typ
   185  				bkind = kindStruct
   186  				return
   187  			case reflect.Slice:
   188  				sliceType = typ
   189  			default:
   190  				setErr()
   191  				return
   192  			}
   193  		case 2:
   194  			switch kind {
   195  			case reflect.Struct:
   196  				structType = typ
   197  				bkind = kindSliceStruct
   198  				return
   199  			case reflect.Ptr:
   200  			default:
   201  				setErr()
   202  				return
   203  			}
   204  		case 3:
   205  			if kind != reflect.Struct {
   206  				setErr()
   207  				return
   208  			}
   209  			structType = typ
   210  			bkind = kindPtrSliceStruct
   211  			return
   212  		}
   213  
   214  		typ = typ.Elem()
   215  		kind = typ.Kind()
   216  	}
   217  }
   218  
   219  func bind(rows *sql.Rows, obj interface{}, structType, sliceType reflect.Type, bkind bindKind) error {
   220  	cols, err := rows.Columns()
   221  	if err != nil {
   222  		return errors.Wrap(err, "bind failed to get column names")
   223  	}
   224  
   225  	var ptrSlice reflect.Value
   226  	switch bkind {
   227  	case kindSliceStruct, kindPtrSliceStruct:
   228  		ptrSlice = reflect.Indirect(reflect.ValueOf(obj))
   229  	}
   230  
   231  	mapping, err := getMappingCache(structType).mapping(cols)
   232  	if err != nil {
   233  		return err
   234  	}
   235  
   236  	var oneStruct reflect.Value
   237  	if bkind == kindSliceStruct {
   238  		oneStruct = reflect.Indirect(reflect.New(structType))
   239  	}
   240  
   241  	foundOne := false
   242  Rows:
   243  	for rows.Next() {
   244  		foundOne = true
   245  		var newStruct reflect.Value
   246  		var pointers []interface{}
   247  
   248  		switch bkind {
   249  		case kindStruct:
   250  			pointers = PtrsFromMapping(reflect.Indirect(reflect.ValueOf(obj)), mapping)
   251  		case kindSliceStruct:
   252  			pointers = PtrsFromMapping(oneStruct, mapping)
   253  		case kindPtrSliceStruct:
   254  			newStruct = reflect.New(structType)
   255  			pointers = PtrsFromMapping(reflect.Indirect(newStruct), mapping)
   256  		}
   257  		if err != nil {
   258  			return err
   259  		}
   260  
   261  		if err := rows.Scan(pointers...); err != nil {
   262  			return errors.Wrap(err, "failed to bind pointers to obj")
   263  		}
   264  
   265  		switch bkind {
   266  		case kindStruct:
   267  			break Rows
   268  		case kindSliceStruct:
   269  			ptrSlice.Set(reflect.Append(ptrSlice, oneStruct))
   270  		case kindPtrSliceStruct:
   271  			ptrSlice.Set(reflect.Append(ptrSlice, newStruct))
   272  		}
   273  	}
   274  
   275  	if bkind == kindStruct && !foundOne {
   276  		return sql.ErrNoRows
   277  	}
   278  
   279  	return nil
   280  }
   281  
   282  // BindMapping creates a mapping that helps look up the pointer for the
   283  // column given.
   284  func BindMapping(typ reflect.Type, mapping map[string]uint64, cols []string) ([]uint64, error) {
   285  	ptrs := make([]uint64, len(cols))
   286  
   287  ColLoop:
   288  	for i, c := range cols {
   289  		ptrMap, ok := mapping[c]
   290  		if ok {
   291  			ptrs[i] = ptrMap
   292  			continue
   293  		}
   294  
   295  		suffix := "." + c
   296  		for maybeMatch, mapping := range mapping {
   297  			if strings.HasSuffix(maybeMatch, suffix) {
   298  				ptrs[i] = mapping
   299  				continue ColLoop
   300  			}
   301  		}
   302  		// if c doesn't exist in the model, the pointer will be the zero value in the ptrs array and it's value will be thrown away
   303  		continue
   304  	}
   305  
   306  	return ptrs, nil
   307  }
   308  
   309  // PtrsFromMapping expects to be passed an addressable struct and a mapping
   310  // of where to find things. It pulls the pointers out referred to by the mapping.
   311  func PtrsFromMapping(val reflect.Value, mapping []uint64) []interface{} {
   312  	ptrs := make([]interface{}, len(mapping))
   313  	for i, m := range mapping {
   314  		ptrs[i] = ptrFromMapping(val, m, true).Interface()
   315  	}
   316  	return ptrs
   317  }
   318  
   319  // ValuesFromMapping expects to be passed an addressable struct and a mapping
   320  // of where to find things. It pulls the pointers out referred to by the mapping.
   321  func ValuesFromMapping(val reflect.Value, mapping []uint64) []interface{} {
   322  	ptrs := make([]interface{}, len(mapping))
   323  	for i, m := range mapping {
   324  		ptrs[i] = ptrFromMapping(val, m, false).Interface()
   325  	}
   326  	return ptrs
   327  }
   328  
   329  // ptrFromMapping expects to be passed an addressable struct that it's looking
   330  // for things on.
   331  func ptrFromMapping(val reflect.Value, mapping uint64, addressOf bool) reflect.Value {
   332  	if mapping == 0 {
   333  		var ignored interface{}
   334  		return reflect.ValueOf(&ignored)
   335  	}
   336  	for i := 0; i < 8; i++ {
   337  		v := (mapping >> uint(i*8)) & sentinel
   338  
   339  		if v == sentinel {
   340  			if addressOf && val.Kind() != reflect.Ptr {
   341  				return val.Addr()
   342  			} else if !addressOf && val.Kind() == reflect.Ptr {
   343  				return reflect.Indirect(val)
   344  			}
   345  			return val
   346  		}
   347  
   348  		val = val.Field(int(v))
   349  		if val.Kind() == reflect.Ptr {
   350  			val = reflect.Indirect(val)
   351  		}
   352  	}
   353  
   354  	panic("could not find pointer from mapping")
   355  }
   356  
   357  // MakeStructMapping creates a map of the struct to be able to quickly look
   358  // up its pointers and values by name.
   359  func MakeStructMapping(typ reflect.Type) map[string]uint64 {
   360  	fieldMaps := make(map[string]uint64)
   361  	makeStructMappingHelper(typ, "", 0, 0, fieldMaps)
   362  	return fieldMaps
   363  }
   364  
   365  func makeStructMappingHelper(typ reflect.Type, prefix string, current uint64, depth uint, fieldMaps map[string]uint64) {
   366  	if typ.Kind() == reflect.Ptr {
   367  		typ = typ.Elem()
   368  	}
   369  
   370  	n := typ.NumField()
   371  	for i := 0; i < n; i++ {
   372  		f := typ.Field(i)
   373  
   374  		tag, recurse := getBoilTag(f)
   375  		if len(tag) == 0 {
   376  			tag = unTitleCase(f.Name)
   377  		} else if tag[0] == '-' {
   378  			continue
   379  		}
   380  
   381  		if len(prefix) != 0 {
   382  			tag = fmt.Sprintf("%s.%s", prefix, tag)
   383  		}
   384  
   385  		if recurse {
   386  			makeStructMappingHelper(f.Type, tag, current|uint64(i)<<depth, depth+8, fieldMaps)
   387  			continue
   388  		}
   389  
   390  		fieldMaps[tag] = current | (sentinel << (depth + 8)) | (uint64(i) << depth)
   391  	}
   392  }
   393  
   394  func getBoilTag(field reflect.StructField) (name string, recurse bool) {
   395  	tag := field.Tag.Get("boil")
   396  
   397  	if len(tag) == 0 {
   398  		return "", false
   399  	}
   400  
   401  	ind := strings.IndexByte(tag, ',')
   402  	if ind == -1 {
   403  		return tag, false
   404  	} else if ind == 0 {
   405  		return "", true
   406  	}
   407  
   408  	nameFragment := tag[:ind]
   409  	return nameFragment, true
   410  }
   411  
   412  var (
   413  	mappingCachesMu sync.Mutex
   414  	mappingCaches   = make(map[reflect.Type]*mappingCache)
   415  )
   416  
   417  func getMappingCache(typ reflect.Type) *mappingCache {
   418  	mappingCachesMu.Lock()
   419  	defer mappingCachesMu.Unlock()
   420  
   421  	cache := mappingCaches[typ]
   422  	if cache != nil {
   423  		return cache
   424  	}
   425  
   426  	cache = newMappingCache(typ)
   427  	mappingCaches[typ] = cache
   428  
   429  	return cache
   430  }
   431  
   432  type mappingCache struct {
   433  	typ reflect.Type
   434  
   435  	mu          sync.Mutex
   436  	structMap   map[string]uint64
   437  	colMappings map[string][]uint64
   438  }
   439  
   440  func newMappingCache(typ reflect.Type) *mappingCache {
   441  	return &mappingCache{
   442  		typ:         typ,
   443  		structMap:   MakeStructMapping(typ),
   444  		colMappings: make(map[string][]uint64),
   445  	}
   446  }
   447  
   448  func (b *mappingCache) mapping(cols []string) ([]uint64, error) {
   449  	buf := strmangle.GetBuffer()
   450  	defer strmangle.PutBuffer(buf)
   451  
   452  	for _, s := range cols {
   453  		buf.WriteString(s)
   454  		buf.WriteByte(0)
   455  	}
   456  
   457  	key := buf.Bytes()
   458  
   459  	b.mu.Lock()
   460  	defer b.mu.Unlock()
   461  
   462  	mapping := b.colMappings[string(key)]
   463  	if mapping != nil {
   464  		return mapping, nil
   465  	}
   466  
   467  	mapping, err := BindMapping(b.typ, b.structMap, cols)
   468  	if err != nil {
   469  		return nil, err
   470  	}
   471  
   472  	b.colMappings[string(key)] = mapping
   473  
   474  	return mapping, nil
   475  }
   476  
   477  // Equal is different to reflect.DeepEqual in that it's both less efficient
   478  // less magical, and dosen't concern itself with a wide variety of types that could
   479  // be present but it does use the driver.Valuer interface since many types that will
   480  // go through database things will use these.
   481  //
   482  // We're focused on basic types + []byte. Since we're really only interested in things
   483  // that are typically used for primary keys in a database.
   484  //
   485  // Choosing not to use the DefaultParameterConverter here because sqlboiler doesn't generate
   486  // pointer columns.
   487  func Equal(a, b interface{}) bool {
   488  	if (a == nil && b != nil) || (a != nil && b == nil) {
   489  		return false
   490  	}
   491  
   492  	// Here we make a fast-path for bytes, because it's the most likely thing
   493  	// this method will be called with.
   494  	if ab, ok := a.([]byte); ok {
   495  		if bb, ok := b.([]byte); ok {
   496  			return bytes.Equal(ab, bb)
   497  		}
   498  	}
   499  
   500  	var err error
   501  	// If either is a sql.Scanner, pull the primitive value out before we get into type checking
   502  	// since we can't compare complex types anyway.
   503  	if v, ok := a.(driver.Valuer); ok {
   504  		a, err = v.Value()
   505  		if err != nil {
   506  			panic(fmt.Sprintf("while comparing values, although 'a' implemented driver.Valuer, an error occured when calling it: %+v", err))
   507  		}
   508  	}
   509  	if v, ok := b.(driver.Valuer); ok {
   510  		b, err = v.Value()
   511  		if err != nil {
   512  			panic(fmt.Sprintf("while comparing values, although 'b' implemented driver.Valuer, an error occured when calling it: %+v", err))
   513  		}
   514  	}
   515  
   516  	// Do nil checks again, since a Null type could have returned nil
   517  	if (a == nil && b != nil) || (a != nil && b == nil) {
   518  		return false
   519  	}
   520  
   521  	// If either is string and another is numeric, try to parse string as numeric
   522  	if as, ok := a.(string); ok && isNumeric(b) {
   523  		a = parseNumeric(as, reflect.TypeOf(b))
   524  	}
   525  	if bs, ok := b.(string); ok && isNumeric(a) {
   526  		b = parseNumeric(bs, reflect.TypeOf(a))
   527  	}
   528  
   529  	a = upgradeNumericTypes(a)
   530  	b = upgradeNumericTypes(b)
   531  
   532  	if at, bt := reflect.TypeOf(a), reflect.TypeOf(b); at != bt {
   533  		panic(fmt.Sprintf("primitive type of a (%s) was not the same primitive type as b (%s)", at.String(), bt.String()))
   534  	}
   535  
   536  	switch t := a.(type) {
   537  	case int64, float64, bool, string:
   538  		return a == b
   539  	case []byte:
   540  		return bytes.Equal(t, b.([]byte))
   541  	case time.Time:
   542  		return t.Equal(b.(time.Time))
   543  	}
   544  
   545  	return false
   546  }
   547  
   548  // isNumeric tests if i is a numeric value.
   549  func isNumeric(i interface{}) bool {
   550  	switch i.(type) {
   551  	case int,
   552  		int8,
   553  		int16,
   554  		int32,
   555  		int64,
   556  		uint,
   557  		uint8,
   558  		uint16,
   559  		uint32,
   560  		uint64,
   561  		float32,
   562  		float64:
   563  		return true
   564  	}
   565  	return false
   566  }
   567  
   568  // parseNumeric tries to parse s as t.
   569  // t must be a numeric type.
   570  func parseNumeric(s string, t reflect.Type) interface{} {
   571  	var (
   572  		res interface{}
   573  		err error
   574  	)
   575  	switch t.Kind() {
   576  	case reflect.Int,
   577  		reflect.Int8,
   578  		reflect.Int16,
   579  		reflect.Int32,
   580  		reflect.Int64:
   581  		res, err = strconv.ParseInt(s, 0, t.Bits())
   582  	case reflect.Uint,
   583  		reflect.Uint8,
   584  		reflect.Uint16,
   585  		reflect.Uint32,
   586  		reflect.Uint64:
   587  		res, err = strconv.ParseUint(s, 0, t.Bits())
   588  	case reflect.Float32,
   589  		reflect.Float64:
   590  		res, err = strconv.ParseFloat(s, t.Bits())
   591  	}
   592  	if err != nil {
   593  		panic(fmt.Sprintf("tries to parse %q as %s but got error: %+v", s, t.String(), err))
   594  	}
   595  	return res
   596  }
   597  
   598  // Assign assigns a value to another using reflection.
   599  // Dst must be a pointer.
   600  func Assign(dst, src interface{}) {
   601  	// Fast path for []byte since it's one of the
   602  	// most frequent other "ids" we'll be assigning.
   603  	if db, ok := dst.(*[]byte); ok {
   604  		if sb, ok := src.([]byte); ok {
   605  			*db = make([]byte, len(sb))
   606  			copy(*db, sb)
   607  			return
   608  		}
   609  	}
   610  
   611  	scan, isDstScanner := dst.(sql.Scanner)
   612  	val, isSrcValuer := src.(driver.Valuer)
   613  
   614  	switch {
   615  	case isDstScanner && isSrcValuer:
   616  		val, err := val.Value()
   617  		if err != nil {
   618  			panic(fmt.Sprintf("tried to call value on %T but got err: %+v", src, err))
   619  		}
   620  
   621  		err = scan.Scan(val)
   622  		if err != nil {
   623  			panic(fmt.Sprintf("tried to call Scan on %T with %#v but got err: %+v", dst, val, err))
   624  		}
   625  
   626  	case isDstScanner && !isSrcValuer:
   627  		// Compress any lower width integer types
   628  		src = upgradeNumericTypes(src)
   629  
   630  		if err := scan.Scan(src); err != nil {
   631  			panic(fmt.Sprintf("tried to call Scan on %T with %#v but got err: %+v", dst, src, err))
   632  		}
   633  
   634  	case !isDstScanner && isSrcValuer:
   635  		val, err := val.Value()
   636  		if err != nil {
   637  			panic(fmt.Sprintf("tried to call value on %T but got err: %+v", src, err))
   638  		}
   639  
   640  		assignValue(dst, val)
   641  
   642  	default:
   643  		// We should always be comparing primitives with each other with == in templates
   644  		// so this method should never be called for say: string, string, or int, int
   645  		panic("this case should have been handled by something other than this method")
   646  	}
   647  }
   648  
   649  func upgradeNumericTypes(i interface{}) interface{} {
   650  	switch t := i.(type) {
   651  	case int:
   652  		return int64(t)
   653  	case int8:
   654  		return int64(t)
   655  	case int16:
   656  		return int64(t)
   657  	case int32:
   658  		return int64(t)
   659  	case uint:
   660  		return int64(t)
   661  	case uint8:
   662  		return int64(t)
   663  	case uint16:
   664  		return int64(t)
   665  	case uint32:
   666  		return int64(t)
   667  	case uint64:
   668  		return int64(t)
   669  	case float32:
   670  		return float64(t)
   671  	default:
   672  		return i
   673  	}
   674  }
   675  
   676  // This whole function makes assumptions that whatever type
   677  // dst is, will be compatible with whatever came out of the Valuer.
   678  // We handle the types that driver.Value could possibly be.
   679  func assignValue(dst interface{}, val driver.Value) {
   680  	dstType := reflect.TypeOf(dst).Elem()
   681  	dstVal := reflect.ValueOf(dst).Elem()
   682  
   683  	if val == nil {
   684  		dstVal.Set(reflect.Zero(dstType))
   685  		return
   686  	}
   687  
   688  	v := reflect.ValueOf(val)
   689  
   690  	switch dstType.Kind() {
   691  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   692  		dstVal.SetInt(v.Int())
   693  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   694  		dstVal.SetInt(int64(v.Uint()))
   695  	case reflect.Bool:
   696  		dstVal.SetBool(v.Bool())
   697  	case reflect.String:
   698  		dstVal.SetString(v.String())
   699  	case reflect.Float32, reflect.Float64:
   700  		dstVal.SetFloat(v.Float())
   701  	case reflect.Slice:
   702  		// Assume []byte
   703  		db, sb := dst.(*[]byte), val.([]byte)
   704  		*db = make([]byte, len(sb))
   705  		copy(*db, sb)
   706  	case reflect.Struct:
   707  		// Assume time.Time
   708  		dstVal.Set(v)
   709  	}
   710  }
   711  
   712  // MustTime retrieves a time value from a valuer.
   713  func MustTime(val driver.Valuer) time.Time {
   714  	v, err := val.Value()
   715  	if err != nil {
   716  		panic(fmt.Sprintf("attempted to call value on %T to get time but got an error: %+v", val, err))
   717  	}
   718  
   719  	if v == nil {
   720  		return time.Time{}
   721  	}
   722  
   723  	return v.(time.Time)
   724  }
   725  
   726  // IsValuerNil returns true if the valuer's value is null.
   727  func IsValuerNil(val driver.Valuer) bool {
   728  	v, err := val.Value()
   729  	if err != nil {
   730  		panic(fmt.Sprintf("attempted to call value on %T but got an error: %+v", val, err))
   731  	}
   732  
   733  	return v == nil
   734  }
   735  
   736  // IsNil is a more generic version of IsValuerNil, will check to make sure it's
   737  // not a valuer first.
   738  func IsNil(val interface{}) bool {
   739  	if val == nil {
   740  		return true
   741  	}
   742  
   743  	valuer, ok := val.(driver.Valuer)
   744  	if ok {
   745  		return IsValuerNil(valuer)
   746  	}
   747  
   748  	return reflect.ValueOf(val).IsNil()
   749  }
   750  
   751  // SetScanner attempts to set a scannable value on a scanner.
   752  func SetScanner(scanner sql.Scanner, val driver.Value) {
   753  	if err := scanner.Scan(val); err != nil {
   754  		panic(fmt.Sprintf("attempted to call Scan on %T with %#v but got an error: %+v", scanner, val, err))
   755  	}
   756  }
   757  
   758  // These are sorted by size so that the biggest thing
   759  // gets replaced first (think guid/id). This list is copied
   760  // from strmangle.uppercaseWords and should hopefully be kept
   761  // in sync.
   762  var specialWordReplacer = strings.NewReplacer(
   763  	"ASCII", "Ascii",
   764  	"GUID", "Guid",
   765  	"JSON", "Json",
   766  	"UUID", "Uuid",
   767  	"UTF8", "Utf8",
   768  	"ACL", "Acl",
   769  	"API", "Api",
   770  	"CPU", "Cpu",
   771  	"EOF", "Eof",
   772  	"RAM", "Ram",
   773  	"SLA", "Sla",
   774  	"UDP", "Udp",
   775  	"UID", "Uid",
   776  	"URI", "Uri",
   777  	"URL", "Url",
   778  	"ID", "Id",
   779  	"IP", "Ip",
   780  	"UI", "Ui",
   781  )
   782  
   783  // unTitleCase attempts to undo a title-cased string.
   784  //
   785  // DO NOT USE THIS METHOD IF YOU CAN AVOID IT
   786  //
   787  // Normally this would be easy but we have to deal with uppercased words
   788  // of varying lengths. We almost never use this function so it
   789  // can be as badly performing as we want. If people don't want to incur
   790  // it's cost they should be able to use the `boil` struct tag to avoid it.
   791  //
   792  // We did not put this in strmangle because we don't want it being part
   793  // of any public API as it's loaded with corner cases and sad performance.
   794  func unTitleCase(n string) string {
   795  	if len(n) == 0 {
   796  		return ""
   797  	}
   798  
   799  	// Make our words no longer special case
   800  	n = specialWordReplacer.Replace(n)
   801  
   802  	buf := strmangle.GetBuffer()
   803  
   804  	first := true
   805  
   806  	writeIt := func(s string) {
   807  		if first {
   808  			first = false
   809  		} else {
   810  			buf.WriteByte('_')
   811  		}
   812  		buf.WriteString(strings.ToLower(s))
   813  	}
   814  
   815  	lastUp := true
   816  	start := 0
   817  	for i, r := range n {
   818  		currentUp := unicode.IsUpper(r)
   819  		isDigit := unicode.IsDigit(r)
   820  
   821  		if !isDigit && !lastUp && currentUp {
   822  			fragment := n[start:i]
   823  			writeIt(fragment)
   824  			start = i
   825  		}
   826  
   827  		if !isDigit && lastUp && !currentUp && i-1-start > 1 {
   828  			fragment := n[start : i-1]
   829  			writeIt(fragment)
   830  			start = i - 1
   831  		}
   832  
   833  		lastUp = currentUp
   834  	}
   835  
   836  	remaining := n[start:]
   837  	if len(remaining) > 0 {
   838  		writeIt(remaining)
   839  	}
   840  
   841  	ret := buf.String()
   842  	strmangle.PutBuffer(buf)
   843  	return ret
   844  }