github.com/movsb/taorm@v0.0.0-20201209183410-91bafb0b22a6/taorm/utils.go (about)

     1  package taorm
     2  
     3  import (
     4  	"database/sql"
     5  	"database/sql/driver"
     6  	"fmt"
     7  	"go/ast"
     8  	"reflect"
     9  	"regexp"
    10  	"strings"
    11  	"time"
    12  	"unsafe"
    13  )
    14  
    15  // https://gist.github.com/stoewer/fbe273b711e6a06315d19552dd4d33e60
    16  var matchFirstCap = regexp.MustCompile("(.)([A-Z][a-z]+)")
    17  var matchAllCap = regexp.MustCompile("([a-z0-9])([A-Z])")
    18  
    19  func toSnakeCase(str string) string {
    20  	snake := matchFirstCap.ReplaceAllString(str, "${1}_${2}")
    21  	snake = matchAllCap.ReplaceAllString(snake, "${1}_${2}")
    22  	return strings.ToLower(snake)
    23  }
    24  
    25  var scannerType = reflect.TypeOf((*sql.Scanner)(nil)).Elem()
    26  var valuerType = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
    27  
    28  func isColumnField(field reflect.StructField) bool {
    29  	if !ast.IsExported(field.Name) {
    30  		return false
    31  	}
    32  
    33  	t := field.Type
    34  
    35  	switch t.Kind() {
    36  	case reflect.Bool, reflect.String,
    37  		reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
    38  		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
    39  		reflect.Float32, reflect.Float64:
    40  		return true
    41  	}
    42  
    43  	valueable := t.Implements(valuerType)
    44  	scannable := reflect.PtrTo(t).Implements(scannerType) && !t.Implements(scannerType)
    45  	if valueable && scannable {
    46  		return true
    47  	}
    48  
    49  	dummy := reflect.NewAt(t, unsafe.Pointer(nil)).Interface()
    50  	switch dummy.(type) {
    51  	case *time.Time:
    52  		return true
    53  	case *[]byte:
    54  		return true
    55  	}
    56  
    57  	return false
    58  }
    59  
    60  func getColumnName(field reflect.StructField) string {
    61  	tag := field.Tag.Get("taorm")
    62  	kvs := strings.Split(tag, ",")
    63  	for _, kv := range kvs {
    64  		s := strings.Split(kv, ":")
    65  		switch s[0] {
    66  		case "-":
    67  			return ""
    68  		case "name":
    69  			if len(s) > 1 {
    70  				return s[1]
    71  			}
    72  			return ""
    73  		}
    74  	}
    75  	return toSnakeCase(field.Name)
    76  }
    77  
    78  type _EmptyEface struct {
    79  	typ *struct{}
    80  	ptr unsafe.Pointer
    81  }
    82  
    83  // createSQLInMarks creates "?,?,?" string.
    84  func createSQLInMarks(count int) string {
    85  	s := "?"
    86  	for i := 1; i < count; i++ {
    87  		s += ",?"
    88  	}
    89  	return s
    90  }
    91  
    92  func panicIf(cond bool, v interface{}) {
    93  	if cond {
    94  		panic(v)
    95  	}
    96  }
    97  
    98  func dumpSQL(query string, args ...interface{}) {
    99  	// fmt.Println(strSQL(query, args...))
   100  }
   101  
   102  func strSQL(query string, args ...interface{}) string {
   103  	return fmt.Sprintf(strings.Replace(query, "?", "%v", -1), args...)
   104  }
   105  
   106  func structName(ty reflect.Type) string {
   107  	return ty.PkgPath() + "." + ty.Name()
   108  }