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.

tx.go 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. // Copyright 2019 The Xorm Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package core
  5. import (
  6. "context"
  7. "database/sql"
  8. "time"
  9. "xorm.io/xorm/log"
  10. )
  11. var (
  12. _ QueryExecuter = &Tx{}
  13. )
  14. // Tx represents a transaction
  15. type Tx struct {
  16. *sql.Tx
  17. db *DB
  18. }
  19. func (db *DB) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) {
  20. start := time.Now()
  21. showSQL := db.NeedLogSQL(ctx)
  22. if showSQL {
  23. db.Logger.BeforeSQL(log.LogContext{
  24. Ctx: ctx,
  25. SQL: "BEGIN TRANSACTION",
  26. })
  27. }
  28. tx, err := db.DB.BeginTx(ctx, opts)
  29. if showSQL {
  30. db.Logger.AfterSQL(log.LogContext{
  31. Ctx: ctx,
  32. SQL: "BEGIN TRANSACTION",
  33. ExecuteTime: time.Now().Sub(start),
  34. Err: err,
  35. })
  36. }
  37. if err != nil {
  38. return nil, err
  39. }
  40. return &Tx{tx, db}, nil
  41. }
  42. func (db *DB) Begin() (*Tx, error) {
  43. return db.BeginTx(context.Background(), nil)
  44. }
  45. func (tx *Tx) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
  46. names := make(map[string]int)
  47. var i int
  48. query = re.ReplaceAllStringFunc(query, func(src string) string {
  49. names[src[1:]] = i
  50. i++
  51. return "?"
  52. })
  53. start := time.Now()
  54. showSQL := tx.db.NeedLogSQL(ctx)
  55. if showSQL {
  56. tx.db.Logger.BeforeSQL(log.LogContext{
  57. Ctx: ctx,
  58. SQL: "PREPARE",
  59. })
  60. }
  61. stmt, err := tx.Tx.PrepareContext(ctx, query)
  62. if showSQL {
  63. tx.db.Logger.AfterSQL(log.LogContext{
  64. Ctx: ctx,
  65. SQL: "PREPARE",
  66. ExecuteTime: time.Now().Sub(start),
  67. Err: err,
  68. })
  69. }
  70. if err != nil {
  71. return nil, err
  72. }
  73. return &Stmt{stmt, tx.db, names, query}, nil
  74. }
  75. func (tx *Tx) Prepare(query string) (*Stmt, error) {
  76. return tx.PrepareContext(context.Background(), query)
  77. }
  78. func (tx *Tx) StmtContext(ctx context.Context, stmt *Stmt) *Stmt {
  79. stmt.Stmt = tx.Tx.StmtContext(ctx, stmt.Stmt)
  80. return stmt
  81. }
  82. func (tx *Tx) Stmt(stmt *Stmt) *Stmt {
  83. return tx.StmtContext(context.Background(), stmt)
  84. }
  85. func (tx *Tx) ExecMapContext(ctx context.Context, query string, mp interface{}) (sql.Result, error) {
  86. query, args, err := MapToSlice(query, mp)
  87. if err != nil {
  88. return nil, err
  89. }
  90. return tx.ExecContext(ctx, query, args...)
  91. }
  92. func (tx *Tx) ExecMap(query string, mp interface{}) (sql.Result, error) {
  93. return tx.ExecMapContext(context.Background(), query, mp)
  94. }
  95. func (tx *Tx) ExecStructContext(ctx context.Context, query string, st interface{}) (sql.Result, error) {
  96. query, args, err := StructToSlice(query, st)
  97. if err != nil {
  98. return nil, err
  99. }
  100. return tx.ExecContext(ctx, query, args...)
  101. }
  102. func (tx *Tx) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) {
  103. start := time.Now()
  104. showSQL := tx.db.NeedLogSQL(ctx)
  105. if showSQL {
  106. tx.db.Logger.BeforeSQL(log.LogContext{
  107. Ctx: ctx,
  108. SQL: query,
  109. Args: args,
  110. })
  111. }
  112. res, err := tx.Tx.ExecContext(ctx, query, args...)
  113. if showSQL {
  114. tx.db.Logger.AfterSQL(log.LogContext{
  115. Ctx: ctx,
  116. SQL: query,
  117. Args: args,
  118. ExecuteTime: time.Now().Sub(start),
  119. Err: err,
  120. })
  121. }
  122. return res, err
  123. }
  124. func (tx *Tx) ExecStruct(query string, st interface{}) (sql.Result, error) {
  125. return tx.ExecStructContext(context.Background(), query, st)
  126. }
  127. func (tx *Tx) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error) {
  128. start := time.Now()
  129. showSQL := tx.db.NeedLogSQL(ctx)
  130. if showSQL {
  131. tx.db.Logger.BeforeSQL(log.LogContext{
  132. Ctx: ctx,
  133. SQL: query,
  134. Args: args,
  135. })
  136. }
  137. rows, err := tx.Tx.QueryContext(ctx, query, args...)
  138. if showSQL {
  139. tx.db.Logger.AfterSQL(log.LogContext{
  140. Ctx: ctx,
  141. SQL: query,
  142. Args: args,
  143. ExecuteTime: time.Now().Sub(start),
  144. Err: err,
  145. })
  146. }
  147. if err != nil {
  148. if rows != nil {
  149. rows.Close()
  150. }
  151. return nil, err
  152. }
  153. return &Rows{rows, tx.db}, nil
  154. }
  155. func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error) {
  156. return tx.QueryContext(context.Background(), query, args...)
  157. }
  158. func (tx *Tx) QueryMapContext(ctx context.Context, query string, mp interface{}) (*Rows, error) {
  159. query, args, err := MapToSlice(query, mp)
  160. if err != nil {
  161. return nil, err
  162. }
  163. return tx.QueryContext(ctx, query, args...)
  164. }
  165. func (tx *Tx) QueryMap(query string, mp interface{}) (*Rows, error) {
  166. return tx.QueryMapContext(context.Background(), query, mp)
  167. }
  168. func (tx *Tx) QueryStructContext(ctx context.Context, query string, st interface{}) (*Rows, error) {
  169. query, args, err := StructToSlice(query, st)
  170. if err != nil {
  171. return nil, err
  172. }
  173. return tx.QueryContext(ctx, query, args...)
  174. }
  175. func (tx *Tx) QueryStruct(query string, st interface{}) (*Rows, error) {
  176. return tx.QueryStructContext(context.Background(), query, st)
  177. }
  178. func (tx *Tx) QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row {
  179. rows, err := tx.QueryContext(ctx, query, args...)
  180. return &Row{rows, err}
  181. }
  182. func (tx *Tx) QueryRow(query string, args ...interface{}) *Row {
  183. return tx.QueryRowContext(context.Background(), query, args...)
  184. }
  185. func (tx *Tx) QueryRowMapContext(ctx context.Context, query string, mp interface{}) *Row {
  186. query, args, err := MapToSlice(query, mp)
  187. if err != nil {
  188. return &Row{nil, err}
  189. }
  190. return tx.QueryRowContext(ctx, query, args...)
  191. }
  192. func (tx *Tx) QueryRowMap(query string, mp interface{}) *Row {
  193. return tx.QueryRowMapContext(context.Background(), query, mp)
  194. }
  195. func (tx *Tx) QueryRowStructContext(ctx context.Context, query string, st interface{}) *Row {
  196. query, args, err := StructToSlice(query, st)
  197. if err != nil {
  198. return &Row{nil, err}
  199. }
  200. return tx.QueryRowContext(ctx, query, args...)
  201. }
  202. func (tx *Tx) QueryRowStruct(query string, st interface{}) *Row {
  203. return tx.QueryRowStructContext(context.Background(), query, st)
  204. }