paramvalue.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. package native
  2. import (
  3. "github.com/ziutek/mymysql/mysql"
  4. "math"
  5. "reflect"
  6. "time"
  7. )
  8. type paramValue struct {
  9. typ uint16
  10. addr reflect.Value
  11. raw bool
  12. length int // >=0 - length of value, <0 - unknown length
  13. }
  14. func (val *paramValue) Len() int {
  15. if !val.addr.IsValid() {
  16. // Invalid Value was binded
  17. return 0
  18. }
  19. // val.addr always points to the pointer - lets dereference it
  20. v := val.addr.Elem()
  21. if v.IsNil() {
  22. // Binded Ptr Value is nil
  23. return 0
  24. }
  25. v = v.Elem()
  26. if val.length >= 0 {
  27. return val.length
  28. }
  29. switch val.typ {
  30. case MYSQL_TYPE_STRING:
  31. return lenStr(v.String())
  32. case MYSQL_TYPE_DATE:
  33. return lenDate(v.Interface().(mysql.Date))
  34. case MYSQL_TYPE_TIMESTAMP:
  35. return lenTime(v.Interface().(mysql.Timestamp).Time)
  36. case MYSQL_TYPE_DATETIME:
  37. return lenTime(v.Interface().(time.Time))
  38. case MYSQL_TYPE_TIME:
  39. return lenDuration(v.Interface().(time.Duration))
  40. case MYSQL_TYPE_TINY: // val.length < 0 so this is bool
  41. return 1
  42. }
  43. // MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_BLOB and type of Raw value
  44. return lenBin(v.Bytes())
  45. }
  46. func (pw *pktWriter) writeValue(val *paramValue) {
  47. if !val.addr.IsValid() {
  48. // Invalid Value was binded
  49. return
  50. }
  51. // val.addr always points to the pointer - lets dereference it
  52. v := val.addr.Elem()
  53. if v.IsNil() {
  54. // Binded Ptr Value is nil
  55. return
  56. }
  57. v = v.Elem()
  58. if val.raw || val.typ == MYSQL_TYPE_VAR_STRING ||
  59. val.typ == MYSQL_TYPE_BLOB {
  60. pw.writeBin(v.Bytes())
  61. return
  62. }
  63. // We don't need unsigned bit to check type
  64. unsign := (val.typ & MYSQL_UNSIGNED_MASK) != 0
  65. switch val.typ & ^MYSQL_UNSIGNED_MASK {
  66. case MYSQL_TYPE_NULL:
  67. // Don't write null values
  68. case MYSQL_TYPE_STRING:
  69. pw.writeBin([]byte(v.String()))
  70. case MYSQL_TYPE_LONG:
  71. i := v.Interface()
  72. if unsign {
  73. l, ok := i.(uint32)
  74. if !ok {
  75. l = uint32(i.(uint))
  76. }
  77. pw.writeU32(l)
  78. } else {
  79. l, ok := i.(int32)
  80. if !ok {
  81. l = int32(i.(int))
  82. }
  83. pw.writeU32(uint32(l))
  84. }
  85. case MYSQL_TYPE_FLOAT:
  86. pw.writeU32(math.Float32bits(v.Interface().(float32)))
  87. case MYSQL_TYPE_SHORT:
  88. if unsign {
  89. pw.writeU16(v.Interface().(uint16))
  90. } else {
  91. pw.writeU16(uint16(v.Interface().(int16)))
  92. }
  93. case MYSQL_TYPE_TINY:
  94. if val.length == -1 {
  95. // Translate bool value to MySQL tiny
  96. if v.Bool() {
  97. pw.writeByte(1)
  98. } else {
  99. pw.writeByte(0)
  100. }
  101. } else {
  102. if unsign {
  103. pw.writeByte(v.Interface().(uint8))
  104. } else {
  105. pw.writeByte(uint8(v.Interface().(int8)))
  106. }
  107. }
  108. case MYSQL_TYPE_LONGLONG:
  109. i := v.Interface()
  110. if unsign {
  111. l, ok := i.(uint64)
  112. if !ok {
  113. l = uint64(i.(uint))
  114. }
  115. pw.writeU64(l)
  116. } else {
  117. l, ok := i.(int64)
  118. if !ok {
  119. l = int64(i.(int))
  120. }
  121. pw.writeU64(uint64(l))
  122. }
  123. case MYSQL_TYPE_DOUBLE:
  124. pw.writeU64(math.Float64bits(v.Interface().(float64)))
  125. case MYSQL_TYPE_DATE:
  126. pw.writeDate(v.Interface().(mysql.Date))
  127. case MYSQL_TYPE_TIMESTAMP:
  128. pw.writeTime(v.Interface().(mysql.Timestamp).Time)
  129. case MYSQL_TYPE_DATETIME:
  130. pw.writeTime(v.Interface().(time.Time))
  131. case MYSQL_TYPE_TIME:
  132. pw.writeDuration(v.Interface().(time.Duration))
  133. default:
  134. panic(mysql.ErrBindUnkType)
  135. }
  136. return
  137. }