packets.go 24 KB

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