You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

token.go 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. package mssql
  2. import (
  3. "context"
  4. "encoding/binary"
  5. "errors"
  6. "fmt"
  7. "io"
  8. "net"
  9. "strconv"
  10. "strings"
  11. )
  12. //go:generate stringer -type token
  13. type token byte
  14. // token ids
  15. const (
  16. tokenReturnStatus token = 121 // 0x79
  17. tokenColMetadata token = 129 // 0x81
  18. tokenOrder token = 169 // 0xA9
  19. tokenError token = 170 // 0xAA
  20. tokenInfo token = 171 // 0xAB
  21. tokenReturnValue token = 0xAC
  22. tokenLoginAck token = 173 // 0xad
  23. tokenRow token = 209 // 0xd1
  24. tokenNbcRow token = 210 // 0xd2
  25. tokenEnvChange token = 227 // 0xE3
  26. tokenSSPI token = 237 // 0xED
  27. tokenDone token = 253 // 0xFD
  28. tokenDoneProc token = 254
  29. tokenDoneInProc token = 255
  30. )
  31. // done flags
  32. // https://msdn.microsoft.com/en-us/library/dd340421.aspx
  33. const (
  34. doneFinal = 0
  35. doneMore = 1
  36. doneError = 2
  37. doneInxact = 4
  38. doneCount = 0x10
  39. doneAttn = 0x20
  40. doneSrvError = 0x100
  41. )
  42. // ENVCHANGE types
  43. // http://msdn.microsoft.com/en-us/library/dd303449.aspx
  44. const (
  45. envTypDatabase = 1
  46. envTypLanguage = 2
  47. envTypCharset = 3
  48. envTypPacketSize = 4
  49. envSortId = 5
  50. envSortFlags = 6
  51. envSqlCollation = 7
  52. envTypBeginTran = 8
  53. envTypCommitTran = 9
  54. envTypRollbackTran = 10
  55. envEnlistDTC = 11
  56. envDefectTran = 12
  57. envDatabaseMirrorPartner = 13
  58. envPromoteTran = 15
  59. envTranMgrAddr = 16
  60. envTranEnded = 17
  61. envResetConnAck = 18
  62. envStartedInstanceName = 19
  63. envRouting = 20
  64. )
  65. // COLMETADATA flags
  66. // https://msdn.microsoft.com/en-us/library/dd357363.aspx
  67. const (
  68. colFlagNullable = 1
  69. // TODO implement more flags
  70. )
  71. // interface for all tokens
  72. type tokenStruct interface{}
  73. type orderStruct struct {
  74. ColIds []uint16
  75. }
  76. type doneStruct struct {
  77. Status uint16
  78. CurCmd uint16
  79. RowCount uint64
  80. errors []Error
  81. }
  82. func (d doneStruct) isError() bool {
  83. return d.Status&doneError != 0 || len(d.errors) > 0
  84. }
  85. func (d doneStruct) getError() Error {
  86. if len(d.errors) > 0 {
  87. return d.errors[len(d.errors)-1]
  88. } else {
  89. return Error{Message: "Request failed but didn't provide reason"}
  90. }
  91. }
  92. type doneInProcStruct doneStruct
  93. var doneFlags2str = map[uint16]string{
  94. doneFinal: "final",
  95. doneMore: "more",
  96. doneError: "error",
  97. doneInxact: "inxact",
  98. doneCount: "count",
  99. doneAttn: "attn",
  100. doneSrvError: "srverror",
  101. }
  102. func doneFlags2Str(flags uint16) string {
  103. strs := make([]string, 0, len(doneFlags2str))
  104. for flag, tag := range doneFlags2str {
  105. if flags&flag != 0 {
  106. strs = append(strs, tag)
  107. }
  108. }
  109. return strings.Join(strs, "|")
  110. }
  111. // ENVCHANGE stream
  112. // http://msdn.microsoft.com/en-us/library/dd303449.aspx
  113. func processEnvChg(sess *tdsSession) {
  114. size := sess.buf.uint16()
  115. r := &io.LimitedReader{R: sess.buf, N: int64(size)}
  116. for {
  117. var err error
  118. var envtype uint8
  119. err = binary.Read(r, binary.LittleEndian, &envtype)
  120. if err == io.EOF {
  121. return
  122. }
  123. if err != nil {
  124. badStreamPanic(err)
  125. }
  126. switch envtype {
  127. case envTypDatabase:
  128. sess.database, err = readBVarChar(r)
  129. if err != nil {
  130. badStreamPanic(err)
  131. }
  132. _, err = readBVarChar(r)
  133. if err != nil {
  134. badStreamPanic(err)
  135. }
  136. case envTypLanguage:
  137. // currently ignored
  138. // new value
  139. if _, err = readBVarChar(r); err != nil {
  140. badStreamPanic(err)
  141. }
  142. // old value
  143. if _, err = readBVarChar(r); err != nil {
  144. badStreamPanic(err)
  145. }
  146. case envTypCharset:
  147. // currently ignored
  148. // new value
  149. if _, err = readBVarChar(r); err != nil {
  150. badStreamPanic(err)
  151. }
  152. // old value
  153. if _, err = readBVarChar(r); err != nil {
  154. badStreamPanic(err)
  155. }
  156. case envTypPacketSize:
  157. packetsize, err := readBVarChar(r)
  158. if err != nil {
  159. badStreamPanic(err)
  160. }
  161. _, err = readBVarChar(r)
  162. if err != nil {
  163. badStreamPanic(err)
  164. }
  165. packetsizei, err := strconv.Atoi(packetsize)
  166. if err != nil {
  167. badStreamPanicf("Invalid Packet size value returned from server (%s): %s", packetsize, err.Error())
  168. }
  169. sess.buf.ResizeBuffer(packetsizei)
  170. case envSortId:
  171. // currently ignored
  172. // new value
  173. if _, err = readBVarChar(r); err != nil {
  174. badStreamPanic(err)
  175. }
  176. // old value, should be 0
  177. if _, err = readBVarChar(r); err != nil {
  178. badStreamPanic(err)
  179. }
  180. case envSortFlags:
  181. // currently ignored
  182. // new value
  183. if _, err = readBVarChar(r); err != nil {
  184. badStreamPanic(err)
  185. }
  186. // old value, should be 0
  187. if _, err = readBVarChar(r); err != nil {
  188. badStreamPanic(err)
  189. }
  190. case envSqlCollation:
  191. // currently ignored
  192. var collationSize uint8
  193. err = binary.Read(r, binary.LittleEndian, &collationSize)
  194. if err != nil {
  195. badStreamPanic(err)
  196. }
  197. // SQL Collation data should contain 5 bytes in length
  198. if collationSize != 5 {
  199. badStreamPanicf("Invalid SQL Collation size value returned from server: %d", collationSize)
  200. }
  201. // 4 bytes, contains: LCID ColFlags Version
  202. var info uint32
  203. err = binary.Read(r, binary.LittleEndian, &info)
  204. if err != nil {
  205. badStreamPanic(err)
  206. }
  207. // 1 byte, contains: sortID
  208. var sortID uint8
  209. err = binary.Read(r, binary.LittleEndian, &sortID)
  210. if err != nil {
  211. badStreamPanic(err)
  212. }
  213. // old value, should be 0
  214. if _, err = readBVarChar(r); err != nil {
  215. badStreamPanic(err)
  216. }
  217. case envTypBeginTran:
  218. tranid, err := readBVarByte(r)
  219. if len(tranid) != 8 {
  220. badStreamPanicf("invalid size of transaction identifier: %d", len(tranid))
  221. }
  222. sess.tranid = binary.LittleEndian.Uint64(tranid)
  223. if err != nil {
  224. badStreamPanic(err)
  225. }
  226. if sess.logFlags&logTransaction != 0 {
  227. sess.log.Printf("BEGIN TRANSACTION %x\n", sess.tranid)
  228. }
  229. _, err = readBVarByte(r)
  230. if err != nil {
  231. badStreamPanic(err)
  232. }
  233. case envTypCommitTran, envTypRollbackTran:
  234. _, err = readBVarByte(r)
  235. if err != nil {
  236. badStreamPanic(err)
  237. }
  238. _, err = readBVarByte(r)
  239. if err != nil {
  240. badStreamPanic(err)
  241. }
  242. if sess.logFlags&logTransaction != 0 {
  243. if envtype == envTypCommitTran {
  244. sess.log.Printf("COMMIT TRANSACTION %x\n", sess.tranid)
  245. } else {
  246. sess.log.Printf("ROLLBACK TRANSACTION %x\n", sess.tranid)
  247. }
  248. }
  249. sess.tranid = 0
  250. case envEnlistDTC:
  251. // currently ignored
  252. // new value, should be 0
  253. if _, err = readBVarChar(r); err != nil {
  254. badStreamPanic(err)
  255. }
  256. // old value
  257. if _, err = readBVarChar(r); err != nil {
  258. badStreamPanic(err)
  259. }
  260. case envDefectTran:
  261. // currently ignored
  262. // new value
  263. if _, err = readBVarChar(r); err != nil {
  264. badStreamPanic(err)
  265. }
  266. // old value, should be 0
  267. if _, err = readBVarChar(r); err != nil {
  268. badStreamPanic(err)
  269. }
  270. case envDatabaseMirrorPartner:
  271. sess.partner, err = readBVarChar(r)
  272. if err != nil {
  273. badStreamPanic(err)
  274. }
  275. _, err = readBVarChar(r)
  276. if err != nil {
  277. badStreamPanic(err)
  278. }
  279. case envPromoteTran:
  280. // currently ignored
  281. // old value, should be 0
  282. if _, err = readBVarChar(r); err != nil {
  283. badStreamPanic(err)
  284. }
  285. // dtc token
  286. // spec says it should be L_VARBYTE, so this code might be wrong
  287. if _, err = readBVarChar(r); err != nil {
  288. badStreamPanic(err)
  289. }
  290. case envTranMgrAddr:
  291. // currently ignored
  292. // old value, should be 0
  293. if _, err = readBVarChar(r); err != nil {
  294. badStreamPanic(err)
  295. }
  296. // XACT_MANAGER_ADDRESS = B_VARBYTE
  297. if _, err = readBVarChar(r); err != nil {
  298. badStreamPanic(err)
  299. }
  300. case envTranEnded:
  301. // currently ignored
  302. // old value, B_VARBYTE
  303. if _, err = readBVarChar(r); err != nil {
  304. badStreamPanic(err)
  305. }
  306. // should be 0
  307. if _, err = readBVarChar(r); err != nil {
  308. badStreamPanic(err)
  309. }
  310. case envResetConnAck:
  311. // currently ignored
  312. // old value, should be 0
  313. if _, err = readBVarChar(r); err != nil {
  314. badStreamPanic(err)
  315. }
  316. // should be 0
  317. if _, err = readBVarChar(r); err != nil {
  318. badStreamPanic(err)
  319. }
  320. case envStartedInstanceName:
  321. // currently ignored
  322. // old value, should be 0
  323. if _, err = readBVarChar(r); err != nil {
  324. badStreamPanic(err)
  325. }
  326. // instance name
  327. if _, err = readBVarChar(r); err != nil {
  328. badStreamPanic(err)
  329. }
  330. case envRouting:
  331. // RoutingData message is:
  332. // ValueLength USHORT
  333. // Protocol (TCP = 0) BYTE
  334. // ProtocolProperty (new port) USHORT
  335. // AlternateServer US_VARCHAR
  336. _, err := readUshort(r)
  337. if err != nil {
  338. badStreamPanic(err)
  339. }
  340. protocol, err := readByte(r)
  341. if err != nil || protocol != 0 {
  342. badStreamPanic(err)
  343. }
  344. newPort, err := readUshort(r)
  345. if err != nil {
  346. badStreamPanic(err)
  347. }
  348. newServer, err := readUsVarChar(r)
  349. if err != nil {
  350. badStreamPanic(err)
  351. }
  352. // consume the OLDVALUE = %x00 %x00
  353. _, err = readUshort(r)
  354. if err != nil {
  355. badStreamPanic(err)
  356. }
  357. sess.routedServer = newServer
  358. sess.routedPort = newPort
  359. default:
  360. // ignore rest of records because we don't know how to skip those
  361. sess.log.Printf("WARN: Unknown ENVCHANGE record detected with type id = %d\n", envtype)
  362. break
  363. }
  364. }
  365. }
  366. // http://msdn.microsoft.com/en-us/library/dd358180.aspx
  367. func parseReturnStatus(r *tdsBuffer) ReturnStatus {
  368. return ReturnStatus(r.int32())
  369. }
  370. func parseOrder(r *tdsBuffer) (res orderStruct) {
  371. len := int(r.uint16())
  372. res.ColIds = make([]uint16, len/2)
  373. for i := 0; i < len/2; i++ {
  374. res.ColIds[i] = r.uint16()
  375. }
  376. return res
  377. }
  378. // https://msdn.microsoft.com/en-us/library/dd340421.aspx
  379. func parseDone(r *tdsBuffer) (res doneStruct) {
  380. res.Status = r.uint16()
  381. res.CurCmd = r.uint16()
  382. res.RowCount = r.uint64()
  383. return res
  384. }
  385. // https://msdn.microsoft.com/en-us/library/dd340553.aspx
  386. func parseDoneInProc(r *tdsBuffer) (res doneInProcStruct) {
  387. res.Status = r.uint16()
  388. res.CurCmd = r.uint16()
  389. res.RowCount = r.uint64()
  390. return res
  391. }
  392. type sspiMsg []byte
  393. func parseSSPIMsg(r *tdsBuffer) sspiMsg {
  394. size := r.uint16()
  395. buf := make([]byte, size)
  396. r.ReadFull(buf)
  397. return sspiMsg(buf)
  398. }
  399. type loginAckStruct struct {
  400. Interface uint8
  401. TDSVersion uint32
  402. ProgName string
  403. ProgVer uint32
  404. }
  405. func parseLoginAck(r *tdsBuffer) loginAckStruct {
  406. size := r.uint16()
  407. buf := make([]byte, size)
  408. r.ReadFull(buf)
  409. var res loginAckStruct
  410. res.Interface = buf[0]
  411. res.TDSVersion = binary.BigEndian.Uint32(buf[1:])
  412. prognamelen := buf[1+4]
  413. var err error
  414. if res.ProgName, err = ucs22str(buf[1+4+1 : 1+4+1+prognamelen*2]); err != nil {
  415. badStreamPanic(err)
  416. }
  417. res.ProgVer = binary.BigEndian.Uint32(buf[size-4:])
  418. return res
  419. }
  420. // http://msdn.microsoft.com/en-us/library/dd357363.aspx
  421. func parseColMetadata72(r *tdsBuffer) (columns []columnStruct) {
  422. count := r.uint16()
  423. if count == 0xffff {
  424. // no metadata is sent
  425. return nil
  426. }
  427. columns = make([]columnStruct, count)
  428. for i := range columns {
  429. column := &columns[i]
  430. column.UserType = r.uint32()
  431. column.Flags = r.uint16()
  432. // parsing TYPE_INFO structure
  433. column.ti = readTypeInfo(r)
  434. column.ColName = r.BVarChar()
  435. }
  436. return columns
  437. }
  438. // http://msdn.microsoft.com/en-us/library/dd357254.aspx
  439. func parseRow(r *tdsBuffer, columns []columnStruct, row []interface{}) {
  440. for i, column := range columns {
  441. row[i] = column.ti.Reader(&column.ti, r)
  442. }
  443. }
  444. // http://msdn.microsoft.com/en-us/library/dd304783.aspx
  445. func parseNbcRow(r *tdsBuffer, columns []columnStruct, row []interface{}) {
  446. bitlen := (len(columns) + 7) / 8
  447. pres := make([]byte, bitlen)
  448. r.ReadFull(pres)
  449. for i, col := range columns {
  450. if pres[i/8]&(1<<(uint(i)%8)) != 0 {
  451. row[i] = nil
  452. continue
  453. }
  454. row[i] = col.ti.Reader(&col.ti, r)
  455. }
  456. }
  457. // http://msdn.microsoft.com/en-us/library/dd304156.aspx
  458. func parseError72(r *tdsBuffer) (res Error) {
  459. length := r.uint16()
  460. _ = length // ignore length
  461. res.Number = r.int32()
  462. res.State = r.byte()
  463. res.Class = r.byte()
  464. res.Message = r.UsVarChar()
  465. res.ServerName = r.BVarChar()
  466. res.ProcName = r.BVarChar()
  467. res.LineNo = r.int32()
  468. return
  469. }
  470. // http://msdn.microsoft.com/en-us/library/dd304156.aspx
  471. func parseInfo(r *tdsBuffer) (res Error) {
  472. length := r.uint16()
  473. _ = length // ignore length
  474. res.Number = r.int32()
  475. res.State = r.byte()
  476. res.Class = r.byte()
  477. res.Message = r.UsVarChar()
  478. res.ServerName = r.BVarChar()
  479. res.ProcName = r.BVarChar()
  480. res.LineNo = r.int32()
  481. return
  482. }
  483. // https://msdn.microsoft.com/en-us/library/dd303881.aspx
  484. func parseReturnValue(r *tdsBuffer) (nv namedValue) {
  485. /*
  486. ParamOrdinal
  487. ParamName
  488. Status
  489. UserType
  490. Flags
  491. TypeInfo
  492. CryptoMetadata
  493. Value
  494. */
  495. r.uint16()
  496. nv.Name = r.BVarChar()
  497. r.byte()
  498. r.uint32() // UserType (uint16 prior to 7.2)
  499. r.uint16()
  500. ti := readTypeInfo(r)
  501. nv.Value = ti.Reader(&ti, r)
  502. return
  503. }
  504. func processSingleResponse(sess *tdsSession, ch chan tokenStruct, outs map[string]interface{}) {
  505. defer func() {
  506. if err := recover(); err != nil {
  507. if sess.logFlags&logErrors != 0 {
  508. sess.log.Printf("ERROR: Intercepted panic %v", err)
  509. }
  510. ch <- err
  511. }
  512. close(ch)
  513. }()
  514. packet_type, err := sess.buf.BeginRead()
  515. if err != nil {
  516. if sess.logFlags&logErrors != 0 {
  517. sess.log.Printf("ERROR: BeginRead failed %v", err)
  518. }
  519. ch <- err
  520. return
  521. }
  522. if packet_type != packReply {
  523. badStreamPanic(fmt.Errorf("unexpected packet type in reply: got %v, expected %v", packet_type, packReply))
  524. }
  525. var columns []columnStruct
  526. errs := make([]Error, 0, 5)
  527. for {
  528. token := token(sess.buf.byte())
  529. if sess.logFlags&logDebug != 0 {
  530. sess.log.Printf("got token %v", token)
  531. }
  532. switch token {
  533. case tokenSSPI:
  534. ch <- parseSSPIMsg(sess.buf)
  535. return
  536. case tokenReturnStatus:
  537. returnStatus := parseReturnStatus(sess.buf)
  538. ch <- returnStatus
  539. case tokenLoginAck:
  540. loginAck := parseLoginAck(sess.buf)
  541. ch <- loginAck
  542. case tokenOrder:
  543. order := parseOrder(sess.buf)
  544. ch <- order
  545. case tokenDoneInProc:
  546. done := parseDoneInProc(sess.buf)
  547. if sess.logFlags&logRows != 0 && done.Status&doneCount != 0 {
  548. sess.log.Printf("(%d row(s) affected)\n", done.RowCount)
  549. }
  550. ch <- done
  551. case tokenDone, tokenDoneProc:
  552. done := parseDone(sess.buf)
  553. done.errors = errs
  554. if sess.logFlags&logDebug != 0 {
  555. sess.log.Printf("got DONE or DONEPROC status=%d", done.Status)
  556. }
  557. if done.Status&doneSrvError != 0 {
  558. ch <- errors.New("SQL Server had internal error")
  559. return
  560. }
  561. if sess.logFlags&logRows != 0 && done.Status&doneCount != 0 {
  562. sess.log.Printf("(%d row(s) affected)\n", done.RowCount)
  563. }
  564. ch <- done
  565. if done.Status&doneMore == 0 {
  566. return
  567. }
  568. case tokenColMetadata:
  569. columns = parseColMetadata72(sess.buf)
  570. ch <- columns
  571. case tokenRow:
  572. row := make([]interface{}, len(columns))
  573. parseRow(sess.buf, columns, row)
  574. ch <- row
  575. case tokenNbcRow:
  576. row := make([]interface{}, len(columns))
  577. parseNbcRow(sess.buf, columns, row)
  578. ch <- row
  579. case tokenEnvChange:
  580. processEnvChg(sess)
  581. case tokenError:
  582. err := parseError72(sess.buf)
  583. if sess.logFlags&logDebug != 0 {
  584. sess.log.Printf("got ERROR %d %s", err.Number, err.Message)
  585. }
  586. errs = append(errs, err)
  587. if sess.logFlags&logErrors != 0 {
  588. sess.log.Println(err.Message)
  589. }
  590. case tokenInfo:
  591. info := parseInfo(sess.buf)
  592. if sess.logFlags&logDebug != 0 {
  593. sess.log.Printf("got INFO %d %s", info.Number, info.Message)
  594. }
  595. if sess.logFlags&logMessages != 0 {
  596. sess.log.Println(info.Message)
  597. }
  598. case tokenReturnValue:
  599. nv := parseReturnValue(sess.buf)
  600. if len(nv.Name) > 0 {
  601. name := nv.Name[1:] // Remove the leading "@".
  602. if ov, has := outs[name]; has {
  603. err = scanIntoOut(name, nv.Value, ov)
  604. if err != nil {
  605. fmt.Println("scan error", err)
  606. ch <- err
  607. }
  608. }
  609. }
  610. default:
  611. badStreamPanic(fmt.Errorf("unknown token type returned: %v", token))
  612. }
  613. }
  614. }
  615. type parseRespIter byte
  616. const (
  617. parseRespIterContinue parseRespIter = iota // Continue parsing current token.
  618. parseRespIterNext // Fetch the next token.
  619. parseRespIterDone // Done with parsing the response.
  620. )
  621. type parseRespState byte
  622. const (
  623. parseRespStateNormal parseRespState = iota // Normal response state.
  624. parseRespStateCancel // Query is canceled, wait for server to confirm.
  625. parseRespStateClosing // Waiting for tokens to come through.
  626. )
  627. type parseResp struct {
  628. sess *tdsSession
  629. ctxDone <-chan struct{}
  630. state parseRespState
  631. cancelError error
  632. }
  633. func (ts *parseResp) sendAttention(ch chan tokenStruct) parseRespIter {
  634. if err := sendAttention(ts.sess.buf); err != nil {
  635. ts.dlogf("failed to send attention signal %v", err)
  636. ch <- err
  637. return parseRespIterDone
  638. }
  639. ts.state = parseRespStateCancel
  640. return parseRespIterContinue
  641. }
  642. func (ts *parseResp) dlog(msg string) {
  643. if ts.sess.logFlags&logDebug != 0 {
  644. ts.sess.log.Println(msg)
  645. }
  646. }
  647. func (ts *parseResp) dlogf(f string, v ...interface{}) {
  648. if ts.sess.logFlags&logDebug != 0 {
  649. ts.sess.log.Printf(f, v...)
  650. }
  651. }
  652. func (ts *parseResp) iter(ctx context.Context, ch chan tokenStruct, tokChan chan tokenStruct) parseRespIter {
  653. switch ts.state {
  654. default:
  655. panic("unknown state")
  656. case parseRespStateNormal:
  657. select {
  658. case tok, ok := <-tokChan:
  659. if !ok {
  660. ts.dlog("response finished")
  661. return parseRespIterDone
  662. }
  663. if err, ok := tok.(net.Error); ok && err.Timeout() {
  664. ts.cancelError = err
  665. ts.dlog("got timeout error, sending attention signal to server")
  666. return ts.sendAttention(ch)
  667. }
  668. // Pass the token along.
  669. ch <- tok
  670. return parseRespIterContinue
  671. case <-ts.ctxDone:
  672. ts.ctxDone = nil
  673. ts.dlog("got cancel message, sending attention signal to server")
  674. return ts.sendAttention(ch)
  675. }
  676. case parseRespStateCancel: // Read all responses until a DONE or error is received.Auth
  677. select {
  678. case tok, ok := <-tokChan:
  679. if !ok {
  680. ts.dlog("response finished but waiting for attention ack")
  681. return parseRespIterNext
  682. }
  683. switch tok := tok.(type) {
  684. default:
  685. // Ignore all other tokens while waiting.
  686. // The TDS spec says other tokens may arrive after an attention
  687. // signal is sent. Ignore these tokens and continue looking for
  688. // a DONE with attention confirm mark.
  689. case doneStruct:
  690. if tok.Status&doneAttn != 0 {
  691. ts.dlog("got cancellation confirmation from server")
  692. if ts.cancelError != nil {
  693. ch <- ts.cancelError
  694. ts.cancelError = nil
  695. } else {
  696. ch <- ctx.Err()
  697. }
  698. return parseRespIterDone
  699. }
  700. // If an error happens during cancel, pass it along and just stop.
  701. // We are uncertain to receive more tokens.
  702. case error:
  703. ch <- tok
  704. ts.state = parseRespStateClosing
  705. }
  706. return parseRespIterContinue
  707. case <-ts.ctxDone:
  708. ts.ctxDone = nil
  709. ts.state = parseRespStateClosing
  710. return parseRespIterContinue
  711. }
  712. case parseRespStateClosing: // Wait for current token chan to close.
  713. if _, ok := <-tokChan; !ok {
  714. ts.dlog("response finished")
  715. return parseRespIterDone
  716. }
  717. return parseRespIterContinue
  718. }
  719. }
  720. func processResponse(ctx context.Context, sess *tdsSession, ch chan tokenStruct, outs map[string]interface{}) {
  721. ts := &parseResp{
  722. sess: sess,
  723. ctxDone: ctx.Done(),
  724. }
  725. defer func() {
  726. // Ensure any remaining error is piped through
  727. // or the query may look like it executed when it actually failed.
  728. if ts.cancelError != nil {
  729. ch <- ts.cancelError
  730. ts.cancelError = nil
  731. }
  732. close(ch)
  733. }()
  734. // Loop over multiple responses.
  735. for {
  736. ts.dlog("initiating response reading")
  737. tokChan := make(chan tokenStruct)
  738. go processSingleResponse(sess, tokChan, outs)
  739. // Loop over multiple tokens in response.
  740. tokensLoop:
  741. for {
  742. switch ts.iter(ctx, ch, tokChan) {
  743. case parseRespIterContinue:
  744. // Nothing, continue to next token.
  745. case parseRespIterNext:
  746. break tokensLoop
  747. case parseRespIterDone:
  748. return
  749. }
  750. }
  751. }
  752. }