packets.go 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408
  1. // Go MySQL Driver - A MySQL-Driver for Go's database/sql package
  2. //
  3. // Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public
  6. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  7. // You can obtain one at http://mozilla.org/MPL/2.0/.
  8. package mysql
  9. import (
  10. "bytes"
  11. "crypto/tls"
  12. "database/sql/driver"
  13. "encoding/binary"
  14. "encoding/json"
  15. "fmt"
  16. "io"
  17. "math"
  18. "strconv"
  19. "time"
  20. )
  21. // Packets documentation:
  22. // http://dev.mysql.com/doc/internals/en/client-server-protocol.html
  23. // Read packet to buffer 'data'
  24. func (mc *mysqlConn) readPacket() ([]byte, error) {
  25. var prevData []byte
  26. for {
  27. // read packet header
  28. data, err := mc.buf.readNext(4)
  29. if err != nil {
  30. if cerr := mc.canceled.Value(); cerr != nil {
  31. return nil, cerr
  32. }
  33. mc.cfg.Logger.Print(err)
  34. mc.Close()
  35. return nil, ErrInvalidConn
  36. }
  37. // packet length [24 bit]
  38. pktLen := int(uint32(data[0]) | uint32(data[1])<<8 | uint32(data[2])<<16)
  39. // check packet sync [8 bit]
  40. if data[3] != mc.sequence {
  41. mc.Close()
  42. if data[3] > mc.sequence {
  43. return nil, ErrPktSyncMul
  44. }
  45. return nil, ErrPktSync
  46. }
  47. mc.sequence++
  48. // packets with length 0 terminate a previous packet which is a
  49. // multiple of (2^24)-1 bytes long
  50. if pktLen == 0 {
  51. // there was no previous packet
  52. if prevData == nil {
  53. mc.cfg.Logger.Print(ErrMalformPkt)
  54. mc.Close()
  55. return nil, ErrInvalidConn
  56. }
  57. return prevData, nil
  58. }
  59. // read packet body [pktLen bytes]
  60. data, err = mc.buf.readNext(pktLen)
  61. if err != nil {
  62. if cerr := mc.canceled.Value(); cerr != nil {
  63. return nil, cerr
  64. }
  65. mc.cfg.Logger.Print(err)
  66. mc.Close()
  67. return nil, ErrInvalidConn
  68. }
  69. // return data if this was the last packet
  70. if pktLen < maxPacketSize {
  71. // zero allocations for non-split packets
  72. if prevData == nil {
  73. return data, nil
  74. }
  75. return append(prevData, data...), nil
  76. }
  77. prevData = append(prevData, data...)
  78. }
  79. }
  80. // Write packet buffer 'data'
  81. func (mc *mysqlConn) writePacket(data []byte) error {
  82. pktLen := len(data) - 4
  83. if pktLen > mc.maxAllowedPacket {
  84. return ErrPktTooLarge
  85. }
  86. for {
  87. var size int
  88. if pktLen >= maxPacketSize {
  89. data[0] = 0xff
  90. data[1] = 0xff
  91. data[2] = 0xff
  92. size = maxPacketSize
  93. } else {
  94. data[0] = byte(pktLen)
  95. data[1] = byte(pktLen >> 8)
  96. data[2] = byte(pktLen >> 16)
  97. size = pktLen
  98. }
  99. data[3] = mc.sequence
  100. // Write packet
  101. if mc.writeTimeout > 0 {
  102. if err := mc.netConn.SetWriteDeadline(time.Now().Add(mc.writeTimeout)); err != nil {
  103. return err
  104. }
  105. }
  106. n, err := mc.netConn.Write(data[:4+size])
  107. if err == nil && n == 4+size {
  108. mc.sequence++
  109. if size != maxPacketSize {
  110. return nil
  111. }
  112. pktLen -= size
  113. data = data[size:]
  114. continue
  115. }
  116. // Handle error
  117. if err == nil { // n != len(data)
  118. mc.cleanup()
  119. mc.cfg.Logger.Print(ErrMalformPkt)
  120. } else {
  121. if cerr := mc.canceled.Value(); cerr != nil {
  122. return cerr
  123. }
  124. if n == 0 && pktLen == len(data)-4 {
  125. // only for the first loop iteration when nothing was written yet
  126. return errBadConnNoWrite
  127. }
  128. mc.cleanup()
  129. mc.cfg.Logger.Print(err)
  130. }
  131. return ErrInvalidConn
  132. }
  133. }
  134. /******************************************************************************
  135. * Initialization Process *
  136. ******************************************************************************/
  137. // Handshake Initialization Packet
  138. // http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::Handshake
  139. func (mc *mysqlConn) readHandshakePacket() (data []byte, plugin string, err error) {
  140. data, err = mc.readPacket()
  141. if err != nil {
  142. // for init we can rewrite this to ErrBadConn for sql.Driver to retry, since
  143. // in connection initialization we don't risk retrying non-idempotent actions.
  144. if err == ErrInvalidConn {
  145. return nil, "", driver.ErrBadConn
  146. }
  147. return
  148. }
  149. if data[0] == iERR {
  150. return nil, "", mc.handleErrorPacket(data)
  151. }
  152. // protocol version [1 byte]
  153. if data[0] < minProtocolVersion {
  154. return nil, "", fmt.Errorf(
  155. "unsupported protocol version %d. Version %d or higher is required",
  156. data[0],
  157. minProtocolVersion,
  158. )
  159. }
  160. // server version [null terminated string]
  161. // connection id [4 bytes]
  162. pos := 1 + bytes.IndexByte(data[1:], 0x00) + 1 + 4
  163. // first part of the password cipher [8 bytes]
  164. authData := data[pos : pos+8]
  165. // (filler) always 0x00 [1 byte]
  166. pos += 8 + 1
  167. // capability flags (lower 2 bytes) [2 bytes]
  168. mc.flags = clientFlag(binary.LittleEndian.Uint16(data[pos : pos+2]))
  169. if mc.flags&clientProtocol41 == 0 {
  170. return nil, "", ErrOldProtocol
  171. }
  172. if mc.flags&clientSSL == 0 && mc.cfg.TLS != nil {
  173. if mc.cfg.AllowFallbackToPlaintext {
  174. mc.cfg.TLS = nil
  175. } else {
  176. return nil, "", ErrNoTLS
  177. }
  178. }
  179. pos += 2
  180. if len(data) > pos {
  181. // character set [1 byte]
  182. // status flags [2 bytes]
  183. // capability flags (upper 2 bytes) [2 bytes]
  184. // length of auth-plugin-data [1 byte]
  185. // reserved (all [00]) [10 bytes]
  186. pos += 1 + 2 + 2 + 1 + 10
  187. // second part of the password cipher [minimum 13 bytes],
  188. // where len=MAX(13, length of auth-plugin-data - 8)
  189. //
  190. // The web documentation is ambiguous about the length. However,
  191. // according to mysql-5.7/sql/auth/sql_authentication.cc line 538,
  192. // the 13th byte is "\0 byte, terminating the second part of
  193. // a scramble". So the second part of the password cipher is
  194. // a NULL terminated string that's at least 13 bytes with the
  195. // last byte being NULL.
  196. //
  197. // The official Python library uses the fixed length 12
  198. // which seems to work but technically could have a hidden bug.
  199. authData = append(authData, data[pos:pos+12]...)
  200. pos += 13
  201. // EOF if version (>= 5.5.7 and < 5.5.10) or (>= 5.6.0 and < 5.6.2)
  202. // \NUL otherwise
  203. if end := bytes.IndexByte(data[pos:], 0x00); end != -1 {
  204. plugin = string(data[pos : pos+end])
  205. } else {
  206. plugin = string(data[pos:])
  207. }
  208. // make a memory safe copy of the cipher slice
  209. var b [20]byte
  210. copy(b[:], authData)
  211. return b[:], plugin, nil
  212. }
  213. // make a memory safe copy of the cipher slice
  214. var b [8]byte
  215. copy(b[:], authData)
  216. return b[:], plugin, nil
  217. }
  218. // Client Authentication Packet
  219. // http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::HandshakeResponse
  220. func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, plugin string) error {
  221. // Adjust client flags based on server support
  222. clientFlags := clientProtocol41 |
  223. clientSecureConn |
  224. clientLongPassword |
  225. clientTransactions |
  226. clientLocalFiles |
  227. clientPluginAuth |
  228. clientMultiResults |
  229. clientConnectAttrs |
  230. mc.flags&clientLongFlag
  231. if mc.cfg.ClientFoundRows {
  232. clientFlags |= clientFoundRows
  233. }
  234. // To enable TLS / SSL
  235. if mc.cfg.TLS != nil {
  236. clientFlags |= clientSSL
  237. }
  238. if mc.cfg.MultiStatements {
  239. clientFlags |= clientMultiStatements
  240. }
  241. // encode length of the auth plugin data
  242. var authRespLEIBuf [9]byte
  243. authRespLen := len(authResp)
  244. authRespLEI := appendLengthEncodedInteger(authRespLEIBuf[:0], uint64(authRespLen))
  245. if len(authRespLEI) > 1 {
  246. // if the length can not be written in 1 byte, it must be written as a
  247. // length encoded integer
  248. clientFlags |= clientPluginAuthLenEncClientData
  249. }
  250. pktLen := 4 + 4 + 1 + 23 + len(mc.cfg.User) + 1 + len(authRespLEI) + len(authResp) + 21 + 1
  251. // To specify a db name
  252. if n := len(mc.cfg.DBName); n > 0 {
  253. clientFlags |= clientConnectWithDB
  254. pktLen += n + 1
  255. }
  256. // encode length of the connection attributes
  257. var connAttrsLEIBuf [9]byte
  258. connAttrsLen := len(mc.connector.encodedAttributes)
  259. connAttrsLEI := appendLengthEncodedInteger(connAttrsLEIBuf[:0], uint64(connAttrsLen))
  260. pktLen += len(connAttrsLEI) + len(mc.connector.encodedAttributes)
  261. // Calculate packet length and get buffer with that size
  262. data, err := mc.buf.takeBuffer(pktLen + 4)
  263. if err != nil {
  264. // cannot take the buffer. Something must be wrong with the connection
  265. mc.cfg.Logger.Print(err)
  266. return errBadConnNoWrite
  267. }
  268. // ClientFlags [32 bit]
  269. data[4] = byte(clientFlags)
  270. data[5] = byte(clientFlags >> 8)
  271. data[6] = byte(clientFlags >> 16)
  272. data[7] = byte(clientFlags >> 24)
  273. // MaxPacketSize [32 bit] (none)
  274. data[8] = 0x00
  275. data[9] = 0x00
  276. data[10] = 0x00
  277. data[11] = 0x00
  278. // Collation ID [1 byte]
  279. cname := mc.cfg.Collation
  280. if cname == "" {
  281. cname = defaultCollation
  282. }
  283. var found bool
  284. data[12], found = collations[cname]
  285. if !found {
  286. // Note possibility for false negatives:
  287. // could be triggered although the collation is valid if the
  288. // collations map does not contain entries the server supports.
  289. return fmt.Errorf("unknown collation: %q", cname)
  290. }
  291. // Filler [23 bytes] (all 0x00)
  292. pos := 13
  293. for ; pos < 13+23; pos++ {
  294. data[pos] = 0
  295. }
  296. // SSL Connection Request Packet
  297. // http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::SSLRequest
  298. if mc.cfg.TLS != nil {
  299. // Send TLS / SSL request packet
  300. if err := mc.writePacket(data[:(4+4+1+23)+4]); err != nil {
  301. return err
  302. }
  303. // Switch to TLS
  304. tlsConn := tls.Client(mc.netConn, mc.cfg.TLS)
  305. if err := tlsConn.Handshake(); err != nil {
  306. return err
  307. }
  308. mc.rawConn = mc.netConn
  309. mc.netConn = tlsConn
  310. mc.buf.nc = tlsConn
  311. }
  312. // User [null terminated string]
  313. if len(mc.cfg.User) > 0 {
  314. pos += copy(data[pos:], mc.cfg.User)
  315. }
  316. data[pos] = 0x00
  317. pos++
  318. // Auth Data [length encoded integer]
  319. pos += copy(data[pos:], authRespLEI)
  320. pos += copy(data[pos:], authResp)
  321. // Databasename [null terminated string]
  322. if len(mc.cfg.DBName) > 0 {
  323. pos += copy(data[pos:], mc.cfg.DBName)
  324. data[pos] = 0x00
  325. pos++
  326. }
  327. pos += copy(data[pos:], plugin)
  328. data[pos] = 0x00
  329. pos++
  330. // Connection Attributes
  331. pos += copy(data[pos:], connAttrsLEI)
  332. pos += copy(data[pos:], []byte(mc.connector.encodedAttributes))
  333. // Send Auth packet
  334. return mc.writePacket(data[:pos])
  335. }
  336. // http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchResponse
  337. func (mc *mysqlConn) writeAuthSwitchPacket(authData []byte) error {
  338. pktLen := 4 + len(authData)
  339. data, err := mc.buf.takeSmallBuffer(pktLen)
  340. if err != nil {
  341. // cannot take the buffer. Something must be wrong with the connection
  342. mc.cfg.Logger.Print(err)
  343. return errBadConnNoWrite
  344. }
  345. // Add the auth data [EOF]
  346. copy(data[4:], authData)
  347. return mc.writePacket(data)
  348. }
  349. /******************************************************************************
  350. * Command Packets *
  351. ******************************************************************************/
  352. func (mc *mysqlConn) writeCommandPacket(command byte) error {
  353. // Reset Packet Sequence
  354. mc.sequence = 0
  355. data, err := mc.buf.takeSmallBuffer(4 + 1)
  356. if err != nil {
  357. // cannot take the buffer. Something must be wrong with the connection
  358. mc.cfg.Logger.Print(err)
  359. return errBadConnNoWrite
  360. }
  361. // Add command byte
  362. data[4] = command
  363. // Send CMD packet
  364. return mc.writePacket(data)
  365. }
  366. func (mc *mysqlConn) writeCommandPacketStr(command byte, arg string) error {
  367. // Reset Packet Sequence
  368. mc.sequence = 0
  369. pktLen := 1 + len(arg)
  370. data, err := mc.buf.takeBuffer(pktLen + 4)
  371. if err != nil {
  372. // cannot take the buffer. Something must be wrong with the connection
  373. mc.cfg.Logger.Print(err)
  374. return errBadConnNoWrite
  375. }
  376. // Add command byte
  377. data[4] = command
  378. // Add arg
  379. copy(data[5:], arg)
  380. // Send CMD packet
  381. return mc.writePacket(data)
  382. }
  383. func (mc *mysqlConn) writeCommandPacketUint32(command byte, arg uint32) error {
  384. // Reset Packet Sequence
  385. mc.sequence = 0
  386. data, err := mc.buf.takeSmallBuffer(4 + 1 + 4)
  387. if err != nil {
  388. // cannot take the buffer. Something must be wrong with the connection
  389. mc.cfg.Logger.Print(err)
  390. return errBadConnNoWrite
  391. }
  392. // Add command byte
  393. data[4] = command
  394. // Add arg [32 bit]
  395. data[5] = byte(arg)
  396. data[6] = byte(arg >> 8)
  397. data[7] = byte(arg >> 16)
  398. data[8] = byte(arg >> 24)
  399. // Send CMD packet
  400. return mc.writePacket(data)
  401. }
  402. /******************************************************************************
  403. * Result Packets *
  404. ******************************************************************************/
  405. func (mc *mysqlConn) readAuthResult() ([]byte, string, error) {
  406. data, err := mc.readPacket()
  407. if err != nil {
  408. return nil, "", err
  409. }
  410. // packet indicator
  411. switch data[0] {
  412. case iOK:
  413. // resultUnchanged, since auth happens before any queries or
  414. // commands have been executed.
  415. return nil, "", mc.resultUnchanged().handleOkPacket(data)
  416. case iAuthMoreData:
  417. return data[1:], "", err
  418. case iEOF:
  419. if len(data) == 1 {
  420. // https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::OldAuthSwitchRequest
  421. return nil, "mysql_old_password", nil
  422. }
  423. pluginEndIndex := bytes.IndexByte(data, 0x00)
  424. if pluginEndIndex < 0 {
  425. return nil, "", ErrMalformPkt
  426. }
  427. plugin := string(data[1:pluginEndIndex])
  428. authData := data[pluginEndIndex+1:]
  429. return authData, plugin, nil
  430. default: // Error otherwise
  431. return nil, "", mc.handleErrorPacket(data)
  432. }
  433. }
  434. // Returns error if Packet is not a 'Result OK'-Packet
  435. func (mc *okHandler) readResultOK() error {
  436. data, err := mc.conn().readPacket()
  437. if err != nil {
  438. return err
  439. }
  440. if data[0] == iOK {
  441. return mc.handleOkPacket(data)
  442. }
  443. return mc.conn().handleErrorPacket(data)
  444. }
  445. // Result Set Header Packet
  446. // http://dev.mysql.com/doc/internals/en/com-query-response.html#packet-ProtocolText::Resultset
  447. func (mc *okHandler) readResultSetHeaderPacket() (int, error) {
  448. // handleOkPacket replaces both values; other cases leave the values unchanged.
  449. mc.result.affectedRows = append(mc.result.affectedRows, 0)
  450. mc.result.insertIds = append(mc.result.insertIds, 0)
  451. data, err := mc.conn().readPacket()
  452. if err == nil {
  453. switch data[0] {
  454. case iOK:
  455. return 0, mc.handleOkPacket(data)
  456. case iERR:
  457. return 0, mc.conn().handleErrorPacket(data)
  458. case iLocalInFile:
  459. return 0, mc.handleInFileRequest(string(data[1:]))
  460. }
  461. // column count
  462. num, _, _ := readLengthEncodedInteger(data)
  463. // ignore remaining data in the packet. see #1478.
  464. return int(num), nil
  465. }
  466. return 0, err
  467. }
  468. // Error Packet
  469. // http://dev.mysql.com/doc/internals/en/generic-response-packets.html#packet-ERR_Packet
  470. func (mc *mysqlConn) handleErrorPacket(data []byte) error {
  471. if data[0] != iERR {
  472. return ErrMalformPkt
  473. }
  474. // 0xff [1 byte]
  475. // Error Number [16 bit uint]
  476. errno := binary.LittleEndian.Uint16(data[1:3])
  477. // 1792: ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
  478. // 1290: ER_OPTION_PREVENTS_STATEMENT (returned by Aurora during failover)
  479. if (errno == 1792 || errno == 1290) && mc.cfg.RejectReadOnly {
  480. // Oops; we are connected to a read-only connection, and won't be able
  481. // to issue any write statements. Since RejectReadOnly is configured,
  482. // we throw away this connection hoping this one would have write
  483. // permission. This is specifically for a possible race condition
  484. // during failover (e.g. on AWS Aurora). See README.md for more.
  485. //
  486. // We explicitly close the connection before returning
  487. // driver.ErrBadConn to ensure that `database/sql` purges this
  488. // connection and initiates a new one for next statement next time.
  489. mc.Close()
  490. return driver.ErrBadConn
  491. }
  492. me := &MySQLError{Number: errno}
  493. pos := 3
  494. // SQL State [optional: # + 5bytes string]
  495. if data[3] == 0x23 {
  496. copy(me.SQLState[:], data[4:4+5])
  497. pos = 9
  498. }
  499. // Error Message [string]
  500. me.Message = string(data[pos:])
  501. return me
  502. }
  503. func readStatus(b []byte) statusFlag {
  504. return statusFlag(b[0]) | statusFlag(b[1])<<8
  505. }
  506. // Returns an instance of okHandler for codepaths where mysqlConn.result doesn't
  507. // need to be cleared first (e.g. during authentication, or while additional
  508. // resultsets are being fetched.)
  509. func (mc *mysqlConn) resultUnchanged() *okHandler {
  510. return (*okHandler)(mc)
  511. }
  512. // okHandler represents the state of the connection when mysqlConn.result has
  513. // been prepared for processing of OK packets.
  514. //
  515. // To correctly populate mysqlConn.result (updated by handleOkPacket()), all
  516. // callpaths must either:
  517. //
  518. // 1. first clear it using clearResult(), or
  519. // 2. confirm that they don't need to (by calling resultUnchanged()).
  520. //
  521. // Both return an instance of type *okHandler.
  522. type okHandler mysqlConn
  523. // Exposes the underlying type's methods.
  524. func (mc *okHandler) conn() *mysqlConn {
  525. return (*mysqlConn)(mc)
  526. }
  527. // clearResult clears the connection's stored affectedRows and insertIds
  528. // fields.
  529. //
  530. // It returns a handler that can process OK responses.
  531. func (mc *mysqlConn) clearResult() *okHandler {
  532. mc.result = mysqlResult{}
  533. return (*okHandler)(mc)
  534. }
  535. // Ok Packet
  536. // http://dev.mysql.com/doc/internals/en/generic-response-packets.html#packet-OK_Packet
  537. func (mc *okHandler) handleOkPacket(data []byte) error {
  538. var n, m int
  539. var affectedRows, insertId uint64
  540. // 0x00 [1 byte]
  541. // Affected rows [Length Coded Binary]
  542. affectedRows, _, n = readLengthEncodedInteger(data[1:])
  543. // Insert id [Length Coded Binary]
  544. insertId, _, m = readLengthEncodedInteger(data[1+n:])
  545. // Update for the current statement result (only used by
  546. // readResultSetHeaderPacket).
  547. if len(mc.result.affectedRows) > 0 {
  548. mc.result.affectedRows[len(mc.result.affectedRows)-1] = int64(affectedRows)
  549. }
  550. if len(mc.result.insertIds) > 0 {
  551. mc.result.insertIds[len(mc.result.insertIds)-1] = int64(insertId)
  552. }
  553. // server_status [2 bytes]
  554. mc.status = readStatus(data[1+n+m : 1+n+m+2])
  555. if mc.status&statusMoreResultsExists != 0 {
  556. return nil
  557. }
  558. // warning count [2 bytes]
  559. return nil
  560. }
  561. // Read Packets as Field Packets until EOF-Packet or an Error appears
  562. // http://dev.mysql.com/doc/internals/en/com-query-response.html#packet-Protocol::ColumnDefinition41
  563. func (mc *mysqlConn) readColumns(count int) ([]mysqlField, error) {
  564. columns := make([]mysqlField, count)
  565. for i := 0; ; i++ {
  566. data, err := mc.readPacket()
  567. if err != nil {
  568. return nil, err
  569. }
  570. // EOF Packet
  571. if data[0] == iEOF && (len(data) == 5 || len(data) == 1) {
  572. if i == count {
  573. return columns, nil
  574. }
  575. return nil, fmt.Errorf("column count mismatch n:%d len:%d", count, len(columns))
  576. }
  577. // Catalog
  578. pos, err := skipLengthEncodedString(data)
  579. if err != nil {
  580. return nil, err
  581. }
  582. // Database [len coded string]
  583. n, err := skipLengthEncodedString(data[pos:])
  584. if err != nil {
  585. return nil, err
  586. }
  587. pos += n
  588. // Table [len coded string]
  589. if mc.cfg.ColumnsWithAlias {
  590. tableName, _, n, err := readLengthEncodedString(data[pos:])
  591. if err != nil {
  592. return nil, err
  593. }
  594. pos += n
  595. columns[i].tableName = string(tableName)
  596. } else {
  597. n, err = skipLengthEncodedString(data[pos:])
  598. if err != nil {
  599. return nil, err
  600. }
  601. pos += n
  602. }
  603. // Original table [len coded string]
  604. n, err = skipLengthEncodedString(data[pos:])
  605. if err != nil {
  606. return nil, err
  607. }
  608. pos += n
  609. // Name [len coded string]
  610. name, _, n, err := readLengthEncodedString(data[pos:])
  611. if err != nil {
  612. return nil, err
  613. }
  614. columns[i].name = string(name)
  615. pos += n
  616. // Original name [len coded string]
  617. n, err = skipLengthEncodedString(data[pos:])
  618. if err != nil {
  619. return nil, err
  620. }
  621. pos += n
  622. // Filler [uint8]
  623. pos++
  624. // Charset [charset, collation uint8]
  625. columns[i].charSet = data[pos]
  626. pos += 2
  627. // Length [uint32]
  628. columns[i].length = binary.LittleEndian.Uint32(data[pos : pos+4])
  629. pos += 4
  630. // Field type [uint8]
  631. columns[i].fieldType = fieldType(data[pos])
  632. pos++
  633. // Flags [uint16]
  634. columns[i].flags = fieldFlag(binary.LittleEndian.Uint16(data[pos : pos+2]))
  635. pos += 2
  636. // Decimals [uint8]
  637. columns[i].decimals = data[pos]
  638. //pos++
  639. // Default value [len coded binary]
  640. //if pos < len(data) {
  641. // defaultVal, _, err = bytesToLengthCodedBinary(data[pos:])
  642. //}
  643. }
  644. }
  645. // Read Packets as Field Packets until EOF-Packet or an Error appears
  646. // http://dev.mysql.com/doc/internals/en/com-query-response.html#packet-ProtocolText::ResultsetRow
  647. func (rows *textRows) readRow(dest []driver.Value) error {
  648. mc := rows.mc
  649. if rows.rs.done {
  650. return io.EOF
  651. }
  652. data, err := mc.readPacket()
  653. if err != nil {
  654. return err
  655. }
  656. // EOF Packet
  657. if data[0] == iEOF && len(data) == 5 {
  658. // server_status [2 bytes]
  659. rows.mc.status = readStatus(data[3:])
  660. rows.rs.done = true
  661. if !rows.HasNextResultSet() {
  662. rows.mc = nil
  663. }
  664. return io.EOF
  665. }
  666. if data[0] == iERR {
  667. rows.mc = nil
  668. return mc.handleErrorPacket(data)
  669. }
  670. // RowSet Packet
  671. var (
  672. n int
  673. isNull bool
  674. pos int = 0
  675. )
  676. for i := range dest {
  677. // Read bytes and convert to string
  678. var buf []byte
  679. buf, isNull, n, err = readLengthEncodedString(data[pos:])
  680. pos += n
  681. if err != nil {
  682. return err
  683. }
  684. if isNull {
  685. dest[i] = nil
  686. continue
  687. }
  688. switch rows.rs.columns[i].fieldType {
  689. case fieldTypeTimestamp,
  690. fieldTypeDateTime,
  691. fieldTypeDate,
  692. fieldTypeNewDate:
  693. if mc.parseTime {
  694. dest[i], err = parseDateTime(buf, mc.cfg.Loc)
  695. } else {
  696. dest[i] = buf
  697. }
  698. case fieldTypeTiny, fieldTypeShort, fieldTypeInt24, fieldTypeYear, fieldTypeLong:
  699. dest[i], err = strconv.ParseInt(string(buf), 10, 64)
  700. case fieldTypeLongLong:
  701. if rows.rs.columns[i].flags&flagUnsigned != 0 {
  702. dest[i], err = strconv.ParseUint(string(buf), 10, 64)
  703. } else {
  704. dest[i], err = strconv.ParseInt(string(buf), 10, 64)
  705. }
  706. case fieldTypeFloat:
  707. var d float64
  708. d, err = strconv.ParseFloat(string(buf), 32)
  709. dest[i] = float32(d)
  710. case fieldTypeDouble:
  711. dest[i], err = strconv.ParseFloat(string(buf), 64)
  712. default:
  713. dest[i] = buf
  714. }
  715. if err != nil {
  716. return err
  717. }
  718. }
  719. return nil
  720. }
  721. // Reads Packets until EOF-Packet or an Error appears. Returns count of Packets read
  722. func (mc *mysqlConn) readUntilEOF() error {
  723. for {
  724. data, err := mc.readPacket()
  725. if err != nil {
  726. return err
  727. }
  728. switch data[0] {
  729. case iERR:
  730. return mc.handleErrorPacket(data)
  731. case iEOF:
  732. if len(data) == 5 {
  733. mc.status = readStatus(data[3:])
  734. }
  735. return nil
  736. }
  737. }
  738. }
  739. /******************************************************************************
  740. * Prepared Statements *
  741. ******************************************************************************/
  742. // Prepare Result Packets
  743. // http://dev.mysql.com/doc/internals/en/com-stmt-prepare-response.html
  744. func (stmt *mysqlStmt) readPrepareResultPacket() (uint16, error) {
  745. data, err := stmt.mc.readPacket()
  746. if err == nil {
  747. // packet indicator [1 byte]
  748. if data[0] != iOK {
  749. return 0, stmt.mc.handleErrorPacket(data)
  750. }
  751. // statement id [4 bytes]
  752. stmt.id = binary.LittleEndian.Uint32(data[1:5])
  753. // Column count [16 bit uint]
  754. columnCount := binary.LittleEndian.Uint16(data[5:7])
  755. // Param count [16 bit uint]
  756. stmt.paramCount = int(binary.LittleEndian.Uint16(data[7:9]))
  757. // Reserved [8 bit]
  758. // Warning count [16 bit uint]
  759. return columnCount, nil
  760. }
  761. return 0, err
  762. }
  763. // http://dev.mysql.com/doc/internals/en/com-stmt-send-long-data.html
  764. func (stmt *mysqlStmt) writeCommandLongData(paramID int, arg []byte) error {
  765. maxLen := stmt.mc.maxAllowedPacket - 1
  766. pktLen := maxLen
  767. // After the header (bytes 0-3) follows before the data:
  768. // 1 byte command
  769. // 4 bytes stmtID
  770. // 2 bytes paramID
  771. const dataOffset = 1 + 4 + 2
  772. // Cannot use the write buffer since
  773. // a) the buffer is too small
  774. // b) it is in use
  775. data := make([]byte, 4+1+4+2+len(arg))
  776. copy(data[4+dataOffset:], arg)
  777. for argLen := len(arg); argLen > 0; argLen -= pktLen - dataOffset {
  778. if dataOffset+argLen < maxLen {
  779. pktLen = dataOffset + argLen
  780. }
  781. stmt.mc.sequence = 0
  782. // Add command byte [1 byte]
  783. data[4] = comStmtSendLongData
  784. // Add stmtID [32 bit]
  785. data[5] = byte(stmt.id)
  786. data[6] = byte(stmt.id >> 8)
  787. data[7] = byte(stmt.id >> 16)
  788. data[8] = byte(stmt.id >> 24)
  789. // Add paramID [16 bit]
  790. data[9] = byte(paramID)
  791. data[10] = byte(paramID >> 8)
  792. // Send CMD packet
  793. err := stmt.mc.writePacket(data[:4+pktLen])
  794. if err == nil {
  795. data = data[pktLen-dataOffset:]
  796. continue
  797. }
  798. return err
  799. }
  800. // Reset Packet Sequence
  801. stmt.mc.sequence = 0
  802. return nil
  803. }
  804. // Execute Prepared Statement
  805. // http://dev.mysql.com/doc/internals/en/com-stmt-execute.html
  806. func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
  807. if len(args) != stmt.paramCount {
  808. return fmt.Errorf(
  809. "argument count mismatch (got: %d; has: %d)",
  810. len(args),
  811. stmt.paramCount,
  812. )
  813. }
  814. const minPktLen = 4 + 1 + 4 + 1 + 4
  815. mc := stmt.mc
  816. // Determine threshold dynamically to avoid packet size shortage.
  817. longDataSize := mc.maxAllowedPacket / (stmt.paramCount + 1)
  818. if longDataSize < 64 {
  819. longDataSize = 64
  820. }
  821. // Reset packet-sequence
  822. mc.sequence = 0
  823. var data []byte
  824. var err error
  825. if len(args) == 0 {
  826. data, err = mc.buf.takeBuffer(minPktLen)
  827. } else {
  828. data, err = mc.buf.takeCompleteBuffer()
  829. // In this case the len(data) == cap(data) which is used to optimise the flow below.
  830. }
  831. if err != nil {
  832. // cannot take the buffer. Something must be wrong with the connection
  833. mc.cfg.Logger.Print(err)
  834. return errBadConnNoWrite
  835. }
  836. // command [1 byte]
  837. data[4] = comStmtExecute
  838. // statement_id [4 bytes]
  839. data[5] = byte(stmt.id)
  840. data[6] = byte(stmt.id >> 8)
  841. data[7] = byte(stmt.id >> 16)
  842. data[8] = byte(stmt.id >> 24)
  843. // flags (0: CURSOR_TYPE_NO_CURSOR) [1 byte]
  844. data[9] = 0x00
  845. // iteration_count (uint32(1)) [4 bytes]
  846. data[10] = 0x01
  847. data[11] = 0x00
  848. data[12] = 0x00
  849. data[13] = 0x00
  850. if len(args) > 0 {
  851. pos := minPktLen
  852. var nullMask []byte
  853. if maskLen, typesLen := (len(args)+7)/8, 1+2*len(args); pos+maskLen+typesLen >= cap(data) {
  854. // buffer has to be extended but we don't know by how much so
  855. // we depend on append after all data with known sizes fit.
  856. // We stop at that because we deal with a lot of columns here
  857. // which makes the required allocation size hard to guess.
  858. tmp := make([]byte, pos+maskLen+typesLen)
  859. copy(tmp[:pos], data[:pos])
  860. data = tmp
  861. nullMask = data[pos : pos+maskLen]
  862. // No need to clean nullMask as make ensures that.
  863. pos += maskLen
  864. } else {
  865. nullMask = data[pos : pos+maskLen]
  866. for i := range nullMask {
  867. nullMask[i] = 0
  868. }
  869. pos += maskLen
  870. }
  871. // newParameterBoundFlag 1 [1 byte]
  872. data[pos] = 0x01
  873. pos++
  874. // type of each parameter [len(args)*2 bytes]
  875. paramTypes := data[pos:]
  876. pos += len(args) * 2
  877. // value of each parameter [n bytes]
  878. paramValues := data[pos:pos]
  879. valuesCap := cap(paramValues)
  880. for i, arg := range args {
  881. // build NULL-bitmap
  882. if arg == nil {
  883. nullMask[i/8] |= 1 << (uint(i) & 7)
  884. paramTypes[i+i] = byte(fieldTypeNULL)
  885. paramTypes[i+i+1] = 0x00
  886. continue
  887. }
  888. if v, ok := arg.(json.RawMessage); ok {
  889. arg = []byte(v)
  890. }
  891. // cache types and values
  892. switch v := arg.(type) {
  893. case int64:
  894. paramTypes[i+i] = byte(fieldTypeLongLong)
  895. paramTypes[i+i+1] = 0x00
  896. if cap(paramValues)-len(paramValues)-8 >= 0 {
  897. paramValues = paramValues[:len(paramValues)+8]
  898. binary.LittleEndian.PutUint64(
  899. paramValues[len(paramValues)-8:],
  900. uint64(v),
  901. )
  902. } else {
  903. paramValues = append(paramValues,
  904. uint64ToBytes(uint64(v))...,
  905. )
  906. }
  907. case uint64:
  908. paramTypes[i+i] = byte(fieldTypeLongLong)
  909. paramTypes[i+i+1] = 0x80 // type is unsigned
  910. if cap(paramValues)-len(paramValues)-8 >= 0 {
  911. paramValues = paramValues[:len(paramValues)+8]
  912. binary.LittleEndian.PutUint64(
  913. paramValues[len(paramValues)-8:],
  914. uint64(v),
  915. )
  916. } else {
  917. paramValues = append(paramValues,
  918. uint64ToBytes(uint64(v))...,
  919. )
  920. }
  921. case float64:
  922. paramTypes[i+i] = byte(fieldTypeDouble)
  923. paramTypes[i+i+1] = 0x00
  924. if cap(paramValues)-len(paramValues)-8 >= 0 {
  925. paramValues = paramValues[:len(paramValues)+8]
  926. binary.LittleEndian.PutUint64(
  927. paramValues[len(paramValues)-8:],
  928. math.Float64bits(v),
  929. )
  930. } else {
  931. paramValues = append(paramValues,
  932. uint64ToBytes(math.Float64bits(v))...,
  933. )
  934. }
  935. case bool:
  936. paramTypes[i+i] = byte(fieldTypeTiny)
  937. paramTypes[i+i+1] = 0x00
  938. if v {
  939. paramValues = append(paramValues, 0x01)
  940. } else {
  941. paramValues = append(paramValues, 0x00)
  942. }
  943. case []byte:
  944. // Common case (non-nil value) first
  945. if v != nil {
  946. paramTypes[i+i] = byte(fieldTypeString)
  947. paramTypes[i+i+1] = 0x00
  948. if len(v) < longDataSize {
  949. paramValues = appendLengthEncodedInteger(paramValues,
  950. uint64(len(v)),
  951. )
  952. paramValues = append(paramValues, v...)
  953. } else {
  954. if err := stmt.writeCommandLongData(i, v); err != nil {
  955. return err
  956. }
  957. }
  958. continue
  959. }
  960. // Handle []byte(nil) as a NULL value
  961. nullMask[i/8] |= 1 << (uint(i) & 7)
  962. paramTypes[i+i] = byte(fieldTypeNULL)
  963. paramTypes[i+i+1] = 0x00
  964. case string:
  965. paramTypes[i+i] = byte(fieldTypeString)
  966. paramTypes[i+i+1] = 0x00
  967. if len(v) < longDataSize {
  968. paramValues = appendLengthEncodedInteger(paramValues,
  969. uint64(len(v)),
  970. )
  971. paramValues = append(paramValues, v...)
  972. } else {
  973. if err := stmt.writeCommandLongData(i, []byte(v)); err != nil {
  974. return err
  975. }
  976. }
  977. case time.Time:
  978. paramTypes[i+i] = byte(fieldTypeString)
  979. paramTypes[i+i+1] = 0x00
  980. var a [64]byte
  981. var b = a[:0]
  982. if v.IsZero() {
  983. b = append(b, "0000-00-00"...)
  984. } else {
  985. b, err = appendDateTime(b, v.In(mc.cfg.Loc), mc.cfg.timeTruncate)
  986. if err != nil {
  987. return err
  988. }
  989. }
  990. paramValues = appendLengthEncodedInteger(paramValues,
  991. uint64(len(b)),
  992. )
  993. paramValues = append(paramValues, b...)
  994. default:
  995. return fmt.Errorf("cannot convert type: %T", arg)
  996. }
  997. }
  998. // Check if param values exceeded the available buffer
  999. // In that case we must build the data packet with the new values buffer
  1000. if valuesCap != cap(paramValues) {
  1001. data = append(data[:pos], paramValues...)
  1002. if err = mc.buf.store(data); err != nil {
  1003. mc.cfg.Logger.Print(err)
  1004. return errBadConnNoWrite
  1005. }
  1006. }
  1007. pos += len(paramValues)
  1008. data = data[:pos]
  1009. }
  1010. return mc.writePacket(data)
  1011. }
  1012. // For each remaining resultset in the stream, discards its rows and updates
  1013. // mc.affectedRows and mc.insertIds.
  1014. func (mc *okHandler) discardResults() error {
  1015. for mc.status&statusMoreResultsExists != 0 {
  1016. resLen, err := mc.readResultSetHeaderPacket()
  1017. if err != nil {
  1018. return err
  1019. }
  1020. if resLen > 0 {
  1021. // columns
  1022. if err := mc.conn().readUntilEOF(); err != nil {
  1023. return err
  1024. }
  1025. // rows
  1026. if err := mc.conn().readUntilEOF(); err != nil {
  1027. return err
  1028. }
  1029. }
  1030. }
  1031. return nil
  1032. }
  1033. // http://dev.mysql.com/doc/internals/en/binary-protocol-resultset-row.html
  1034. func (rows *binaryRows) readRow(dest []driver.Value) error {
  1035. data, err := rows.mc.readPacket()
  1036. if err != nil {
  1037. return err
  1038. }
  1039. // packet indicator [1 byte]
  1040. if data[0] != iOK {
  1041. // EOF Packet
  1042. if data[0] == iEOF && len(data) == 5 {
  1043. rows.mc.status = readStatus(data[3:])
  1044. rows.rs.done = true
  1045. if !rows.HasNextResultSet() {
  1046. rows.mc = nil
  1047. }
  1048. return io.EOF
  1049. }
  1050. mc := rows.mc
  1051. rows.mc = nil
  1052. // Error otherwise
  1053. return mc.handleErrorPacket(data)
  1054. }
  1055. // NULL-bitmap, [(column-count + 7 + 2) / 8 bytes]
  1056. pos := 1 + (len(dest)+7+2)>>3
  1057. nullMask := data[1:pos]
  1058. for i := range dest {
  1059. // Field is NULL
  1060. // (byte >> bit-pos) % 2 == 1
  1061. if ((nullMask[(i+2)>>3] >> uint((i+2)&7)) & 1) == 1 {
  1062. dest[i] = nil
  1063. continue
  1064. }
  1065. // Convert to byte-coded string
  1066. switch rows.rs.columns[i].fieldType {
  1067. case fieldTypeNULL:
  1068. dest[i] = nil
  1069. continue
  1070. // Numeric Types
  1071. case fieldTypeTiny:
  1072. if rows.rs.columns[i].flags&flagUnsigned != 0 {
  1073. dest[i] = int64(data[pos])
  1074. } else {
  1075. dest[i] = int64(int8(data[pos]))
  1076. }
  1077. pos++
  1078. continue
  1079. case fieldTypeShort, fieldTypeYear:
  1080. if rows.rs.columns[i].flags&flagUnsigned != 0 {
  1081. dest[i] = int64(binary.LittleEndian.Uint16(data[pos : pos+2]))
  1082. } else {
  1083. dest[i] = int64(int16(binary.LittleEndian.Uint16(data[pos : pos+2])))
  1084. }
  1085. pos += 2
  1086. continue
  1087. case fieldTypeInt24, fieldTypeLong:
  1088. if rows.rs.columns[i].flags&flagUnsigned != 0 {
  1089. dest[i] = int64(binary.LittleEndian.Uint32(data[pos : pos+4]))
  1090. } else {
  1091. dest[i] = int64(int32(binary.LittleEndian.Uint32(data[pos : pos+4])))
  1092. }
  1093. pos += 4
  1094. continue
  1095. case fieldTypeLongLong:
  1096. if rows.rs.columns[i].flags&flagUnsigned != 0 {
  1097. val := binary.LittleEndian.Uint64(data[pos : pos+8])
  1098. if val > math.MaxInt64 {
  1099. dest[i] = uint64ToString(val)
  1100. } else {
  1101. dest[i] = int64(val)
  1102. }
  1103. } else {
  1104. dest[i] = int64(binary.LittleEndian.Uint64(data[pos : pos+8]))
  1105. }
  1106. pos += 8
  1107. continue
  1108. case fieldTypeFloat:
  1109. dest[i] = math.Float32frombits(binary.LittleEndian.Uint32(data[pos : pos+4]))
  1110. pos += 4
  1111. continue
  1112. case fieldTypeDouble:
  1113. dest[i] = math.Float64frombits(binary.LittleEndian.Uint64(data[pos : pos+8]))
  1114. pos += 8
  1115. continue
  1116. // Length coded Binary Strings
  1117. case fieldTypeDecimal, fieldTypeNewDecimal, fieldTypeVarChar,
  1118. fieldTypeBit, fieldTypeEnum, fieldTypeSet, fieldTypeTinyBLOB,
  1119. fieldTypeMediumBLOB, fieldTypeLongBLOB, fieldTypeBLOB,
  1120. fieldTypeVarString, fieldTypeString, fieldTypeGeometry, fieldTypeJSON:
  1121. var isNull bool
  1122. var n int
  1123. dest[i], isNull, n, err = readLengthEncodedString(data[pos:])
  1124. pos += n
  1125. if err == nil {
  1126. if !isNull {
  1127. continue
  1128. } else {
  1129. dest[i] = nil
  1130. continue
  1131. }
  1132. }
  1133. return err
  1134. case
  1135. fieldTypeDate, fieldTypeNewDate, // Date YYYY-MM-DD
  1136. fieldTypeTime, // Time [-][H]HH:MM:SS[.fractal]
  1137. fieldTypeTimestamp, fieldTypeDateTime: // Timestamp YYYY-MM-DD HH:MM:SS[.fractal]
  1138. num, isNull, n := readLengthEncodedInteger(data[pos:])
  1139. pos += n
  1140. switch {
  1141. case isNull:
  1142. dest[i] = nil
  1143. continue
  1144. case rows.rs.columns[i].fieldType == fieldTypeTime:
  1145. // database/sql does not support an equivalent to TIME, return a string
  1146. var dstlen uint8
  1147. switch decimals := rows.rs.columns[i].decimals; decimals {
  1148. case 0x00, 0x1f:
  1149. dstlen = 8
  1150. case 1, 2, 3, 4, 5, 6:
  1151. dstlen = 8 + 1 + decimals
  1152. default:
  1153. return fmt.Errorf(
  1154. "protocol error, illegal decimals value %d",
  1155. rows.rs.columns[i].decimals,
  1156. )
  1157. }
  1158. dest[i], err = formatBinaryTime(data[pos:pos+int(num)], dstlen)
  1159. case rows.mc.parseTime:
  1160. dest[i], err = parseBinaryDateTime(num, data[pos:], rows.mc.cfg.Loc)
  1161. default:
  1162. var dstlen uint8
  1163. if rows.rs.columns[i].fieldType == fieldTypeDate {
  1164. dstlen = 10
  1165. } else {
  1166. switch decimals := rows.rs.columns[i].decimals; decimals {
  1167. case 0x00, 0x1f:
  1168. dstlen = 19
  1169. case 1, 2, 3, 4, 5, 6:
  1170. dstlen = 19 + 1 + decimals
  1171. default:
  1172. return fmt.Errorf(
  1173. "protocol error, illegal decimals value %d",
  1174. rows.rs.columns[i].decimals,
  1175. )
  1176. }
  1177. }
  1178. dest[i], err = formatBinaryDateTime(data[pos:pos+int(num)], dstlen)
  1179. }
  1180. if err == nil {
  1181. pos += int(num)
  1182. continue
  1183. } else {
  1184. return err
  1185. }
  1186. // Please report if this happens!
  1187. default:
  1188. return fmt.Errorf("unknown field type %d", rows.rs.columns[i].fieldType)
  1189. }
  1190. }
  1191. return nil
  1192. }