packets.go 23 KB

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