mssql.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  1. package mssql
  2. import (
  3. "context"
  4. "database/sql"
  5. "database/sql/driver"
  6. "encoding/binary"
  7. "errors"
  8. "fmt"
  9. "io"
  10. "math"
  11. "net"
  12. "reflect"
  13. "strings"
  14. "time"
  15. )
  16. var driverInstance = &Driver{processQueryText: true}
  17. var driverInstanceNoProcess = &Driver{processQueryText: false}
  18. func init() {
  19. sql.Register("mssql", driverInstance)
  20. sql.Register("sqlserver", driverInstanceNoProcess)
  21. createDialer = func(p *connectParams) dialer {
  22. return tcpDialer{&net.Dialer{KeepAlive: p.keepAlive}}
  23. }
  24. }
  25. // Abstract the dialer for testing and for non-TCP based connections.
  26. type dialer interface {
  27. Dial(ctx context.Context, addr string) (net.Conn, error)
  28. }
  29. var createDialer func(p *connectParams) dialer
  30. type tcpDialer struct {
  31. nd *net.Dialer
  32. }
  33. func (d tcpDialer) Dial(ctx context.Context, addr string) (net.Conn, error) {
  34. return d.nd.DialContext(ctx, "tcp", addr)
  35. }
  36. type Driver struct {
  37. log optionalLogger
  38. processQueryText bool
  39. }
  40. // OpenConnector opens a new connector. Useful to dial with a context.
  41. func (d *Driver) OpenConnector(dsn string) (*Connector, error) {
  42. params, err := parseConnectParams(dsn)
  43. if err != nil {
  44. return nil, err
  45. }
  46. return &Connector{
  47. params: params,
  48. driver: d,
  49. }, nil
  50. }
  51. func (d *Driver) Open(dsn string) (driver.Conn, error) {
  52. return d.open(context.Background(), dsn)
  53. }
  54. func SetLogger(logger Logger) {
  55. driverInstance.SetLogger(logger)
  56. driverInstanceNoProcess.SetLogger(logger)
  57. }
  58. func (d *Driver) SetLogger(logger Logger) {
  59. d.log = optionalLogger{logger}
  60. }
  61. // Connector holds the parsed DSN and is ready to make a new connection
  62. // at any time.
  63. //
  64. // In the future, settings that cannot be passed through a string DSN
  65. // may be set directly on the connector.
  66. type Connector struct {
  67. params connectParams
  68. driver *Driver
  69. // ResetSQL is executed after marking a given connection to be reset.
  70. // When not present, the next query will be reset to the database
  71. // defaults.
  72. // When present the connection will immediately mark the connection to
  73. // be reset, then execute the ResetSQL text to setup the session
  74. // that may be different from the base database defaults.
  75. //
  76. // For Example, the application relies on the following defaults
  77. // but is not allowed to set them at the database system level.
  78. //
  79. // SET XACT_ABORT ON;
  80. // SET TEXTSIZE -1;
  81. // SET ANSI_NULLS ON;
  82. // SET LOCK_TIMEOUT 10000;
  83. //
  84. // ResetSQL should not attempt to manually call sp_reset_connection.
  85. // This will happen at the TDS layer.
  86. ResetSQL string
  87. }
  88. type Conn struct {
  89. connector *Connector
  90. sess *tdsSession
  91. transactionCtx context.Context
  92. resetSession bool
  93. processQueryText bool
  94. connectionGood bool
  95. outs map[string]interface{}
  96. }
  97. func (c *Conn) checkBadConn(err error) error {
  98. // this is a hack to address Issue #275
  99. // we set connectionGood flag to false if
  100. // error indicates that connection is not usable
  101. // but we return actual error instead of ErrBadConn
  102. // this will cause connection to stay in a pool
  103. // but next request to this connection will return ErrBadConn
  104. // it might be possible to revise this hack after
  105. // https://github.com/golang/go/issues/20807
  106. // is implemented
  107. switch err {
  108. case nil:
  109. return nil
  110. case io.EOF:
  111. c.connectionGood = false
  112. return driver.ErrBadConn
  113. case driver.ErrBadConn:
  114. // It is an internal programming error if driver.ErrBadConn
  115. // is ever passed to this function. driver.ErrBadConn should
  116. // only ever be returned in response to a *mssql.Conn.connectionGood == false
  117. // check in the external facing API.
  118. panic("driver.ErrBadConn in checkBadConn. This should not happen.")
  119. }
  120. switch err.(type) {
  121. case net.Error:
  122. c.connectionGood = false
  123. return err
  124. case StreamError:
  125. c.connectionGood = false
  126. return err
  127. default:
  128. return err
  129. }
  130. }
  131. func (c *Conn) clearOuts() {
  132. c.outs = nil
  133. }
  134. func (c *Conn) simpleProcessResp(ctx context.Context) error {
  135. tokchan := make(chan tokenStruct, 5)
  136. go processResponse(ctx, c.sess, tokchan, c.outs)
  137. c.clearOuts()
  138. for tok := range tokchan {
  139. switch token := tok.(type) {
  140. case doneStruct:
  141. if token.isError() {
  142. return c.checkBadConn(token.getError())
  143. }
  144. case error:
  145. return c.checkBadConn(token)
  146. }
  147. }
  148. return nil
  149. }
  150. func (c *Conn) Commit() error {
  151. if !c.connectionGood {
  152. return driver.ErrBadConn
  153. }
  154. if err := c.sendCommitRequest(); err != nil {
  155. return c.checkBadConn(err)
  156. }
  157. return c.simpleProcessResp(c.transactionCtx)
  158. }
  159. func (c *Conn) sendCommitRequest() error {
  160. headers := []headerStruct{
  161. {hdrtype: dataStmHdrTransDescr,
  162. data: transDescrHdr{c.sess.tranid, 1}.pack()},
  163. }
  164. reset := c.resetSession
  165. c.resetSession = false
  166. if err := sendCommitXact(c.sess.buf, headers, "", 0, 0, "", reset); err != nil {
  167. if c.sess.logFlags&logErrors != 0 {
  168. c.sess.log.Printf("Failed to send CommitXact with %v", err)
  169. }
  170. c.connectionGood = false
  171. return fmt.Errorf("Faild to send CommitXact: %v", err)
  172. }
  173. return nil
  174. }
  175. func (c *Conn) Rollback() error {
  176. if !c.connectionGood {
  177. return driver.ErrBadConn
  178. }
  179. if err := c.sendRollbackRequest(); err != nil {
  180. return c.checkBadConn(err)
  181. }
  182. return c.simpleProcessResp(c.transactionCtx)
  183. }
  184. func (c *Conn) sendRollbackRequest() error {
  185. headers := []headerStruct{
  186. {hdrtype: dataStmHdrTransDescr,
  187. data: transDescrHdr{c.sess.tranid, 1}.pack()},
  188. }
  189. reset := c.resetSession
  190. c.resetSession = false
  191. if err := sendRollbackXact(c.sess.buf, headers, "", 0, 0, "", reset); err != nil {
  192. if c.sess.logFlags&logErrors != 0 {
  193. c.sess.log.Printf("Failed to send RollbackXact with %v", err)
  194. }
  195. c.connectionGood = false
  196. return fmt.Errorf("Failed to send RollbackXact: %v", err)
  197. }
  198. return nil
  199. }
  200. func (c *Conn) Begin() (driver.Tx, error) {
  201. return c.begin(context.Background(), isolationUseCurrent)
  202. }
  203. func (c *Conn) begin(ctx context.Context, tdsIsolation isoLevel) (tx driver.Tx, err error) {
  204. if !c.connectionGood {
  205. return nil, driver.ErrBadConn
  206. }
  207. err = c.sendBeginRequest(ctx, tdsIsolation)
  208. if err != nil {
  209. return nil, c.checkBadConn(err)
  210. }
  211. tx, err = c.processBeginResponse(ctx)
  212. if err != nil {
  213. return nil, c.checkBadConn(err)
  214. }
  215. return
  216. }
  217. func (c *Conn) sendBeginRequest(ctx context.Context, tdsIsolation isoLevel) error {
  218. c.transactionCtx = ctx
  219. headers := []headerStruct{
  220. {hdrtype: dataStmHdrTransDescr,
  221. data: transDescrHdr{0, 1}.pack()},
  222. }
  223. reset := c.resetSession
  224. c.resetSession = false
  225. if err := sendBeginXact(c.sess.buf, headers, tdsIsolation, "", reset); err != nil {
  226. if c.sess.logFlags&logErrors != 0 {
  227. c.sess.log.Printf("Failed to send BeginXact with %v", err)
  228. }
  229. c.connectionGood = false
  230. return fmt.Errorf("Failed to send BiginXant: %v", err)
  231. }
  232. return nil
  233. }
  234. func (c *Conn) processBeginResponse(ctx context.Context) (driver.Tx, error) {
  235. if err := c.simpleProcessResp(ctx); err != nil {
  236. return nil, err
  237. }
  238. // successful BEGINXACT request will return sess.tranid
  239. // for started transaction
  240. return c, nil
  241. }
  242. func (d *Driver) open(ctx context.Context, dsn string) (*Conn, error) {
  243. params, err := parseConnectParams(dsn)
  244. if err != nil {
  245. return nil, err
  246. }
  247. return d.connect(ctx, params)
  248. }
  249. // connect to the server, using the provided context for dialing only.
  250. func (d *Driver) connect(ctx context.Context, params connectParams) (*Conn, error) {
  251. sess, err := connect(ctx, d.log, params)
  252. if err != nil {
  253. // main server failed, try fail-over partner
  254. if params.failOverPartner == "" {
  255. return nil, err
  256. }
  257. params.host = params.failOverPartner
  258. if params.failOverPort != 0 {
  259. params.port = params.failOverPort
  260. }
  261. sess, err = connect(ctx, d.log, params)
  262. if err != nil {
  263. // fail-over partner also failed, now fail
  264. return nil, err
  265. }
  266. }
  267. conn := &Conn{
  268. sess: sess,
  269. transactionCtx: context.Background(),
  270. processQueryText: d.processQueryText,
  271. connectionGood: true,
  272. }
  273. conn.sess.log = d.log
  274. return conn, nil
  275. }
  276. func (c *Conn) Close() error {
  277. return c.sess.buf.transport.Close()
  278. }
  279. type Stmt struct {
  280. c *Conn
  281. query string
  282. paramCount int
  283. notifSub *queryNotifSub
  284. }
  285. type queryNotifSub struct {
  286. msgText string
  287. options string
  288. timeout uint32
  289. }
  290. func (c *Conn) Prepare(query string) (driver.Stmt, error) {
  291. if !c.connectionGood {
  292. return nil, driver.ErrBadConn
  293. }
  294. if len(query) > 10 && strings.EqualFold(query[:10], "INSERTBULK") {
  295. return c.prepareCopyIn(context.Background(), query)
  296. }
  297. return c.prepareContext(context.Background(), query)
  298. }
  299. func (c *Conn) prepareContext(ctx context.Context, query string) (*Stmt, error) {
  300. paramCount := -1
  301. if c.processQueryText {
  302. query, paramCount = parseParams(query)
  303. }
  304. return &Stmt{c, query, paramCount, nil}, nil
  305. }
  306. func (s *Stmt) Close() error {
  307. return nil
  308. }
  309. func (s *Stmt) SetQueryNotification(id, options string, timeout time.Duration) {
  310. to := uint32(timeout / time.Second)
  311. if to < 1 {
  312. to = 1
  313. }
  314. s.notifSub = &queryNotifSub{id, options, to}
  315. }
  316. func (s *Stmt) NumInput() int {
  317. return s.paramCount
  318. }
  319. func (s *Stmt) sendQuery(args []namedValue) (err error) {
  320. headers := []headerStruct{
  321. {hdrtype: dataStmHdrTransDescr,
  322. data: transDescrHdr{s.c.sess.tranid, 1}.pack()},
  323. }
  324. if s.notifSub != nil {
  325. headers = append(headers,
  326. headerStruct{
  327. hdrtype: dataStmHdrQueryNotif,
  328. data: queryNotifHdr{
  329. s.notifSub.msgText,
  330. s.notifSub.options,
  331. s.notifSub.timeout,
  332. }.pack(),
  333. })
  334. }
  335. conn := s.c
  336. // no need to check number of parameters here, it is checked by database/sql
  337. if conn.sess.logFlags&logSQL != 0 {
  338. conn.sess.log.Println(s.query)
  339. }
  340. if conn.sess.logFlags&logParams != 0 && len(args) > 0 {
  341. for i := 0; i < len(args); i++ {
  342. if len(args[i].Name) > 0 {
  343. s.c.sess.log.Printf("\t@%s\t%v\n", args[i].Name, args[i].Value)
  344. } else {
  345. s.c.sess.log.Printf("\t@p%d\t%v\n", i+1, args[i].Value)
  346. }
  347. }
  348. }
  349. reset := conn.resetSession
  350. conn.resetSession = false
  351. if len(args) == 0 {
  352. if err = sendSqlBatch72(conn.sess.buf, s.query, headers, reset); err != nil {
  353. if conn.sess.logFlags&logErrors != 0 {
  354. conn.sess.log.Printf("Failed to send SqlBatch with %v", err)
  355. }
  356. conn.connectionGood = false
  357. return fmt.Errorf("failed to send SQL Batch: %v", err)
  358. }
  359. } else {
  360. proc := Sp_ExecuteSql
  361. var params []Param
  362. if isProc(s.query) {
  363. proc.name = s.query
  364. params, _, err = s.makeRPCParams(args, 0)
  365. } else {
  366. var decls []string
  367. params, decls, err = s.makeRPCParams(args, 2)
  368. if err != nil {
  369. return
  370. }
  371. params[0] = makeStrParam(s.query)
  372. params[1] = makeStrParam(strings.Join(decls, ","))
  373. }
  374. if err = sendRpc(conn.sess.buf, headers, proc, 0, params, reset); err != nil {
  375. if conn.sess.logFlags&logErrors != 0 {
  376. conn.sess.log.Printf("Failed to send Rpc with %v", err)
  377. }
  378. conn.connectionGood = false
  379. return fmt.Errorf("Failed to send RPC: %v", err)
  380. }
  381. }
  382. return
  383. }
  384. // isProc takes the query text in s and determines if it is a stored proc name
  385. // or SQL text.
  386. func isProc(s string) bool {
  387. if len(s) == 0 {
  388. return false
  389. }
  390. if s[0] == '[' && s[len(s)-1] == ']' && strings.ContainsAny(s, "\n\r") == false {
  391. return true
  392. }
  393. return !strings.ContainsAny(s, " \t\n\r;")
  394. }
  395. func (s *Stmt) makeRPCParams(args []namedValue, offset int) ([]Param, []string, error) {
  396. var err error
  397. params := make([]Param, len(args)+offset)
  398. decls := make([]string, len(args))
  399. for i, val := range args {
  400. params[i+offset], err = s.makeParam(val.Value)
  401. if err != nil {
  402. return nil, nil, err
  403. }
  404. var name string
  405. if len(val.Name) > 0 {
  406. name = "@" + val.Name
  407. } else {
  408. name = fmt.Sprintf("@p%d", val.Ordinal)
  409. }
  410. params[i+offset].Name = name
  411. decls[i] = fmt.Sprintf("%s %s", name, makeDecl(params[i+offset].ti))
  412. }
  413. return params, decls, nil
  414. }
  415. type namedValue struct {
  416. Name string
  417. Ordinal int
  418. Value driver.Value
  419. }
  420. func convertOldArgs(args []driver.Value) []namedValue {
  421. list := make([]namedValue, len(args))
  422. for i, v := range args {
  423. list[i] = namedValue{
  424. Ordinal: i + 1,
  425. Value: v,
  426. }
  427. }
  428. return list
  429. }
  430. func (s *Stmt) Query(args []driver.Value) (driver.Rows, error) {
  431. return s.queryContext(context.Background(), convertOldArgs(args))
  432. }
  433. func (s *Stmt) queryContext(ctx context.Context, args []namedValue) (rows driver.Rows, err error) {
  434. if !s.c.connectionGood {
  435. return nil, driver.ErrBadConn
  436. }
  437. if err = s.sendQuery(args); err != nil {
  438. return nil, s.c.checkBadConn(err)
  439. }
  440. return s.processQueryResponse(ctx)
  441. }
  442. func (s *Stmt) processQueryResponse(ctx context.Context) (res driver.Rows, err error) {
  443. tokchan := make(chan tokenStruct, 5)
  444. ctx, cancel := context.WithCancel(ctx)
  445. go processResponse(ctx, s.c.sess, tokchan, s.c.outs)
  446. s.c.clearOuts()
  447. // process metadata
  448. var cols []columnStruct
  449. loop:
  450. for tok := range tokchan {
  451. switch token := tok.(type) {
  452. // By ignoring DONE token we effectively
  453. // skip empty result-sets.
  454. // This improves results in queries like that:
  455. // set nocount on; select 1
  456. // see TestIgnoreEmptyResults test
  457. //case doneStruct:
  458. //break loop
  459. case []columnStruct:
  460. cols = token
  461. break loop
  462. case doneStruct:
  463. if token.isError() {
  464. return nil, s.c.checkBadConn(token.getError())
  465. }
  466. case error:
  467. return nil, s.c.checkBadConn(token)
  468. }
  469. }
  470. res = &Rows{stmt: s, tokchan: tokchan, cols: cols, cancel: cancel}
  471. return
  472. }
  473. func (s *Stmt) Exec(args []driver.Value) (driver.Result, error) {
  474. return s.exec(context.Background(), convertOldArgs(args))
  475. }
  476. func (s *Stmt) exec(ctx context.Context, args []namedValue) (res driver.Result, err error) {
  477. if !s.c.connectionGood {
  478. return nil, driver.ErrBadConn
  479. }
  480. if err = s.sendQuery(args); err != nil {
  481. return nil, s.c.checkBadConn(err)
  482. }
  483. if res, err = s.processExec(ctx); err != nil {
  484. return nil, s.c.checkBadConn(err)
  485. }
  486. return
  487. }
  488. func (s *Stmt) processExec(ctx context.Context) (res driver.Result, err error) {
  489. tokchan := make(chan tokenStruct, 5)
  490. go processResponse(ctx, s.c.sess, tokchan, s.c.outs)
  491. s.c.clearOuts()
  492. var rowCount int64
  493. for token := range tokchan {
  494. switch token := token.(type) {
  495. case doneInProcStruct:
  496. if token.Status&doneCount != 0 {
  497. rowCount += int64(token.RowCount)
  498. }
  499. case doneStruct:
  500. if token.Status&doneCount != 0 {
  501. rowCount += int64(token.RowCount)
  502. }
  503. if token.isError() {
  504. return nil, token.getError()
  505. }
  506. case error:
  507. return nil, token
  508. }
  509. }
  510. return &Result{s.c, rowCount}, nil
  511. }
  512. type Rows struct {
  513. stmt *Stmt
  514. cols []columnStruct
  515. tokchan chan tokenStruct
  516. nextCols []columnStruct
  517. cancel func()
  518. }
  519. func (rc *Rows) Close() error {
  520. rc.cancel()
  521. for _ = range rc.tokchan {
  522. }
  523. rc.tokchan = nil
  524. return nil
  525. }
  526. func (rc *Rows) Columns() (res []string) {
  527. res = make([]string, len(rc.cols))
  528. for i, col := range rc.cols {
  529. res[i] = col.ColName
  530. }
  531. return
  532. }
  533. func (rc *Rows) Next(dest []driver.Value) error {
  534. if !rc.stmt.c.connectionGood {
  535. return driver.ErrBadConn
  536. }
  537. if rc.nextCols != nil {
  538. return io.EOF
  539. }
  540. for tok := range rc.tokchan {
  541. switch tokdata := tok.(type) {
  542. case []columnStruct:
  543. rc.nextCols = tokdata
  544. return io.EOF
  545. case []interface{}:
  546. for i := range dest {
  547. dest[i] = tokdata[i]
  548. }
  549. return nil
  550. case doneStruct:
  551. if tokdata.isError() {
  552. return rc.stmt.c.checkBadConn(tokdata.getError())
  553. }
  554. case error:
  555. return rc.stmt.c.checkBadConn(tokdata)
  556. }
  557. }
  558. return io.EOF
  559. }
  560. func (rc *Rows) HasNextResultSet() bool {
  561. return rc.nextCols != nil
  562. }
  563. func (rc *Rows) NextResultSet() error {
  564. rc.cols = rc.nextCols
  565. rc.nextCols = nil
  566. if rc.cols == nil {
  567. return io.EOF
  568. }
  569. return nil
  570. }
  571. // It should return
  572. // the value type that can be used to scan types into. For example, the database
  573. // column type "bigint" this should return "reflect.TypeOf(int64(0))".
  574. func (r *Rows) ColumnTypeScanType(index int) reflect.Type {
  575. return makeGoLangScanType(r.cols[index].ti)
  576. }
  577. // RowsColumnTypeDatabaseTypeName may be implemented by Rows. It should return the
  578. // database system type name without the length. Type names should be uppercase.
  579. // Examples of returned types: "VARCHAR", "NVARCHAR", "VARCHAR2", "CHAR", "TEXT",
  580. // "DECIMAL", "SMALLINT", "INT", "BIGINT", "BOOL", "[]BIGINT", "JSONB", "XML",
  581. // "TIMESTAMP".
  582. func (r *Rows) ColumnTypeDatabaseTypeName(index int) string {
  583. return makeGoLangTypeName(r.cols[index].ti)
  584. }
  585. // RowsColumnTypeLength may be implemented by Rows. It should return the length
  586. // of the column type if the column is a variable length type. If the column is
  587. // not a variable length type ok should return false.
  588. // If length is not limited other than system limits, it should return math.MaxInt64.
  589. // The following are examples of returned values for various types:
  590. // TEXT (math.MaxInt64, true)
  591. // varchar(10) (10, true)
  592. // nvarchar(10) (10, true)
  593. // decimal (0, false)
  594. // int (0, false)
  595. // bytea(30) (30, true)
  596. func (r *Rows) ColumnTypeLength(index int) (int64, bool) {
  597. return makeGoLangTypeLength(r.cols[index].ti)
  598. }
  599. // It should return
  600. // the precision and scale for decimal types. If not applicable, ok should be false.
  601. // The following are examples of returned values for various types:
  602. // decimal(38, 4) (38, 4, true)
  603. // int (0, 0, false)
  604. // decimal (math.MaxInt64, math.MaxInt64, true)
  605. func (r *Rows) ColumnTypePrecisionScale(index int) (int64, int64, bool) {
  606. return makeGoLangTypePrecisionScale(r.cols[index].ti)
  607. }
  608. // The nullable value should
  609. // be true if it is known the column may be null, or false if the column is known
  610. // to be not nullable.
  611. // If the column nullability is unknown, ok should be false.
  612. func (r *Rows) ColumnTypeNullable(index int) (nullable, ok bool) {
  613. nullable = r.cols[index].Flags&colFlagNullable != 0
  614. ok = true
  615. return
  616. }
  617. func makeStrParam(val string) (res Param) {
  618. res.ti.TypeId = typeNVarChar
  619. res.buffer = str2ucs2(val)
  620. res.ti.Size = len(res.buffer)
  621. return
  622. }
  623. func (s *Stmt) makeParam(val driver.Value) (res Param, err error) {
  624. if val == nil {
  625. res.ti.TypeId = typeNull
  626. res.buffer = nil
  627. res.ti.Size = 0
  628. return
  629. }
  630. switch val := val.(type) {
  631. case int64:
  632. res.ti.TypeId = typeIntN
  633. res.buffer = make([]byte, 8)
  634. res.ti.Size = 8
  635. binary.LittleEndian.PutUint64(res.buffer, uint64(val))
  636. case float64:
  637. res.ti.TypeId = typeFltN
  638. res.ti.Size = 8
  639. res.buffer = make([]byte, 8)
  640. binary.LittleEndian.PutUint64(res.buffer, math.Float64bits(val))
  641. case []byte:
  642. res.ti.TypeId = typeBigVarBin
  643. res.ti.Size = len(val)
  644. res.buffer = val
  645. case string:
  646. res = makeStrParam(val)
  647. case bool:
  648. res.ti.TypeId = typeBitN
  649. res.ti.Size = 1
  650. res.buffer = make([]byte, 1)
  651. if val {
  652. res.buffer[0] = 1
  653. }
  654. case time.Time:
  655. if s.c.sess.loginAck.TDSVersion >= verTDS73 {
  656. res.ti.TypeId = typeDateTimeOffsetN
  657. res.ti.Scale = 7
  658. res.ti.Size = 10
  659. buf := make([]byte, 10)
  660. res.buffer = buf
  661. days, ns := dateTime2(val)
  662. ns /= 100
  663. buf[0] = byte(ns)
  664. buf[1] = byte(ns >> 8)
  665. buf[2] = byte(ns >> 16)
  666. buf[3] = byte(ns >> 24)
  667. buf[4] = byte(ns >> 32)
  668. buf[5] = byte(days)
  669. buf[6] = byte(days >> 8)
  670. buf[7] = byte(days >> 16)
  671. _, offset := val.Zone()
  672. offset /= 60
  673. buf[8] = byte(offset)
  674. buf[9] = byte(offset >> 8)
  675. } else {
  676. res.ti.TypeId = typeDateTimeN
  677. res.ti.Size = 8
  678. res.buffer = make([]byte, 8)
  679. ref := time.Date(1900, 1, 1, 0, 0, 0, 0, time.UTC)
  680. dur := val.Sub(ref)
  681. days := dur / (24 * time.Hour)
  682. tm := (300 * (dur % (24 * time.Hour))) / time.Second
  683. binary.LittleEndian.PutUint32(res.buffer[0:4], uint32(days))
  684. binary.LittleEndian.PutUint32(res.buffer[4:8], uint32(tm))
  685. }
  686. default:
  687. return s.makeParamExtra(val)
  688. }
  689. return
  690. }
  691. type Result struct {
  692. c *Conn
  693. rowsAffected int64
  694. }
  695. func (r *Result) RowsAffected() (int64, error) {
  696. return r.rowsAffected, nil
  697. }
  698. func (r *Result) LastInsertId() (int64, error) {
  699. s, err := r.c.Prepare("select cast(@@identity as bigint)")
  700. if err != nil {
  701. return 0, err
  702. }
  703. defer s.Close()
  704. rows, err := s.Query(nil)
  705. if err != nil {
  706. return 0, err
  707. }
  708. defer rows.Close()
  709. dest := make([]driver.Value, 1)
  710. err = rows.Next(dest)
  711. if err != nil {
  712. return 0, err
  713. }
  714. if dest[0] == nil {
  715. return -1, errors.New("There is no generated identity value")
  716. }
  717. lastInsertId := dest[0].(int64)
  718. return lastInsertId, nil
  719. }