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

stmt.go 5.4 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package sql
  18. import (
  19. "context"
  20. "database/sql/driver"
  21. "github.com/seata/seata-go/pkg/datasource/sql/exec"
  22. "github.com/seata/seata-go/pkg/datasource/sql/types"
  23. )
  24. type Stmt struct {
  25. conn *Conn
  26. // res
  27. res *DBResource
  28. // txCtx
  29. txCtx *types.TransactionContext
  30. // query
  31. query string
  32. // stmt
  33. stmt driver.Stmt
  34. }
  35. // Close closes the statement.
  36. //
  37. // As of Go 1.1, a Stmt will not be closed if it's in use
  38. // by any queries.
  39. //
  40. // Drivers must ensure all network calls made by Close
  41. // do not block indefinitely (e.g. apply a timeout).
  42. func (s *Stmt) Close() error {
  43. s.txCtx = nil
  44. return s.stmt.Close()
  45. }
  46. // NumInput returns the number of placeholder parameters.
  47. //
  48. // If NumInput returns >= 0, the sql package will sanity check
  49. // argument counts from callers and return errors to the caller
  50. // before the statement's Exec or Query methods are called.
  51. //
  52. // NumInput may also return -1, if the driver doesn't know
  53. // its number of placeholders. In that case, the sql package
  54. // will not sanity check Exec or Query argument counts.
  55. func (s *Stmt) NumInput() int {
  56. return s.stmt.NumInput()
  57. }
  58. // Query executes a query that may return rows, such as a
  59. // SELECT.
  60. //
  61. // Deprecated: Drivers should implement StmtQueryContext instead (or additionally).
  62. func (s *Stmt) Query(args []driver.Value) (driver.Rows, error) {
  63. executor, err := exec.BuildExecutor(s.res.dbType, s.query)
  64. if err != nil {
  65. return nil, err
  66. }
  67. execCtx := &exec.ExecContext{
  68. TxCtx: s.txCtx,
  69. Query: s.query,
  70. Values: args,
  71. }
  72. ret, err := executor.ExecWithValue(context.Background(), execCtx,
  73. func(ctx context.Context, query string, args []driver.Value) (types.ExecResult, error) {
  74. ret, err := s.stmt.Query(args)
  75. if err != nil {
  76. return nil, err
  77. }
  78. return types.NewResult(types.WithRows(ret)), nil
  79. })
  80. if err != nil {
  81. return nil, err
  82. }
  83. return ret.GetRows(), nil
  84. }
  85. // StmtQueryContext enhances the Stmt interface by providing Query with context.
  86. // QueryContext executes a query that may return rows, such as a
  87. // SELECT.
  88. //
  89. // QueryContext must honor the context timeout and return when it is canceled.
  90. func (s *Stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
  91. stmt, ok := s.stmt.(driver.StmtQueryContext)
  92. if !ok {
  93. return nil, driver.ErrSkip
  94. }
  95. executor, err := exec.BuildExecutor(s.res.dbType, s.query)
  96. if err != nil {
  97. return nil, err
  98. }
  99. execCtx := &exec.ExecContext{
  100. TxCtx: s.txCtx,
  101. Query: s.query,
  102. NamedValues: args,
  103. }
  104. ret, err := executor.ExecWithNamedValue(context.Background(), execCtx,
  105. func(ctx context.Context, query string, args []driver.NamedValue) (types.ExecResult, error) {
  106. ret, err := stmt.QueryContext(ctx, args)
  107. if err != nil {
  108. return nil, err
  109. }
  110. return types.NewResult(types.WithRows(ret)), nil
  111. })
  112. if err != nil {
  113. return nil, err
  114. }
  115. return ret.GetRows(), nil
  116. }
  117. // Exec executes a query that doesn't return rows, such
  118. // as an INSERT or UPDATE.
  119. //
  120. // Deprecated: Drivers should implement StmtExecContext instead (or additionally).
  121. func (s *Stmt) Exec(args []driver.Value) (driver.Result, error) {
  122. // in transaction, need run Executor
  123. executor, err := exec.BuildExecutor(s.res.dbType, s.query)
  124. if err != nil {
  125. return nil, err
  126. }
  127. execCtx := &exec.ExecContext{
  128. TxCtx: s.txCtx,
  129. Query: s.query,
  130. Values: args,
  131. }
  132. ret, err := executor.ExecWithValue(context.Background(), execCtx,
  133. func(ctx context.Context, query string, args []driver.Value) (types.ExecResult, error) {
  134. ret, err := s.stmt.Exec(args)
  135. if err != nil {
  136. return nil, err
  137. }
  138. return types.NewResult(types.WithResult(ret)), nil
  139. })
  140. return ret.GetResult(), err
  141. }
  142. // ExecContext executes a query that doesn't return rows, such
  143. // as an INSERT or UPDATE.
  144. //
  145. // ExecContext must honor the context timeout and return when it is canceled.
  146. func (s *Stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {
  147. stmt, ok := s.stmt.(driver.StmtExecContext)
  148. if !ok {
  149. return nil, driver.ErrSkip
  150. }
  151. // in transaction, need run Executor
  152. executor, err := exec.BuildExecutor(s.res.dbType, s.query)
  153. if err != nil {
  154. return nil, err
  155. }
  156. execCtx := &exec.ExecContext{
  157. TxCtx: s.txCtx,
  158. Query: s.query,
  159. NamedValues: args,
  160. }
  161. ret, err := executor.ExecWithNamedValue(ctx, execCtx,
  162. func(ctx context.Context, query string, args []driver.NamedValue) (types.ExecResult, error) {
  163. ret, err := stmt.ExecContext(ctx, args)
  164. if err != nil {
  165. return nil, err
  166. }
  167. return types.NewResult(types.WithResult(ret)), nil
  168. })
  169. return ret.GetResult(), err
  170. }