packets.go 24 KB

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