packets.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915
  1. // Go MySQL Driver - A MySQL-Driver for Go's database/sql package
  2. //
  3. // Copyright 2012 Julien Schmidt. All rights reserved.
  4. // http://www.julienschmidt.com
  5. //
  6. // This Source Code Form is subject to the terms of the Mozilla Public
  7. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  8. // You can obtain one at http://mozilla.org/MPL/2.0/.
  9. package mysql
  10. import (
  11. "bytes"
  12. "database/sql/driver"
  13. "encoding/binary"
  14. "errors"
  15. "fmt"
  16. "io"
  17. "math"
  18. "time"
  19. )
  20. // Packets documentation:
  21. // http://dev.mysql.com/doc/internals/en/client-server-protocol.html
  22. // Read packet to buffer 'data'
  23. func (mc *mysqlConn) readPacket() (data []byte, err error) {
  24. // Read header
  25. data = make([]byte, 4)
  26. err = mc.buf.read(data)
  27. if err != nil {
  28. errLog.Print(err)
  29. return nil, driver.ErrBadConn
  30. }
  31. // Packet Length
  32. var pktLen uint32
  33. pktLen |= uint32(data[0])
  34. pktLen |= uint32(data[1]) << 8
  35. pktLen |= uint32(data[2]) << 16
  36. if pktLen == 0 {
  37. return nil, err
  38. }
  39. // Check Packet Sync
  40. if data[3] != mc.sequence {
  41. if data[3] > mc.sequence {
  42. return nil, errPktSyncMul
  43. } else {
  44. return nil, errPktSync
  45. }
  46. }
  47. mc.sequence++
  48. // Read packet body
  49. data = make([]byte, pktLen)
  50. err = mc.buf.read(data)
  51. if err == nil {
  52. return data, nil
  53. }
  54. errLog.Print(err)
  55. return nil, driver.ErrBadConn
  56. }
  57. func (mc *mysqlConn) writePacket(data []byte) error {
  58. // Write packet
  59. n, err := mc.netConn.Write(data)
  60. if err != nil || n != len(data) {
  61. if err == nil {
  62. errLog.Print(errMalformPkt)
  63. }
  64. errLog.Print(err)
  65. return driver.ErrBadConn
  66. }
  67. mc.sequence++
  68. return nil
  69. }
  70. /******************************************************************************
  71. * Initialisation Process *
  72. ******************************************************************************/
  73. // Handshake Initialization Packet
  74. // http://dev.mysql.com/doc/internals/en/connection-phase.html#packet-Protocol::Handshake
  75. func (mc *mysqlConn) readInitPacket() (err error) {
  76. data, err := mc.readPacket()
  77. if err != nil {
  78. return
  79. }
  80. // protocol version [1 byte]
  81. if data[0] < MIN_PROTOCOL_VERSION {
  82. err = fmt.Errorf(
  83. "Unsupported MySQL Protocol Version %d. Protocol Version %d or higher is required",
  84. data[0],
  85. MIN_PROTOCOL_VERSION)
  86. }
  87. // server version [null terminated string]
  88. // connection id [4 bytes]
  89. pos := 1 + (bytes.IndexByte(data[1:], 0x00) + 1) + 4
  90. // first part of scramble buffer [8 bytes]
  91. mc.scrambleBuff = data[pos : pos+8]
  92. // (filler) always 0x00 [1 byte]
  93. pos += 8 + 1
  94. // capability flags (lower 2 bytes) [2 bytes]
  95. mc.flags = ClientFlag(binary.LittleEndian.Uint16(data[pos : pos+2]))
  96. if mc.flags&CLIENT_PROTOCOL_41 == 0 {
  97. err = errors.New("MySQL-Server does not support required Protocol 41+")
  98. }
  99. pos += 2
  100. if len(data) > pos {
  101. // character set [1 byte]
  102. mc.charset = data[pos]
  103. // status flags [2 bytes]
  104. // capability flags (upper 2 bytes) [2 bytes]
  105. // length of auth-plugin-data [1 byte]
  106. // reserved (all [00]) [10 byte]
  107. pos += 1 + 2 + 2 + 1 + 10
  108. mc.scrambleBuff = append(mc.scrambleBuff, data[pos:len(data)-1]...)
  109. if data[len(data)-1] == 0 {
  110. return
  111. }
  112. return errMalformPkt
  113. }
  114. return
  115. }
  116. /* Client Authentication Packet
  117. Bytes Name
  118. ----- ----
  119. 4 client_flags
  120. 4 max_packet_size
  121. 1 charset_number
  122. 23 (filler) always 0x00...
  123. n (Null-Terminated String) user
  124. n (Length Coded Binary) scramble_buff (1 + x bytes)
  125. n (Null-Terminated String) databasename (optional)
  126. */
  127. func (mc *mysqlConn) writeAuthPacket() error {
  128. // Adjust client flags based on server support
  129. clientFlags := uint32(
  130. CLIENT_PROTOCOL_41 |
  131. CLIENT_SECURE_CONN |
  132. CLIENT_LONG_PASSWORD |
  133. CLIENT_TRANSACTIONS,
  134. )
  135. if mc.flags&CLIENT_LONG_FLAG > 0 {
  136. clientFlags |= uint32(CLIENT_LONG_FLAG)
  137. }
  138. // User Password
  139. scrambleBuff := scramblePassword(mc.scrambleBuff, []byte(mc.cfg.passwd))
  140. pktLen := 4 + 4 + 1 + 23 + len(mc.cfg.user) + 1 + 1 + len(scrambleBuff)
  141. // To specify a db name
  142. if len(mc.cfg.dbname) > 0 {
  143. clientFlags |= uint32(CLIENT_CONNECT_WITH_DB)
  144. pktLen += len(mc.cfg.dbname) + 1
  145. }
  146. // Calculate packet length and make buffer with that size
  147. data := make([]byte, 0, pktLen+4)
  148. // Add the packet header
  149. data = append(data, uint24ToBytes(uint32(pktLen))...)
  150. data = append(data, mc.sequence)
  151. // ClientFlags
  152. data = append(data, uint32ToBytes(clientFlags)...)
  153. // MaxPacketSize
  154. data = append(data, uint32ToBytes(MAX_PACKET_SIZE)...)
  155. // Charset
  156. data = append(data, mc.charset)
  157. // Filler
  158. data = append(data, make([]byte, 23)...)
  159. // User
  160. if len(mc.cfg.user) > 0 {
  161. data = append(data, []byte(mc.cfg.user)...)
  162. }
  163. // Null-Terminator
  164. data = append(data, 0x0)
  165. // ScrambleBuffer
  166. data = append(data, byte(len(scrambleBuff)))
  167. if len(scrambleBuff) > 0 {
  168. data = append(data, scrambleBuff...)
  169. }
  170. // Databasename
  171. if len(mc.cfg.dbname) > 0 {
  172. data = append(data, []byte(mc.cfg.dbname)...)
  173. // Null-Terminator
  174. data = append(data, 0x0)
  175. }
  176. // Send Auth packet
  177. return mc.writePacket(data)
  178. }
  179. /******************************************************************************
  180. * Command Packets *
  181. ******************************************************************************/
  182. /* Command Packet
  183. Bytes Name
  184. ----- ----
  185. 1 command
  186. n arg
  187. */
  188. func (mc *mysqlConn) writeCommandPacket(command commandType, args ...interface{}) error {
  189. // Reset Packet Sequence
  190. mc.sequence = 0
  191. var arg []byte
  192. switch command {
  193. // Commands without args
  194. case COM_QUIT, COM_PING:
  195. if len(args) > 0 {
  196. return fmt.Errorf("Too much arguments (Got: %d Has: 0)", len(args))
  197. }
  198. arg = []byte{}
  199. // Commands with 1 arg unterminated string
  200. case COM_QUERY, COM_STMT_PREPARE:
  201. if len(args) != 1 {
  202. return fmt.Errorf("Invalid arguments count (Got: %d Has: 1)", len(args))
  203. }
  204. arg = []byte(args[0].(string))
  205. // Commands with 1 arg 32 bit uint
  206. case COM_STMT_CLOSE:
  207. if len(args) != 1 {
  208. return fmt.Errorf("Invalid arguments count (Got: %d Has: 1)", len(args))
  209. }
  210. arg = uint32ToBytes(args[0].(uint32))
  211. default:
  212. return fmt.Errorf("Unknown command: %d", command)
  213. }
  214. pktLen := 1 + len(arg)
  215. data := make([]byte, 0, pktLen+4)
  216. // Add the packet header
  217. data = append(data, uint24ToBytes(uint32(pktLen))...)
  218. data = append(data, mc.sequence)
  219. // Add command byte
  220. data = append(data, byte(command))
  221. // Add arg
  222. data = append(data, arg...)
  223. // Send CMD packet
  224. return mc.writePacket(data)
  225. }
  226. /******************************************************************************
  227. * Result Packets *
  228. ******************************************************************************/
  229. // Returns error if Packet is not an 'Result OK'-Packet
  230. func (mc *mysqlConn) readResultOK() error {
  231. data, err := mc.readPacket()
  232. if err != nil {
  233. return err
  234. }
  235. switch data[0] {
  236. // OK
  237. case 0:
  238. return mc.handleOkPacket(data)
  239. // EOF, someone is using old_passwords
  240. case 254:
  241. return errOldPassword
  242. // ERROR
  243. case 255:
  244. return mc.handleErrorPacket(data)
  245. }
  246. return errMalformPkt
  247. }
  248. /* Error Packet
  249. Bytes Name
  250. ----- ----
  251. 1 field_count, always = 0xff
  252. 2 errno
  253. 1 (sqlstate marker), always '#'
  254. 5 sqlstate (5 characters)
  255. n message
  256. */
  257. func (mc *mysqlConn) handleErrorPacket(data []byte) error {
  258. // Error Number [16 bit uint]
  259. errno := binary.LittleEndian.Uint16(data[1:3])
  260. // SQL State [# + 5bytes string]
  261. //sqlstate := string(data[pos : pos+6])
  262. // Error Message [string]
  263. return fmt.Errorf("Error %d: %s", errno, string(data[9:]))
  264. }
  265. /* Ok Packet
  266. Bytes Name
  267. ----- ----
  268. 1 (Length Coded Binary) field_count, always = 0
  269. 1-9 (Length Coded Binary) affected_rows
  270. 1-9 (Length Coded Binary) insert_id
  271. 2 server_status
  272. 2 warning_count
  273. n (until end of packet) message
  274. */
  275. func (mc *mysqlConn) handleOkPacket(data []byte) (err error) {
  276. var n int
  277. // Affected rows [Length Coded Binary]
  278. mc.affectedRows, _, n, err = readLengthEncodedInteger(data[1:])
  279. if err != nil {
  280. return
  281. }
  282. // Insert id [Length Coded Binary]
  283. mc.insertId, _, _, err = readLengthEncodedInteger(data[1+n:])
  284. if err != nil {
  285. return
  286. }
  287. // Skip remaining data
  288. return
  289. }
  290. /* Result Set Header Packet
  291. Bytes Name
  292. ----- ----
  293. 1-9 (Length-Coded-Binary) field_count
  294. 1-9 (Length-Coded-Binary) extra
  295. The order of packets for a result set is:
  296. (Result Set Header Packet) the number of columns
  297. (Field Packets) column descriptors
  298. (EOF Packet) marker: end of Field Packets
  299. (Row Data Packets) row contents
  300. (EOF Packet) marker: end of Data Packets
  301. */
  302. func (mc *mysqlConn) readResultSetHeaderPacket() (fieldCount int, err error) {
  303. data, err := mc.readPacket()
  304. if err != nil {
  305. errLog.Print(err)
  306. err = driver.ErrBadConn
  307. return
  308. }
  309. if data[0] == 0 {
  310. err = mc.handleOkPacket(data)
  311. return
  312. } else if data[0] == 255 {
  313. err = mc.handleErrorPacket(data)
  314. return
  315. }
  316. num, _, n, err := readLengthEncodedInteger(data)
  317. if err != nil || (n-len(data)) != 0 {
  318. err = errors.New("Malformed Packet")
  319. return
  320. }
  321. fieldCount = int(num)
  322. return
  323. }
  324. // Read Packets as Field Packets until EOF-Packet or an Error appears
  325. func (mc *mysqlConn) readColumns(count int) (columns []mysqlField, err error) {
  326. var data []byte
  327. var pos, n int
  328. var name []byte
  329. for {
  330. data, err = mc.readPacket()
  331. if err != nil {
  332. return
  333. }
  334. // EOF Packet
  335. if data[0] == 254 && len(data) == 5 {
  336. if len(columns) != count {
  337. err = fmt.Errorf("ColumnsCount mismatch n:%d len:%d", count, len(columns))
  338. }
  339. return
  340. }
  341. // Catalog
  342. pos, err = readAndDropLengthEnodedString(data)
  343. if err != nil {
  344. return
  345. }
  346. // Database [len coded string]
  347. n, err = readAndDropLengthEnodedString(data[pos:])
  348. if err != nil {
  349. return
  350. }
  351. pos += n
  352. // Table [len coded string]
  353. n, err = readAndDropLengthEnodedString(data[pos:])
  354. if err != nil {
  355. return
  356. }
  357. pos += n
  358. // Original table [len coded string]
  359. n, err = readAndDropLengthEnodedString(data[pos:])
  360. if err != nil {
  361. return
  362. }
  363. pos += n
  364. // Name [len coded string]
  365. name, n, err = readLengthEnodedString(data[pos:])
  366. if err != nil {
  367. return
  368. }
  369. pos += n
  370. // Original name [len coded string]
  371. n, err = readAndDropLengthEnodedString(data[pos:])
  372. if err != nil {
  373. return
  374. }
  375. // Filler [1 byte]
  376. // Charset [16 bit uint]
  377. // Length [32 bit uint]
  378. pos += n + 1 + 2 + 4
  379. // Field type [byte]
  380. fieldType := FieldType(data[pos])
  381. pos++
  382. // Flags [16 bit uint]
  383. flags := FieldFlag(binary.LittleEndian.Uint16(data[pos : pos+2]))
  384. //pos += 2
  385. // Decimals [8 bit uint]
  386. //pos++
  387. // Default value [len coded binary]
  388. //if pos < len(data) {
  389. // defaultVal, _, err = bytesToLengthCodedBinary(data[pos:])
  390. //}
  391. columns = append(columns, mysqlField{name: string(name), fieldType: fieldType, flags: flags})
  392. }
  393. return
  394. }
  395. // Read Packets as Field Packets until EOF-Packet or an Error appears
  396. func (rows *mysqlRows) readRow(dest []driver.Value) (err error) {
  397. data, err := rows.mc.readPacket()
  398. if err != nil {
  399. return
  400. }
  401. // EOF Packet
  402. if data[0] == 254 && len(data) == 5 {
  403. return io.EOF
  404. }
  405. // RowSet Packet
  406. var n int
  407. pos := 0
  408. for i := range dest {
  409. // Read bytes and convert to string
  410. dest[i], n, err = readLengthEnodedString(data[pos:])
  411. pos += n
  412. if err == nil {
  413. continue
  414. }
  415. return // err
  416. }
  417. return
  418. }
  419. // Reads Packets until EOF-Packet or an Error appears. Returns count of Packets read
  420. func (mc *mysqlConn) readUntilEOF() (count uint64, err error) {
  421. var data []byte
  422. for {
  423. data, err = mc.readPacket()
  424. // Err or EOF Packet
  425. if err != nil || (data[0] == 254 && len(data) == 5) {
  426. return
  427. }
  428. count++
  429. }
  430. return
  431. }
  432. /******************************************************************************
  433. * Prepared Statements *
  434. ******************************************************************************/
  435. /* Prepare Result Packets
  436. Type Of Result Packet Hexadecimal Value Of First Byte (field_count)
  437. --------------------- ---------------------------------------------
  438. Prepare OK Packet 00
  439. Error Packet ff
  440. Prepare OK Packet
  441. Bytes Name
  442. ----- ----
  443. 1 0 - marker for OK packet
  444. 4 statement_handler_id
  445. 2 number of columns in result set
  446. 2 number of parameters in query
  447. 1 filler (always 0)
  448. 2 warning count
  449. It is made up of:
  450. a PREPARE_OK packet
  451. if "number of parameters" > 0
  452. (field packets) as in a Result Set Header Packet
  453. (EOF packet)
  454. if "number of columns" > 0
  455. (field packets) as in a Result Set Header Packet
  456. (EOF packet)
  457. */
  458. func (stmt *mysqlStmt) readPrepareResultPacket() (columnCount uint16, err error) {
  459. data, err := stmt.mc.readPacket()
  460. if err != nil {
  461. return
  462. }
  463. // Position
  464. pos := 0
  465. if data[pos] != 0 {
  466. err = stmt.mc.handleErrorPacket(data)
  467. return
  468. }
  469. pos++
  470. stmt.id = binary.LittleEndian.Uint32(data[pos : pos+4])
  471. pos += 4
  472. // Column count [16 bit uint]
  473. columnCount = binary.LittleEndian.Uint16(data[pos : pos+2])
  474. pos += 2
  475. // Param count [16 bit uint]
  476. stmt.paramCount = int(binary.LittleEndian.Uint16(data[pos : pos+2]))
  477. pos += 2
  478. // Warning count [16 bit uint]
  479. // bytesToUint16(data[pos : pos+2])
  480. return
  481. }
  482. /* Command Packet
  483. Bytes Name
  484. ----- ----
  485. 1 code
  486. 4 statement_id
  487. 1 flags
  488. 4 iteration_count
  489. if param_count > 0:
  490. (param_count+7)/8 null_bit_map
  491. 1 new_parameter_bound_flag
  492. if new_params_bound == 1:
  493. n*2 type of parameters
  494. n values for the parameters
  495. */
  496. func (stmt *mysqlStmt) buildExecutePacket(args []driver.Value) error {
  497. argsLen := len(args)
  498. if argsLen != stmt.paramCount {
  499. return fmt.Errorf(
  500. "Arguments count mismatch (Got: %d Has: %d",
  501. argsLen,
  502. stmt.paramCount)
  503. }
  504. // Reset packet-sequence
  505. stmt.mc.sequence = 0
  506. pktLen := 1 + 4 + 1 + 4 + ((stmt.paramCount + 7) >> 3) + 1 + (argsLen << 1)
  507. paramValues := make([][]byte, 0, argsLen)
  508. paramTypes := make([]byte, 0, (argsLen << 1))
  509. bitMask := uint64(0)
  510. var i, valLen int
  511. for i = range args {
  512. // build nullBitMap
  513. if args[i] == nil {
  514. bitMask += 1 << uint(i)
  515. }
  516. // cache types and values
  517. switch args[i].(type) {
  518. case nil:
  519. paramTypes = append(paramTypes, []byte{
  520. byte(FIELD_TYPE_NULL),
  521. 0x0}...)
  522. continue
  523. case int64:
  524. paramTypes = append(paramTypes, []byte{byte(FIELD_TYPE_LONGLONG), 0x0}...)
  525. val := uint64ToBytes(uint64(args[i].(int64)))
  526. pktLen += len(val)
  527. paramValues = append(paramValues, val)
  528. continue
  529. case float64:
  530. paramTypes = append(paramTypes, []byte{byte(FIELD_TYPE_DOUBLE), 0x0}...)
  531. val := uint64ToBytes(math.Float64bits(args[i].(float64)))
  532. pktLen += len(val)
  533. paramValues = append(paramValues, val)
  534. continue
  535. case bool:
  536. paramTypes = append(paramTypes, []byte{byte(FIELD_TYPE_TINY), 0x0}...)
  537. pktLen++
  538. if args[i].(bool) {
  539. paramValues = append(paramValues, []byte{byte(1)})
  540. } else {
  541. paramValues = append(paramValues, []byte{byte(0)})
  542. }
  543. continue
  544. case []byte:
  545. paramTypes = append(paramTypes, []byte{byte(FIELD_TYPE_STRING), 0x0}...)
  546. val := args[i].([]byte)
  547. valLen = len(val)
  548. lcb := lengthEncodedIntegerToBytes(uint64(valLen))
  549. pktLen += len(lcb) + valLen
  550. paramValues = append(paramValues, lcb)
  551. paramValues = append(paramValues, val)
  552. continue
  553. case string:
  554. paramTypes = append(paramTypes, []byte{byte(FIELD_TYPE_STRING), 0x0}...)
  555. val := []byte(args[i].(string))
  556. valLen = len(val)
  557. lcb := lengthEncodedIntegerToBytes(uint64(valLen))
  558. pktLen += valLen + len(lcb)
  559. paramValues = append(paramValues, lcb)
  560. paramValues = append(paramValues, val)
  561. continue
  562. case time.Time:
  563. paramTypes = append(paramTypes, []byte{byte(FIELD_TYPE_STRING), 0x0}...)
  564. val := []byte(args[i].(time.Time).Format(TIME_FORMAT))
  565. valLen = len(val)
  566. lcb := lengthEncodedIntegerToBytes(uint64(valLen))
  567. pktLen += valLen + len(lcb)
  568. paramValues = append(paramValues, lcb)
  569. paramValues = append(paramValues, val)
  570. continue
  571. default:
  572. return fmt.Errorf("Can't convert type: %T", args[i])
  573. }
  574. }
  575. data := make([]byte, 0, pktLen+4)
  576. // Add the packet header
  577. data = append(data, uint24ToBytes(uint32(pktLen))...)
  578. data = append(data, stmt.mc.sequence)
  579. // code [1 byte]
  580. data = append(data, byte(COM_STMT_EXECUTE))
  581. // statement_id [4 bytes]
  582. data = append(data, uint32ToBytes(stmt.id)...)
  583. // flags (0: CURSOR_TYPE_NO_CURSOR) [1 byte]
  584. data = append(data, byte(0))
  585. // iteration_count [4 bytes]
  586. data = append(data, uint32ToBytes(1)...)
  587. // append nullBitMap [(param_count+7)/8 bytes]
  588. if stmt.paramCount > 0 {
  589. // Convert bitMask to bytes
  590. nullBitMap := make([]byte, (stmt.paramCount+7)/8)
  591. for i = 0; i < len(nullBitMap); i++ {
  592. nullBitMap[i] = byte(bitMask >> uint(i*8))
  593. }
  594. data = append(data, nullBitMap...)
  595. }
  596. // newParameterBoundFlag 1 [1 byte]
  597. data = append(data, byte(1))
  598. // type of parameters [n*2 byte]
  599. data = append(data, paramTypes...)
  600. // values for the parameters [n byte]
  601. for _, paramValue := range paramValues {
  602. data = append(data, paramValue...)
  603. }
  604. return stmt.mc.writePacket(data)
  605. }
  606. // http://dev.mysql.com/doc/internals/en/prepared-statements.html#packet-ProtocolBinary::ResultsetRow
  607. func (rc *mysqlRows) readBinaryRow(dest []driver.Value) (err error) {
  608. data, err := rc.mc.readPacket()
  609. if err != nil {
  610. return
  611. }
  612. // EOF Packet
  613. if data[0] == 254 && len(data) == 5 {
  614. return io.EOF
  615. }
  616. // BinaryRowSet Packet
  617. pos := 1 + (len(dest)+7+2)>>3
  618. nullBitMap := data[1:pos]
  619. var n int
  620. var unsigned bool
  621. for i := range dest {
  622. // Field is NULL
  623. if (nullBitMap[(i+2)>>3] >> uint((i+2)&7) & 1) == 1 {
  624. dest[i] = nil
  625. continue
  626. }
  627. unsigned = rc.columns[i].flags&FLAG_UNSIGNED != 0
  628. // Convert to byte-coded string
  629. switch rc.columns[i].fieldType {
  630. case FIELD_TYPE_NULL:
  631. dest[i] = nil
  632. continue
  633. // Numeric Typs
  634. case FIELD_TYPE_TINY:
  635. if unsigned {
  636. dest[i] = uint64(data[pos])
  637. } else {
  638. dest[i] = int64(int8(data[pos]))
  639. }
  640. pos++
  641. continue
  642. case FIELD_TYPE_SHORT, FIELD_TYPE_YEAR:
  643. if unsigned {
  644. dest[i] = uint64(binary.LittleEndian.Uint16(data[pos : pos+2]))
  645. } else {
  646. dest[i] = int64(int16(binary.LittleEndian.Uint16(data[pos : pos+2])))
  647. }
  648. pos += 2
  649. continue
  650. case FIELD_TYPE_INT24, FIELD_TYPE_LONG:
  651. if unsigned {
  652. dest[i] = uint64(binary.LittleEndian.Uint32(data[pos : pos+4]))
  653. } else {
  654. dest[i] = int64(int32(binary.LittleEndian.Uint32(data[pos : pos+4])))
  655. }
  656. pos += 4
  657. continue
  658. case FIELD_TYPE_LONGLONG:
  659. if unsigned {
  660. dest[i] = binary.LittleEndian.Uint64(data[pos : pos+8])
  661. } else {
  662. dest[i] = int64(binary.LittleEndian.Uint64(data[pos : pos+8]))
  663. }
  664. pos += 8
  665. continue
  666. case FIELD_TYPE_FLOAT:
  667. dest[i] = math.Float32frombits(binary.LittleEndian.Uint32(data[pos : pos+4]))
  668. pos += 4
  669. continue
  670. case FIELD_TYPE_DOUBLE:
  671. dest[i] = math.Float64frombits(binary.LittleEndian.Uint64(data[pos : pos+8]))
  672. pos += 8
  673. continue
  674. // Length coded Binary Strings
  675. case FIELD_TYPE_DECIMAL, FIELD_TYPE_NEWDECIMAL, FIELD_TYPE_VARCHAR,
  676. FIELD_TYPE_BIT, FIELD_TYPE_ENUM, FIELD_TYPE_SET,
  677. FIELD_TYPE_TINY_BLOB, FIELD_TYPE_MEDIUM_BLOB, FIELD_TYPE_LONG_BLOB,
  678. FIELD_TYPE_BLOB, FIELD_TYPE_VAR_STRING, FIELD_TYPE_STRING,
  679. FIELD_TYPE_GEOMETRY:
  680. dest[i], n, err = readLengthEnodedString(data[pos:])
  681. pos += n
  682. if err == nil {
  683. continue
  684. }
  685. return // err
  686. // Date YYYY-MM-DD
  687. case FIELD_TYPE_DATE, FIELD_TYPE_NEWDATE:
  688. var num uint64
  689. // TODO(js): allow nil values
  690. num, _, n, err = readLengthEncodedInteger(data[pos:])
  691. if err != nil {
  692. return
  693. }
  694. if num == 0 {
  695. dest[i] = []byte("0000-00-00")
  696. pos += n
  697. continue
  698. } else {
  699. dest[i] = []byte(fmt.Sprintf("%04d-%02d-%02d",
  700. binary.LittleEndian.Uint16(data[pos:pos+2]),
  701. data[pos+2],
  702. data[pos+3]))
  703. pos += n + int(num)
  704. continue
  705. }
  706. // Time HH:MM:SS
  707. case FIELD_TYPE_TIME:
  708. var num uint64
  709. // TODO(js): allow nil values
  710. num, _, n, err = readLengthEncodedInteger(data[pos:])
  711. if err != nil {
  712. return
  713. }
  714. if num == 0 {
  715. dest[i] = []byte("00:00:00")
  716. pos += n
  717. continue
  718. } else {
  719. dest[i] = []byte(fmt.Sprintf("%02d:%02d:%02d",
  720. data[pos+6],
  721. data[pos+7],
  722. data[pos+8]))
  723. pos += n + int(num)
  724. continue
  725. }
  726. // Timestamp YYYY-MM-DD HH:MM:SS
  727. case FIELD_TYPE_TIMESTAMP, FIELD_TYPE_DATETIME:
  728. var num uint64
  729. // TODO(js): allow nil values
  730. num, _, n, err = readLengthEncodedInteger(data[pos:])
  731. if err != nil {
  732. return
  733. }
  734. switch num {
  735. case 0:
  736. dest[i] = []byte("0000-00-00 00:00:00")
  737. pos += n
  738. continue
  739. case 4:
  740. dest[i] = []byte(fmt.Sprintf("%04d-%02d-%02d 00:00:00",
  741. binary.LittleEndian.Uint16(data[pos:pos+2]),
  742. data[pos+2],
  743. data[pos+3]))
  744. pos += n + int(num)
  745. continue
  746. default:
  747. if num < 7 {
  748. return fmt.Errorf("Invalid datetime-packet length %d", num)
  749. }
  750. dest[i] = []byte(fmt.Sprintf("%04d-%02d-%02d %02d:%02d:%02d",
  751. binary.LittleEndian.Uint16(data[pos:pos+2]),
  752. data[pos+2],
  753. data[pos+3],
  754. data[pos+4],
  755. data[pos+5],
  756. data[pos+6]))
  757. pos += n + int(num)
  758. continue
  759. }
  760. // Please report if this happens!
  761. default:
  762. return fmt.Errorf("Unknown FieldType %d", rc.columns[i].fieldType)
  763. }
  764. }
  765. return
  766. }