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 }