packets.go 25 KB

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