named_context.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. // +build go1.8
  2. package sqlx
  3. import (
  4. "context"
  5. "database/sql"
  6. )
  7. // A union interface of contextPreparer and binder, required to be able to
  8. // prepare named statements with context (as the bindtype must be determined).
  9. type namedPreparerContext interface {
  10. PreparerContext
  11. binder
  12. }
  13. func prepareNamedContext(ctx context.Context, p namedPreparerContext, query string) (*NamedStmt, error) {
  14. bindType := BindType(p.DriverName())
  15. q, args, err := compileNamedQuery([]byte(query), bindType)
  16. if err != nil {
  17. return nil, err
  18. }
  19. stmt, err := PreparexContext(ctx, p, q)
  20. if err != nil {
  21. return nil, err
  22. }
  23. return &NamedStmt{
  24. QueryString: q,
  25. Params: args,
  26. Stmt: stmt,
  27. }, nil
  28. }
  29. // ExecContext executes a named statement using the struct passed.
  30. // Any named placeholder parameters are replaced with fields from arg.
  31. func (n *NamedStmt) ExecContext(ctx context.Context, arg interface{}) (sql.Result, error) {
  32. args, err := bindAnyArgs(n.Params, arg, n.Stmt.Mapper)
  33. if err != nil {
  34. return *new(sql.Result), err
  35. }
  36. return n.Stmt.ExecContext(ctx, args...)
  37. }
  38. // QueryContext executes a named statement using the struct argument, returning rows.
  39. // Any named placeholder parameters are replaced with fields from arg.
  40. func (n *NamedStmt) QueryContext(ctx context.Context, arg interface{}) (*sql.Rows, error) {
  41. args, err := bindAnyArgs(n.Params, arg, n.Stmt.Mapper)
  42. if err != nil {
  43. return nil, err
  44. }
  45. return n.Stmt.QueryContext(ctx, args...)
  46. }
  47. // QueryRowContext executes a named statement against the database. Because sqlx cannot
  48. // create a *sql.Row with an error condition pre-set for binding errors, sqlx
  49. // returns a *sqlx.Row instead.
  50. // Any named placeholder parameters are replaced with fields from arg.
  51. func (n *NamedStmt) QueryRowContext(ctx context.Context, arg interface{}) *Row {
  52. args, err := bindAnyArgs(n.Params, arg, n.Stmt.Mapper)
  53. if err != nil {
  54. return &Row{err: err}
  55. }
  56. return n.Stmt.QueryRowxContext(ctx, args...)
  57. }
  58. // MustExecContext execs a NamedStmt, panicing on error
  59. // Any named placeholder parameters are replaced with fields from arg.
  60. func (n *NamedStmt) MustExecContext(ctx context.Context, arg interface{}) sql.Result {
  61. res, err := n.ExecContext(ctx, arg)
  62. if err != nil {
  63. panic(err)
  64. }
  65. return res
  66. }
  67. // QueryxContext using this NamedStmt
  68. // Any named placeholder parameters are replaced with fields from arg.
  69. func (n *NamedStmt) QueryxContext(ctx context.Context, arg interface{}) (*Rows, error) {
  70. r, err := n.QueryContext(ctx, arg)
  71. if err != nil {
  72. return nil, err
  73. }
  74. return &Rows{Rows: r, Mapper: n.Stmt.Mapper, unsafe: isUnsafe(n)}, err
  75. }
  76. // QueryRowxContext this NamedStmt. Because of limitations with QueryRow, this is
  77. // an alias for QueryRow.
  78. // Any named placeholder parameters are replaced with fields from arg.
  79. func (n *NamedStmt) QueryRowxContext(ctx context.Context, arg interface{}) *Row {
  80. return n.QueryRowContext(ctx, arg)
  81. }
  82. // SelectContext using this NamedStmt
  83. // Any named placeholder parameters are replaced with fields from arg.
  84. func (n *NamedStmt) SelectContext(ctx context.Context, dest interface{}, arg interface{}) error {
  85. rows, err := n.QueryxContext(ctx, arg)
  86. if err != nil {
  87. return err
  88. }
  89. // if something happens here, we want to make sure the rows are Closed
  90. defer rows.Close()
  91. return scanAll(rows, dest, false)
  92. }
  93. // GetContext using this NamedStmt
  94. // Any named placeholder parameters are replaced with fields from arg.
  95. func (n *NamedStmt) GetContext(ctx context.Context, dest interface{}, arg interface{}) error {
  96. r := n.QueryRowxContext(ctx, arg)
  97. return r.scanAny(dest, false)
  98. }
  99. // NamedQueryContext binds a named query and then runs Query on the result using the
  100. // provided Ext (sqlx.Tx, sqlx.Db). It works with both structs and with
  101. // map[string]interface{} types.
  102. func NamedQueryContext(ctx context.Context, e ExtContext, query string, arg interface{}) (*Rows, error) {
  103. q, args, err := bindNamedMapper(BindType(e.DriverName()), query, arg, mapperFor(e))
  104. if err != nil {
  105. return nil, err
  106. }
  107. return e.QueryxContext(ctx, q, args...)
  108. }
  109. // NamedExecContext uses BindStruct to get a query executable by the driver and
  110. // then runs Exec on the result. Returns an error from the binding
  111. // or the query execution itself.
  112. func NamedExecContext(ctx context.Context, e ExtContext, query string, arg interface{}) (sql.Result, error) {
  113. q, args, err := bindNamedMapper(BindType(e.DriverName()), query, arg, mapperFor(e))
  114. if err != nil {
  115. return nil, err
  116. }
  117. return e.ExecContext(ctx, q, args...)
  118. }