packets.go 23 KB

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