packets.go 23 KB

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