resp.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. package client
  2. import (
  3. "encoding/binary"
  4. "github.com/juju/errors"
  5. . "github.com/siddontang/go-mysql/mysql"
  6. "github.com/siddontang/go/hack"
  7. )
  8. func (c *Conn) readUntilEOF() (err error) {
  9. var data []byte
  10. for {
  11. data, err = c.ReadPacket()
  12. if err != nil {
  13. return
  14. }
  15. // EOF Packet
  16. if c.isEOFPacket(data) {
  17. return
  18. }
  19. }
  20. return
  21. }
  22. func (c *Conn) isEOFPacket(data []byte) bool {
  23. return data[0] == EOF_HEADER && len(data) <= 5
  24. }
  25. func (c *Conn) handleOKPacket(data []byte) (*Result, error) {
  26. var n int
  27. var pos int = 1
  28. r := new(Result)
  29. r.AffectedRows, _, n = LengthEncodedInt(data[pos:])
  30. pos += n
  31. r.InsertId, _, n = LengthEncodedInt(data[pos:])
  32. pos += n
  33. if c.capability&CLIENT_PROTOCOL_41 > 0 {
  34. r.Status = binary.LittleEndian.Uint16(data[pos:])
  35. c.status = r.Status
  36. pos += 2
  37. //todo:strict_mode, check warnings as error
  38. //Warnings := binary.LittleEndian.Uint16(data[pos:])
  39. //pos += 2
  40. } else if c.capability&CLIENT_TRANSACTIONS > 0 {
  41. r.Status = binary.LittleEndian.Uint16(data[pos:])
  42. c.status = r.Status
  43. pos += 2
  44. }
  45. //new ok package will check CLIENT_SESSION_TRACK too, but I don't support it now.
  46. //skip info
  47. return r, nil
  48. }
  49. func (c *Conn) handleErrorPacket(data []byte) error {
  50. e := new(MyError)
  51. var pos int = 1
  52. e.Code = binary.LittleEndian.Uint16(data[pos:])
  53. pos += 2
  54. if c.capability&CLIENT_PROTOCOL_41 > 0 {
  55. //skip '#'
  56. pos++
  57. e.State = hack.String(data[pos : pos+5])
  58. pos += 5
  59. }
  60. e.Message = hack.String(data[pos:])
  61. return e
  62. }
  63. func (c *Conn) readOK() (*Result, error) {
  64. data, err := c.ReadPacket()
  65. if err != nil {
  66. return nil, errors.Trace(err)
  67. }
  68. if data[0] == OK_HEADER {
  69. return c.handleOKPacket(data)
  70. } else if data[0] == ERR_HEADER {
  71. return nil, c.handleErrorPacket(data)
  72. } else {
  73. return nil, errors.New("invalid ok packet")
  74. }
  75. }
  76. func (c *Conn) readResult(binary bool) (*Result, error) {
  77. data, err := c.ReadPacket()
  78. if err != nil {
  79. return nil, errors.Trace(err)
  80. }
  81. if data[0] == OK_HEADER {
  82. return c.handleOKPacket(data)
  83. } else if data[0] == ERR_HEADER {
  84. return nil, c.handleErrorPacket(data)
  85. } else if data[0] == LocalInFile_HEADER {
  86. return nil, ErrMalformPacket
  87. }
  88. return c.readResultset(data, binary)
  89. }
  90. func (c *Conn) readResultset(data []byte, binary bool) (*Result, error) {
  91. result := &Result{
  92. Status: 0,
  93. InsertId: 0,
  94. AffectedRows: 0,
  95. Resultset: &Resultset{},
  96. }
  97. // column count
  98. count, _, n := LengthEncodedInt(data)
  99. if n-len(data) != 0 {
  100. return nil, ErrMalformPacket
  101. }
  102. result.Fields = make([]*Field, count)
  103. result.FieldNames = make(map[string]int, count)
  104. if err := c.readResultColumns(result); err != nil {
  105. return nil, errors.Trace(err)
  106. }
  107. if err := c.readResultRows(result, binary); err != nil {
  108. return nil, errors.Trace(err)
  109. }
  110. return result, nil
  111. }
  112. func (c *Conn) readResultColumns(result *Result) (err error) {
  113. var i int = 0
  114. var data []byte
  115. for {
  116. data, err = c.ReadPacket()
  117. if err != nil {
  118. return
  119. }
  120. // EOF Packet
  121. if c.isEOFPacket(data) {
  122. if c.capability&CLIENT_PROTOCOL_41 > 0 {
  123. //result.Warnings = binary.LittleEndian.Uint16(data[1:])
  124. //todo add strict_mode, warning will be treat as error
  125. result.Status = binary.LittleEndian.Uint16(data[3:])
  126. c.status = result.Status
  127. }
  128. if i != len(result.Fields) {
  129. err = ErrMalformPacket
  130. }
  131. return
  132. }
  133. result.Fields[i], err = FieldData(data).Parse()
  134. if err != nil {
  135. return
  136. }
  137. result.FieldNames[hack.String(result.Fields[i].Name)] = i
  138. i++
  139. }
  140. }
  141. func (c *Conn) readResultRows(result *Result, isBinary bool) (err error) {
  142. var data []byte
  143. for {
  144. data, err = c.ReadPacket()
  145. if err != nil {
  146. return
  147. }
  148. // EOF Packet
  149. if c.isEOFPacket(data) {
  150. if c.capability&CLIENT_PROTOCOL_41 > 0 {
  151. //result.Warnings = binary.LittleEndian.Uint16(data[1:])
  152. //todo add strict_mode, warning will be treat as error
  153. result.Status = binary.LittleEndian.Uint16(data[3:])
  154. c.status = result.Status
  155. }
  156. break
  157. }
  158. result.RowDatas = append(result.RowDatas, data)
  159. }
  160. result.Values = make([][]interface{}, len(result.RowDatas))
  161. for i := range result.Values {
  162. result.Values[i], err = result.RowDatas[i].Parse(result.Fields, isBinary)
  163. if err != nil {
  164. return errors.Trace(err)
  165. }
  166. }
  167. return nil
  168. }