packets.go 23 KB

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