packets.go 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  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. fmt.Println(e)
  46. e = driver.ErrBadConn
  47. return
  48. }
  49. return
  50. }
  51. // Send Packet with given data
  52. func (mc *mysqlConn) writePacket(data []byte) (e error) {
  53. // Set time BEFORE to avoid possible collisions
  54. if mc.server.keepalive > 0 {
  55. mc.lastCmdTime = time.Now()
  56. }
  57. pktLen := uint32(len(data))
  58. if int(pktLen) == 0 {
  59. return
  60. }
  61. // Add the packet header
  62. pktData := make([]byte, 0, len(data)+4)
  63. pktData = append(pktData, uint24ToBytes(pktLen)...)
  64. pktData = append(pktData, mc.sequence)
  65. pktData = append(pktData, data...)
  66. // Write packet
  67. n, e := mc.netConn.Write(pktData)
  68. if e != nil || n != len(pktData) {
  69. fmt.Println("BadConn:", e)
  70. e = driver.ErrBadConn
  71. return
  72. }
  73. mc.sequence++
  74. return
  75. }
  76. // Read n bytes long number num
  77. func (mc *mysqlConn) readNumber(n uint8) (num uint64, e error) {
  78. // Read bytes into array
  79. buf := make([]byte, n)
  80. nr, err := io.ReadFull(mc.netConn, buf)
  81. if err != nil || nr != int(n) {
  82. fmt.Println(e)
  83. e = driver.ErrBadConn
  84. return
  85. }
  86. // Convert to uint64
  87. num = 0
  88. for i := uint8(0); i < n; i++ {
  89. num |= uint64(buf[i]) << (i * 8)
  90. }
  91. return
  92. }
  93. /******************************************************************************
  94. * Initialisation Process *
  95. ******************************************************************************/
  96. /* Handshake Initialization Packet
  97. Bytes Name
  98. ----- ----
  99. 1 protocol_version
  100. n (Null-Terminated String) server_version
  101. 4 thread_id
  102. 8 scramble_buff
  103. 1 (filler) always 0x00
  104. 2 server_capabilities
  105. 1 server_language
  106. 2 server_status
  107. 2 server capabilities (two upper bytes)
  108. 1 length of the scramble
  109. 10 (filler) always 0
  110. n rest of the plugin provided data (at least 12 bytes)
  111. 1 \0 byte, terminating the second part of a scramble
  112. */
  113. func (mc *mysqlConn) readInitPacket() (e error) {
  114. data, e := mc.readPacket()
  115. if e != nil {
  116. return
  117. }
  118. mc.server = new(serverSettings)
  119. // Position
  120. pos := 0
  121. // Protocol version [8 bit uint]
  122. mc.server.protocol = data[pos]
  123. if mc.server.protocol < MIN_PROTOCOL_VERSION {
  124. e = errors.New(fmt.Sprintf("Unsupported MySQL Protocol Version %d. Protocol Version %d or higher is required", mc.server.protocol, 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 errors.New(fmt.Sprintf("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 errors.New(fmt.Sprintf("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 errors.New(fmt.Sprintf("Invalid arguments count (Got:%d Need: 1)", len(args)))
  245. }
  246. data = append(data, uint32ToBytes(args[0].(uint32))...)
  247. default:
  248. return errors.New(fmt.Sprintf("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 = errors.New(fmt.Sprintf("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. fmt.Println("nil", i, (*args)[i])
  596. bitMask += 1 << uint(i)
  597. }
  598. }
  599. // Convert bitMask to bytes
  600. for i = 0; i < len(nullBitMap); i++ {
  601. nullBitMap[i] = byte(bitMask >> uint(i*8))
  602. }
  603. // append nullBitMap [(param_count+7)/8 bytes]
  604. data = append(data, nullBitMap...)
  605. // Check for changed Params
  606. newParamsBound := true
  607. if stmt.args != nil {
  608. for i := 0; i < len(*args); i++ {
  609. if (*args)[i] != (*stmt.args)[i] {
  610. fmt.Println((*args)[i], "!=", (*stmt.args)[i])
  611. newParamsBound = false
  612. break
  613. }
  614. }
  615. }
  616. // No (new) Parameters bound or rebound
  617. if !newParamsBound {
  618. //newParameterBoundFlag 0 [1 byte]
  619. data = append(data, byte(0))
  620. } else {
  621. // newParameterBoundFlag 1 [1 byte]
  622. data = append(data, byte(1))
  623. // append types and cache values
  624. paramValues := make([]byte, 0)
  625. var pv reflect.Value
  626. for i = 0; i < stmt.paramCount; i++ {
  627. switch (*args)[i].(type) {
  628. case nil:
  629. data = append(data, []byte{
  630. byte(FIELD_TYPE_NULL),
  631. 0x0}...)
  632. continue
  633. case []byte:
  634. data = append(data, []byte{
  635. byte(FIELD_TYPE_STRING),
  636. 0x0}...)
  637. val := (*args)[i].([]byte)
  638. paramValues = append(paramValues, lengthCodedBinaryToBytes(uint64(len(val)))...)
  639. paramValues = append(paramValues, val...)
  640. continue
  641. case time.Time:
  642. // Format to string for time+date Fields
  643. // Data is packed in case reflect.String below
  644. (*args)[i] = (*args)[i].(time.Time).Format(TIME_FORMAT)
  645. }
  646. pv = reflect.ValueOf((*args)[i])
  647. switch pv.Kind() {
  648. case reflect.Int64:
  649. data = append(data, []byte{
  650. byte(FIELD_TYPE_LONGLONG),
  651. 0x0}...)
  652. paramValues = append(paramValues, int64ToBytes(pv.Int())...)
  653. continue
  654. case reflect.Float64:
  655. data = append(data, []byte{
  656. byte(FIELD_TYPE_DOUBLE),
  657. 0x0}...)
  658. paramValues = append(paramValues, float64ToBytes(pv.Float())...)
  659. continue
  660. case reflect.Bool:
  661. data = append(data, []byte{
  662. byte(FIELD_TYPE_TINY),
  663. 0x0}...)
  664. val := pv.Bool()
  665. if val {
  666. paramValues = append(paramValues, byte(1))
  667. } else {
  668. paramValues = append(paramValues, byte(0))
  669. }
  670. continue
  671. case reflect.String:
  672. data = append(data, []byte{
  673. byte(FIELD_TYPE_STRING),
  674. 0x0}...)
  675. val := pv.String()
  676. paramValues = append(paramValues, lengthCodedBinaryToBytes(uint64(len(val)))...)
  677. paramValues = append(paramValues, []byte(val)...)
  678. continue
  679. default:
  680. return fmt.Errorf("Invalid Value: %s", pv.Kind().String())
  681. }
  682. }
  683. // append cached values
  684. data = append(data, paramValues...)
  685. }
  686. // Save args
  687. stmt.args = args
  688. }
  689. return stmt.mc.writePacket(data)
  690. }
  691. func (mc *mysqlConn) readBinaryRows(rc *rowsContent) (e error) {
  692. var data, nullBitMap []byte
  693. var i, pos, n int
  694. var unsigned, isNull bool
  695. columnsCount := len(rc.columns)
  696. for {
  697. data, e = mc.readPacket()
  698. if e != nil {
  699. return
  700. }
  701. pos = 0
  702. // EOF Packet
  703. if data[pos] == 254 && len(data) == 5 {
  704. return
  705. }
  706. pos++
  707. // BinaryRowSet Packet
  708. row := make([]*[]byte, columnsCount)
  709. nullBitMap = data[pos : pos+(columnsCount+7+2)/8]
  710. pos += (columnsCount + 7 + 2) / 8
  711. for i = 0; i < columnsCount; i++ {
  712. // Field is NULL
  713. if (nullBitMap[(i+2)/8] >> uint((i+2)%8) & 1) == 1 {
  714. row[i] = nil
  715. continue
  716. }
  717. unsigned = rc.columns[i].flags&FLAG_UNSIGNED != 0
  718. // Convert to byte-coded string
  719. switch rc.columns[i].fieldType {
  720. case FIELD_TYPE_NULL:
  721. row[i] = nil
  722. // Numeric Typs
  723. case FIELD_TYPE_TINY:
  724. if unsigned {
  725. row[i] = uintToByteStr(uint64(byteToUint8(data[pos])))
  726. } else {
  727. row[i] = intToByteStr(int64(int8(byteToUint8(data[pos]))))
  728. }
  729. pos++
  730. case FIELD_TYPE_SHORT, FIELD_TYPE_YEAR:
  731. if unsigned {
  732. row[i] = uintToByteStr(uint64(bytesToUint16(data[pos : pos+2])))
  733. } else {
  734. row[i] = intToByteStr(int64(int16(bytesToUint16(data[pos : pos+2]))))
  735. }
  736. pos += 2
  737. case FIELD_TYPE_INT24, FIELD_TYPE_LONG:
  738. if unsigned {
  739. row[i] = uintToByteStr(uint64(bytesToUint32(data[pos : pos+4])))
  740. } else {
  741. row[i] = intToByteStr(int64(int32(bytesToUint32(data[pos : pos+4]))))
  742. }
  743. pos += 4
  744. case FIELD_TYPE_LONGLONG:
  745. if unsigned {
  746. row[i] = uintToByteStr(bytesToUint64(data[pos : pos+8]))
  747. } else {
  748. row[i] = intToByteStr(int64(bytesToUint64(data[pos : pos+8])))
  749. }
  750. pos += 8
  751. case FIELD_TYPE_FLOAT:
  752. row[i] = float32ToByteStr(bytesToFloat32(data[pos : pos+4]))
  753. pos += 4
  754. case FIELD_TYPE_DOUBLE:
  755. row[i] = float64ToByteStr(bytesToFloat64(data[pos : pos+8]))
  756. pos += 8
  757. case FIELD_TYPE_DECIMAL, FIELD_TYPE_NEWDECIMAL:
  758. var tmp []byte
  759. tmp, n, isNull, e = readLengthCodedBinary(data[pos:])
  760. if e != nil {
  761. return
  762. }
  763. if isNull && rc.columns[i].flags&FLAG_NOT_NULL == 0 {
  764. row[i] = nil
  765. } else {
  766. row[i] = &tmp
  767. }
  768. pos += n
  769. // Length coded Binary Strings
  770. case FIELD_TYPE_VARCHAR, FIELD_TYPE_BIT, FIELD_TYPE_ENUM,
  771. FIELD_TYPE_SET, FIELD_TYPE_TINY_BLOB, FIELD_TYPE_MEDIUM_BLOB,
  772. FIELD_TYPE_LONG_BLOB, FIELD_TYPE_BLOB, FIELD_TYPE_VAR_STRING,
  773. FIELD_TYPE_STRING, FIELD_TYPE_GEOMETRY:
  774. var tmp []byte
  775. tmp, n, isNull, e = readLengthCodedBinary(data[pos:])
  776. if e != nil {
  777. return
  778. }
  779. if isNull && rc.columns[i].flags&FLAG_NOT_NULL == 0 {
  780. row[i] = nil
  781. } else {
  782. row[i] = &tmp
  783. }
  784. pos += n
  785. // Date YYYY-MM-DD
  786. case FIELD_TYPE_DATE, FIELD_TYPE_NEWDATE:
  787. var num uint64
  788. num, n, e = bytesToLengthCodedBinary(data[pos:])
  789. if e != nil {
  790. return
  791. }
  792. pos += n
  793. var tmp []byte
  794. if num == 0 {
  795. tmp = []byte("0000-00-00")
  796. } else {
  797. tmp = []byte(fmt.Sprintf("%04d-%02d-%02d",
  798. bytesToUint16(data[pos:pos+2]),
  799. data[pos+2],
  800. data[pos+3]))
  801. }
  802. row[i] = &tmp
  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. var tmp []byte
  812. if num == 0 {
  813. tmp = []byte("00:00:00")
  814. } else {
  815. tmp = []byte(fmt.Sprintf("%02d:%02d:%02d",
  816. data[pos+6],
  817. data[pos+7],
  818. data[pos+8]))
  819. }
  820. row[i] = &tmp
  821. pos += n + int(num)
  822. // Timestamp YYYY-MM-DD HH:MM:SS
  823. case FIELD_TYPE_TIMESTAMP, FIELD_TYPE_DATETIME:
  824. var num uint64
  825. num, n, e = bytesToLengthCodedBinary(data[pos:])
  826. if e != nil {
  827. return
  828. }
  829. pos += n
  830. var tmp []byte
  831. if num == 0 {
  832. tmp = []byte("0000-00-00 00:00:00")
  833. } else {
  834. tmp = []byte(fmt.Sprintf("%04d-%02d-%02d %02d:%02d:%02d",
  835. bytesToUint16(data[pos:pos+2]),
  836. data[pos+2],
  837. data[pos+3],
  838. data[pos+4],
  839. data[pos+5],
  840. data[pos+6]))
  841. }
  842. row[i] = &tmp
  843. pos += int(num)
  844. // Please report if this happens!
  845. default:
  846. return fmt.Errorf("Unknown FieldType %d", rc.columns[i].fieldType)
  847. }
  848. }
  849. rc.rows = append(rc.rows, &row)
  850. }
  851. mc.affectedRows = uint64(len(rc.rows))
  852. return
  853. }