packets.go 23 KB

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