You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

150 lines
3.1 KiB

  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. errLog.Print(ErrInvalidConn)
  24. return driver.ErrBadConn
  25. }
  26. err := stmt.mc.writeCommandPacketUint32(comStmtClose, stmt.id)
  27. stmt.mc = nil
  28. return err
  29. }
  30. func (stmt *mysqlStmt) NumInput() int {
  31. return stmt.paramCount
  32. }
  33. func (stmt *mysqlStmt) ColumnConverter(idx int) driver.ValueConverter {
  34. return converter{}
  35. }
  36. func (stmt *mysqlStmt) Exec(args []driver.Value) (driver.Result, error) {
  37. if stmt.mc.netConn == nil {
  38. errLog.Print(ErrInvalidConn)
  39. return nil, driver.ErrBadConn
  40. }
  41. // Send command
  42. err := stmt.writeExecutePacket(args)
  43. if err != nil {
  44. return nil, err
  45. }
  46. mc := stmt.mc
  47. mc.affectedRows = 0
  48. mc.insertId = 0
  49. // Read Result
  50. resLen, err := mc.readResultSetHeaderPacket()
  51. if err == nil {
  52. if resLen > 0 {
  53. // Columns
  54. err = mc.readUntilEOF()
  55. if err != nil {
  56. return nil, err
  57. }
  58. // Rows
  59. err = mc.readUntilEOF()
  60. }
  61. if err == nil {
  62. return &mysqlResult{
  63. affectedRows: int64(mc.affectedRows),
  64. insertId: int64(mc.insertId),
  65. }, nil
  66. }
  67. }
  68. return nil, err
  69. }
  70. func (stmt *mysqlStmt) Query(args []driver.Value) (driver.Rows, error) {
  71. if stmt.mc.netConn == nil {
  72. errLog.Print(ErrInvalidConn)
  73. return nil, driver.ErrBadConn
  74. }
  75. // Send command
  76. err := stmt.writeExecutePacket(args)
  77. if err != nil {
  78. return nil, err
  79. }
  80. mc := stmt.mc
  81. // Read Result
  82. resLen, err := mc.readResultSetHeaderPacket()
  83. if err != nil {
  84. return nil, err
  85. }
  86. rows := new(binaryRows)
  87. if resLen > 0 {
  88. rows.mc = mc
  89. // Columns
  90. // If not cached, read them and cache them
  91. if stmt.columns == nil {
  92. rows.columns, err = mc.readColumns(resLen)
  93. stmt.columns = rows.columns
  94. } else {
  95. rows.columns = stmt.columns
  96. err = mc.readUntilEOF()
  97. }
  98. }
  99. return rows, err
  100. }
  101. type converter struct{}
  102. func (c converter) ConvertValue(v interface{}) (driver.Value, error) {
  103. if driver.IsValue(v) {
  104. return v, nil
  105. }
  106. rv := reflect.ValueOf(v)
  107. switch rv.Kind() {
  108. case reflect.Ptr:
  109. // indirect pointers
  110. if rv.IsNil() {
  111. return nil, nil
  112. }
  113. return c.ConvertValue(rv.Elem().Interface())
  114. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  115. return rv.Int(), nil
  116. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
  117. return int64(rv.Uint()), nil
  118. case reflect.Uint64:
  119. u64 := rv.Uint()
  120. if u64 >= 1<<63 {
  121. return strconv.FormatUint(u64, 10), nil
  122. }
  123. return int64(u64), nil
  124. case reflect.Float32, reflect.Float64:
  125. return rv.Float(), nil
  126. }
  127. return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind())
  128. }