本站源代码
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

212 lines
4.9KB

  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. "fmt"
  12. "io"
  13. "reflect"
  14. "strconv"
  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.IsSet() {
  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) Exec(args []driver.Value) (driver.Result, error) {
  40. if stmt.mc.closed.IsSet() {
  41. errLog.Print(ErrInvalidConn)
  42. return nil, driver.ErrBadConn
  43. }
  44. // Send command
  45. err := stmt.writeExecutePacket(args)
  46. if err != nil {
  47. return nil, stmt.mc.markBadConn(err)
  48. }
  49. mc := stmt.mc
  50. mc.affectedRows = 0
  51. mc.insertId = 0
  52. // Read Result
  53. resLen, err := mc.readResultSetHeaderPacket()
  54. if err != nil {
  55. return nil, err
  56. }
  57. if resLen > 0 {
  58. // Columns
  59. if err = mc.readUntilEOF(); err != nil {
  60. return nil, err
  61. }
  62. // Rows
  63. if err := mc.readUntilEOF(); err != nil {
  64. return nil, err
  65. }
  66. }
  67. if err := mc.discardResults(); err != nil {
  68. return nil, err
  69. }
  70. return &mysqlResult{
  71. affectedRows: int64(mc.affectedRows),
  72. insertId: int64(mc.insertId),
  73. }, nil
  74. }
  75. func (stmt *mysqlStmt) Query(args []driver.Value) (driver.Rows, error) {
  76. return stmt.query(args)
  77. }
  78. func (stmt *mysqlStmt) query(args []driver.Value) (*binaryRows, error) {
  79. if stmt.mc.closed.IsSet() {
  80. errLog.Print(ErrInvalidConn)
  81. return nil, driver.ErrBadConn
  82. }
  83. // Send command
  84. err := stmt.writeExecutePacket(args)
  85. if err != nil {
  86. return nil, stmt.mc.markBadConn(err)
  87. }
  88. mc := stmt.mc
  89. // Read Result
  90. resLen, err := mc.readResultSetHeaderPacket()
  91. if err != nil {
  92. return nil, err
  93. }
  94. rows := new(binaryRows)
  95. if resLen > 0 {
  96. rows.mc = mc
  97. rows.rs.columns, err = mc.readColumns(resLen)
  98. } else {
  99. rows.rs.done = true
  100. switch err := rows.NextResultSet(); err {
  101. case nil, io.EOF:
  102. return rows, nil
  103. default:
  104. return nil, err
  105. }
  106. }
  107. return rows, err
  108. }
  109. type converter struct{}
  110. // ConvertValue mirrors the reference/default converter in database/sql/driver
  111. // with _one_ exception. We support uint64 with their high bit and the default
  112. // implementation does not. This function should be kept in sync with
  113. // database/sql/driver defaultConverter.ConvertValue() except for that
  114. // deliberate difference.
  115. func (c converter) ConvertValue(v interface{}) (driver.Value, error) {
  116. if driver.IsValue(v) {
  117. return v, nil
  118. }
  119. if vr, ok := v.(driver.Valuer); ok {
  120. sv, err := callValuerValue(vr)
  121. if err != nil {
  122. return nil, err
  123. }
  124. if !driver.IsValue(sv) {
  125. return nil, fmt.Errorf("non-Value type %T returned from Value", sv)
  126. }
  127. return sv, nil
  128. }
  129. rv := reflect.ValueOf(v)
  130. switch rv.Kind() {
  131. case reflect.Ptr:
  132. // indirect pointers
  133. if rv.IsNil() {
  134. return nil, nil
  135. } else {
  136. return c.ConvertValue(rv.Elem().Interface())
  137. }
  138. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  139. return rv.Int(), nil
  140. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
  141. return int64(rv.Uint()), nil
  142. case reflect.Uint64:
  143. u64 := rv.Uint()
  144. if u64 >= 1<<63 {
  145. return strconv.FormatUint(u64, 10), nil
  146. }
  147. return int64(u64), nil
  148. case reflect.Float32, reflect.Float64:
  149. return rv.Float(), nil
  150. case reflect.Bool:
  151. return rv.Bool(), nil
  152. case reflect.Slice:
  153. ek := rv.Type().Elem().Kind()
  154. if ek == reflect.Uint8 {
  155. return rv.Bytes(), nil
  156. }
  157. return nil, fmt.Errorf("unsupported type %T, a slice of %s", v, ek)
  158. case reflect.String:
  159. return rv.String(), nil
  160. }
  161. return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind())
  162. }
  163. var valuerReflectType = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
  164. // callValuerValue returns vr.Value(), with one exception:
  165. // If vr.Value is an auto-generated method on a pointer type and the
  166. // pointer is nil, it would panic at runtime in the panicwrap
  167. // method. Treat it like nil instead.
  168. //
  169. // This is so people can implement driver.Value on value types and
  170. // still use nil pointers to those types to mean nil/NULL, just like
  171. // string/*string.
  172. //
  173. // This is an exact copy of the same-named unexported function from the
  174. // database/sql package.
  175. func callValuerValue(vr driver.Valuer) (v driver.Value, err error) {
  176. if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Ptr &&
  177. rv.IsNil() &&
  178. rv.Type().Elem().Implements(valuerReflectType) {
  179. return nil, nil
  180. }
  181. return vr.Value()
  182. }
上海开阖软件有限公司 沪ICP备12045867号-1