packets.go 24 KB

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