statement.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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. "reflect"
  13. "strconv"
  14. )
  15. type mysqlStmt struct {
  16. mc *mysqlConn
  17. id uint32
  18. paramCount int
  19. columns []mysqlField // cached from the first query
  20. }
  21. func (stmt *mysqlStmt) Close() error {
  22. if stmt.mc == nil || stmt.mc.netConn == nil {
  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.netConn == nil {
  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, 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. if resLen > 0 {
  56. // Columns
  57. err = mc.readUntilEOF()
  58. if err != nil {
  59. return nil, err
  60. }
  61. // Rows
  62. err = mc.readUntilEOF()
  63. }
  64. if err == nil {
  65. return &mysqlResult{
  66. affectedRows: int64(mc.affectedRows),
  67. insertId: int64(mc.insertId),
  68. }, nil
  69. }
  70. }
  71. return nil, err
  72. }
  73. func (stmt *mysqlStmt) Query(args []driver.Value) (driver.Rows, error) {
  74. if stmt.mc.netConn == nil {
  75. errLog.Print(ErrInvalidConn)
  76. return nil, driver.ErrBadConn
  77. }
  78. // Send command
  79. err := stmt.writeExecutePacket(args)
  80. if err != nil {
  81. return nil, err
  82. }
  83. mc := stmt.mc
  84. // Read Result
  85. resLen, err := mc.readResultSetHeaderPacket()
  86. if err != nil {
  87. return nil, err
  88. }
  89. rows := new(binaryRows)
  90. if resLen > 0 {
  91. rows.mc = mc
  92. // Columns
  93. // If not cached, read them and cache them
  94. if stmt.columns == nil {
  95. rows.columns, err = mc.readColumns(resLen)
  96. stmt.columns = rows.columns
  97. } else {
  98. rows.columns = stmt.columns
  99. err = mc.readUntilEOF()
  100. }
  101. }
  102. return rows, err
  103. }
  104. type converter struct{}
  105. func (c converter) ConvertValue(v interface{}) (driver.Value, error) {
  106. if driver.IsValue(v) {
  107. return v, nil
  108. }
  109. rv := reflect.ValueOf(v)
  110. switch rv.Kind() {
  111. case reflect.Ptr:
  112. // indirect pointers
  113. if rv.IsNil() {
  114. return nil, nil
  115. }
  116. return c.ConvertValue(rv.Elem().Interface())
  117. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  118. return rv.Int(), nil
  119. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
  120. return int64(rv.Uint()), nil
  121. case reflect.Uint64:
  122. u64 := rv.Uint()
  123. if u64 >= 1<<63 {
  124. return strconv.FormatUint(u64, 10), nil
  125. }
  126. return int64(u64), nil
  127. case reflect.Float32, reflect.Float64:
  128. return rv.Float(), nil
  129. }
  130. return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind())
  131. }