statement.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // Go MySQL Driver - A MySQL-Driver for Go's database/sql package
  2. //
  3. // Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public
  6. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  7. // You can obtain one at http://mozilla.org/MPL/2.0/.
  8. package mysql
  9. import (
  10. "database/sql/driver"
  11. "encoding/json"
  12. "fmt"
  13. "io"
  14. "reflect"
  15. )
  16. type mysqlStmt struct {
  17. mc *mysqlConn
  18. id uint32
  19. paramCount int
  20. }
  21. func (stmt *mysqlStmt) Close() error {
  22. if stmt.mc == nil || stmt.mc.closed.Load() {
  23. // driver.Stmt.Close can be called more than once, thus this function
  24. // has to be idempotent.
  25. // See also Issue #450 and golang/go#16019.
  26. //errLog.Print(ErrInvalidConn)
  27. return driver.ErrBadConn
  28. }
  29. err := stmt.mc.writeCommandPacketUint32(comStmtClose, stmt.id)
  30. stmt.mc = nil
  31. return err
  32. }
  33. func (stmt *mysqlStmt) NumInput() int {
  34. return stmt.paramCount
  35. }
  36. func (stmt *mysqlStmt) ColumnConverter(idx int) driver.ValueConverter {
  37. return converter{}
  38. }
  39. func (stmt *mysqlStmt) CheckNamedValue(nv *driver.NamedValue) (err error) {
  40. nv.Value, err = converter{}.ConvertValue(nv.Value)
  41. return
  42. }
  43. func (stmt *mysqlStmt) Exec(args []driver.Value) (driver.Result, error) {
  44. if stmt.mc.closed.Load() {
  45. stmt.mc.log(ErrInvalidConn)
  46. return nil, driver.ErrBadConn
  47. }
  48. // Send command
  49. err := stmt.writeExecutePacket(args)
  50. if err != nil {
  51. return nil, stmt.mc.markBadConn(err)
  52. }
  53. mc := stmt.mc
  54. handleOk := stmt.mc.clearResult()
  55. // Read Result
  56. resLen, err := handleOk.readResultSetHeaderPacket()
  57. if err != nil {
  58. return nil, err
  59. }
  60. if resLen > 0 {
  61. // Columns
  62. if err = mc.readUntilEOF(); err != nil {
  63. return nil, err
  64. }
  65. // Rows
  66. if err := mc.readUntilEOF(); err != nil {
  67. return nil, err
  68. }
  69. }
  70. if err := handleOk.discardResults(); err != nil {
  71. return nil, err
  72. }
  73. copied := mc.result
  74. return &copied, nil
  75. }
  76. func (stmt *mysqlStmt) Query(args []driver.Value) (driver.Rows, error) {
  77. return stmt.query(args)
  78. }
  79. func (stmt *mysqlStmt) query(args []driver.Value) (*binaryRows, error) {
  80. if stmt.mc.closed.Load() {
  81. stmt.mc.log(ErrInvalidConn)
  82. return nil, driver.ErrBadConn
  83. }
  84. // Send command
  85. err := stmt.writeExecutePacket(args)
  86. if err != nil {
  87. return nil, stmt.mc.markBadConn(err)
  88. }
  89. mc := stmt.mc
  90. // Read Result
  91. handleOk := stmt.mc.clearResult()
  92. resLen, err := handleOk.readResultSetHeaderPacket()
  93. if err != nil {
  94. return nil, err
  95. }
  96. rows := new(binaryRows)
  97. if resLen > 0 {
  98. rows.mc = mc
  99. rows.rs.columns, err = mc.readColumns(resLen)
  100. } else {
  101. rows.rs.done = true
  102. switch err := rows.NextResultSet(); err {
  103. case nil, io.EOF:
  104. return rows, nil
  105. default:
  106. return nil, err
  107. }
  108. }
  109. return rows, err
  110. }
  111. var jsonType = reflect.TypeOf(json.RawMessage{})
  112. type converter struct{}
  113. // ConvertValue mirrors the reference/default converter in database/sql/driver
  114. // with _one_ exception. We support uint64 with their high bit and the default
  115. // implementation does not. This function should be kept in sync with
  116. // database/sql/driver defaultConverter.ConvertValue() except for that
  117. // deliberate difference.
  118. func (c converter) ConvertValue(v any) (driver.Value, error) {
  119. if driver.IsValue(v) {
  120. return v, nil
  121. }
  122. if vr, ok := v.(driver.Valuer); ok {
  123. sv, err := callValuerValue(vr)
  124. if err != nil {
  125. return nil, err
  126. }
  127. if driver.IsValue(sv) {
  128. return sv, nil
  129. }
  130. // A value returned from the Valuer interface can be "a type handled by
  131. // a database driver's NamedValueChecker interface" so we should accept
  132. // uint64 here as well.
  133. if u, ok := sv.(uint64); ok {
  134. return u, nil
  135. }
  136. return nil, fmt.Errorf("non-Value type %T returned from Value", sv)
  137. }
  138. rv := reflect.ValueOf(v)
  139. switch rv.Kind() {
  140. case reflect.Ptr:
  141. // indirect pointers
  142. if rv.IsNil() {
  143. return nil, nil
  144. } else {
  145. return c.ConvertValue(rv.Elem().Interface())
  146. }
  147. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  148. return rv.Int(), nil
  149. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  150. return rv.Uint(), nil
  151. case reflect.Float32, reflect.Float64:
  152. return rv.Float(), nil
  153. case reflect.Bool:
  154. return rv.Bool(), nil
  155. case reflect.Slice:
  156. switch t := rv.Type(); {
  157. case t == jsonType:
  158. return v, nil
  159. case t.Elem().Kind() == reflect.Uint8:
  160. return rv.Bytes(), nil
  161. default:
  162. return nil, fmt.Errorf("unsupported type %T, a slice of %s", v, t.Elem().Kind())
  163. }
  164. case reflect.String:
  165. return rv.String(), nil
  166. }
  167. return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind())
  168. }
  169. var valuerReflectType = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
  170. // callValuerValue returns vr.Value(), with one exception:
  171. // If vr.Value is an auto-generated method on a pointer type and the
  172. // pointer is nil, it would panic at runtime in the panicwrap
  173. // method. Treat it like nil instead.
  174. //
  175. // This is so people can implement driver.Value on value types and
  176. // still use nil pointers to those types to mean nil/NULL, just like
  177. // string/*string.
  178. //
  179. // This is an exact copy of the same-named unexported function from the
  180. // database/sql package.
  181. func callValuerValue(vr driver.Valuer) (v driver.Value, err error) {
  182. if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Ptr &&
  183. rv.IsNil() &&
  184. rv.Type().Elem().Implements(valuerReflectType) {
  185. return nil, nil
  186. }
  187. return vr.Value()
  188. }