sql.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. package logger
  2. import (
  3. "database/sql/driver"
  4. "fmt"
  5. "reflect"
  6. "regexp"
  7. "strconv"
  8. "strings"
  9. "time"
  10. "unicode"
  11. "gorm.io/gorm/utils"
  12. )
  13. func isPrintable(s []byte) bool {
  14. for _, r := range s {
  15. if !unicode.IsPrint(rune(r)) {
  16. return false
  17. }
  18. }
  19. return true
  20. }
  21. var convertableTypes = []reflect.Type{reflect.TypeOf(time.Time{}), reflect.TypeOf(false), reflect.TypeOf([]byte{})}
  22. func ExplainSQL(sql string, numericPlaceholder *regexp.Regexp, escaper string, avars ...interface{}) string {
  23. var convertParams func(interface{}, int)
  24. var vars = make([]string, len(avars))
  25. convertParams = func(v interface{}, idx int) {
  26. switch v := v.(type) {
  27. case bool:
  28. vars[idx] = strconv.FormatBool(v)
  29. case time.Time:
  30. if v.IsZero() {
  31. vars[idx] = escaper + "0000-00-00 00:00:00" + escaper
  32. } else {
  33. vars[idx] = escaper + v.Format("2006-01-02 15:04:05.999") + escaper
  34. }
  35. case *time.Time:
  36. if v != nil {
  37. if v.IsZero() {
  38. vars[idx] = escaper + "0000-00-00 00:00:00" + escaper
  39. } else {
  40. vars[idx] = escaper + v.Format("2006-01-02 15:04:05.999") + escaper
  41. }
  42. } else {
  43. vars[idx] = "NULL"
  44. }
  45. case fmt.Stringer:
  46. reflectValue := reflect.ValueOf(v)
  47. if v != nil && reflectValue.IsValid() && ((reflectValue.Kind() == reflect.Ptr && !reflectValue.IsNil()) || reflectValue.Kind() != reflect.Ptr) {
  48. vars[idx] = escaper + strings.Replace(fmt.Sprintf("%v", v), escaper, "\\"+escaper, -1) + escaper
  49. } else {
  50. vars[idx] = "NULL"
  51. }
  52. case driver.Valuer:
  53. reflectValue := reflect.ValueOf(v)
  54. if v != nil && reflectValue.IsValid() && ((reflectValue.Kind() == reflect.Ptr && !reflectValue.IsNil()) || reflectValue.Kind() != reflect.Ptr) {
  55. r, _ := v.Value()
  56. convertParams(r, idx)
  57. } else {
  58. vars[idx] = "NULL"
  59. }
  60. case []byte:
  61. if isPrintable(v) {
  62. vars[idx] = escaper + strings.Replace(string(v), escaper, "\\"+escaper, -1) + escaper
  63. } else {
  64. vars[idx] = escaper + "<binary>" + escaper
  65. }
  66. case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
  67. vars[idx] = utils.ToString(v)
  68. case float64, float32:
  69. vars[idx] = fmt.Sprintf("%.6f", v)
  70. case string:
  71. vars[idx] = escaper + strings.Replace(v, escaper, "\\"+escaper, -1) + escaper
  72. default:
  73. rv := reflect.ValueOf(v)
  74. if v == nil || !rv.IsValid() || rv.Kind() == reflect.Ptr && rv.IsNil() {
  75. vars[idx] = "NULL"
  76. } else if valuer, ok := v.(driver.Valuer); ok {
  77. v, _ = valuer.Value()
  78. convertParams(v, idx)
  79. } else if rv.Kind() == reflect.Ptr && !rv.IsZero() {
  80. convertParams(reflect.Indirect(rv).Interface(), idx)
  81. } else {
  82. for _, t := range convertableTypes {
  83. if rv.Type().ConvertibleTo(t) {
  84. convertParams(rv.Convert(t).Interface(), idx)
  85. return
  86. }
  87. }
  88. vars[idx] = escaper + strings.Replace(fmt.Sprint(v), escaper, "\\"+escaper, -1) + escaper
  89. }
  90. }
  91. }
  92. for idx, v := range avars {
  93. convertParams(v, idx)
  94. }
  95. if numericPlaceholder == nil {
  96. var idx int
  97. var newSQL strings.Builder
  98. for _, v := range []byte(sql) {
  99. if v == '?' {
  100. if len(vars) > idx {
  101. newSQL.WriteString(vars[idx])
  102. idx++
  103. continue
  104. }
  105. }
  106. newSQL.WriteByte(v)
  107. }
  108. sql = newSQL.String()
  109. } else {
  110. sql = numericPlaceholder.ReplaceAllString(sql, "$$$1$$")
  111. for idx, v := range vars {
  112. sql = strings.Replace(sql, "$"+strconv.Itoa(idx+1)+"$", v, 1)
  113. }
  114. }
  115. return sql
  116. }