http urls monitor.

insert.go 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. package sqlbuilder
  2. import (
  3. "context"
  4. "database/sql"
  5. "upper.io/db.v3/internal/immutable"
  6. "upper.io/db.v3/internal/sqladapter/exql"
  7. )
  8. type inserterQuery struct {
  9. table string
  10. enqueuedValues [][]interface{}
  11. returning []exql.Fragment
  12. columns []exql.Fragment
  13. values []*exql.Values
  14. arguments []interface{}
  15. extra string
  16. amendFn func(string) string
  17. }
  18. func (iq *inserterQuery) processValues() ([]*exql.Values, []interface{}, error) {
  19. var values []*exql.Values
  20. var arguments []interface{}
  21. var mapOptions *MapOptions
  22. if len(iq.enqueuedValues) > 1 {
  23. mapOptions = &MapOptions{IncludeZeroed: true, IncludeNil: true}
  24. }
  25. for _, enqueuedValue := range iq.enqueuedValues {
  26. if len(enqueuedValue) == 1 {
  27. // If and only if we passed one argument to Values.
  28. ff, vv, err := Map(enqueuedValue[0], mapOptions)
  29. if err == nil {
  30. // If we didn't have any problem with mapping we can convert it into
  31. // columns and values.
  32. columns, vals, args, _ := toColumnsValuesAndArguments(ff, vv)
  33. values, arguments = append(values, vals), append(arguments, args...)
  34. if len(iq.columns) == 0 {
  35. for _, c := range columns.Columns {
  36. iq.columns = append(iq.columns, c)
  37. }
  38. }
  39. continue
  40. }
  41. // The only error we can expect without exiting is this argument not
  42. // being a map or struct, in which case we can continue.
  43. if err != ErrExpectingPointerToEitherMapOrStruct {
  44. return nil, nil, err
  45. }
  46. }
  47. if len(iq.columns) == 0 || len(enqueuedValue) == len(iq.columns) {
  48. arguments = append(arguments, enqueuedValue...)
  49. l := len(enqueuedValue)
  50. placeholders := make([]exql.Fragment, l)
  51. for i := 0; i < l; i++ {
  52. placeholders[i] = exql.RawValue(`?`)
  53. }
  54. values = append(values, exql.NewValueGroup(placeholders...))
  55. }
  56. }
  57. return values, arguments, nil
  58. }
  59. func (iq *inserterQuery) statement() *exql.Statement {
  60. stmt := &exql.Statement{
  61. Type: exql.Insert,
  62. Table: exql.TableWithName(iq.table),
  63. }
  64. if len(iq.values) > 0 {
  65. stmt.Values = exql.JoinValueGroups(iq.values...)
  66. }
  67. if len(iq.columns) > 0 {
  68. stmt.Columns = exql.JoinColumns(iq.columns...)
  69. }
  70. if len(iq.returning) > 0 {
  71. stmt.Returning = exql.ReturningColumns(iq.returning...)
  72. }
  73. stmt.SetAmendment(iq.amendFn)
  74. return stmt
  75. }
  76. type inserter struct {
  77. builder *sqlBuilder
  78. fn func(*inserterQuery) error
  79. prev *inserter
  80. }
  81. var _ = immutable.Immutable(&inserter{})
  82. func (ins *inserter) SQLBuilder() *sqlBuilder {
  83. if ins.prev == nil {
  84. return ins.builder
  85. }
  86. return ins.prev.SQLBuilder()
  87. }
  88. func (ins *inserter) template() *exql.Template {
  89. return ins.SQLBuilder().t.Template
  90. }
  91. func (ins *inserter) String() string {
  92. s, err := ins.Compile()
  93. if err != nil {
  94. panic(err.Error())
  95. }
  96. return prepareQueryForDisplay(s)
  97. }
  98. func (ins *inserter) frame(fn func(*inserterQuery) error) *inserter {
  99. return &inserter{prev: ins, fn: fn}
  100. }
  101. func (ins *inserter) Batch(n int) *BatchInserter {
  102. return newBatchInserter(ins, n)
  103. }
  104. func (ins *inserter) Amend(fn func(string) string) Inserter {
  105. return ins.frame(func(iq *inserterQuery) error {
  106. iq.amendFn = fn
  107. return nil
  108. })
  109. }
  110. func (ins *inserter) Arguments() []interface{} {
  111. iq, err := ins.build()
  112. if err != nil {
  113. return nil
  114. }
  115. return iq.arguments
  116. }
  117. func (ins *inserter) Returning(columns ...string) Inserter {
  118. return ins.frame(func(iq *inserterQuery) error {
  119. columnsToFragments(&iq.returning, columns)
  120. return nil
  121. })
  122. }
  123. func (ins *inserter) Exec() (sql.Result, error) {
  124. return ins.ExecContext(ins.SQLBuilder().sess.Context())
  125. }
  126. func (ins *inserter) ExecContext(ctx context.Context) (sql.Result, error) {
  127. iq, err := ins.build()
  128. if err != nil {
  129. return nil, err
  130. }
  131. return ins.SQLBuilder().sess.StatementExec(ctx, iq.statement(), iq.arguments...)
  132. }
  133. func (ins *inserter) Prepare() (*sql.Stmt, error) {
  134. return ins.PrepareContext(ins.SQLBuilder().sess.Context())
  135. }
  136. func (ins *inserter) PrepareContext(ctx context.Context) (*sql.Stmt, error) {
  137. iq, err := ins.build()
  138. if err != nil {
  139. return nil, err
  140. }
  141. return ins.SQLBuilder().sess.StatementPrepare(ctx, iq.statement())
  142. }
  143. func (ins *inserter) Query() (*sql.Rows, error) {
  144. return ins.QueryContext(ins.SQLBuilder().sess.Context())
  145. }
  146. func (ins *inserter) QueryContext(ctx context.Context) (*sql.Rows, error) {
  147. iq, err := ins.build()
  148. if err != nil {
  149. return nil, err
  150. }
  151. return ins.SQLBuilder().sess.StatementQuery(ctx, iq.statement(), iq.arguments...)
  152. }
  153. func (ins *inserter) QueryRow() (*sql.Row, error) {
  154. return ins.QueryRowContext(ins.SQLBuilder().sess.Context())
  155. }
  156. func (ins *inserter) QueryRowContext(ctx context.Context) (*sql.Row, error) {
  157. iq, err := ins.build()
  158. if err != nil {
  159. return nil, err
  160. }
  161. return ins.SQLBuilder().sess.StatementQueryRow(ctx, iq.statement(), iq.arguments...)
  162. }
  163. func (ins *inserter) Iterator() Iterator {
  164. return ins.IteratorContext(ins.SQLBuilder().sess.Context())
  165. }
  166. func (ins *inserter) IteratorContext(ctx context.Context) Iterator {
  167. rows, err := ins.QueryContext(ctx)
  168. return &iterator{ins.SQLBuilder().sess, rows, err}
  169. }
  170. func (ins *inserter) Into(table string) Inserter {
  171. return ins.frame(func(iq *inserterQuery) error {
  172. iq.table = table
  173. return nil
  174. })
  175. }
  176. func (ins *inserter) Columns(columns ...string) Inserter {
  177. return ins.frame(func(iq *inserterQuery) error {
  178. columnsToFragments(&iq.columns, columns)
  179. return nil
  180. })
  181. }
  182. func (ins *inserter) Values(values ...interface{}) Inserter {
  183. return ins.frame(func(iq *inserterQuery) error {
  184. iq.enqueuedValues = append(iq.enqueuedValues, values)
  185. return nil
  186. })
  187. }
  188. func (ins *inserter) statement() (*exql.Statement, error) {
  189. iq, err := ins.build()
  190. if err != nil {
  191. return nil, err
  192. }
  193. return iq.statement(), nil
  194. }
  195. func (ins *inserter) build() (*inserterQuery, error) {
  196. iq, err := immutable.FastForward(ins)
  197. if err != nil {
  198. return nil, err
  199. }
  200. ret := iq.(*inserterQuery)
  201. ret.values, ret.arguments, err = ret.processValues()
  202. if err != nil {
  203. return nil, err
  204. }
  205. return ret, nil
  206. }
  207. func (ins *inserter) Compile() (string, error) {
  208. s, err := ins.statement()
  209. if err != nil {
  210. return "", err
  211. }
  212. return s.Compile(ins.template())
  213. }
  214. func (ins *inserter) Prev() immutable.Immutable {
  215. if ins == nil {
  216. return nil
  217. }
  218. return ins.prev
  219. }
  220. func (ins *inserter) Fn(in interface{}) error {
  221. if ins.fn == nil {
  222. return nil
  223. }
  224. return ins.fn(in.(*inserterQuery))
  225. }
  226. func (ins *inserter) Base() interface{} {
  227. return &inserterQuery{}
  228. }
  229. func columnsToFragments(dst *[]exql.Fragment, columns []string) error {
  230. l := len(columns)
  231. f := make([]exql.Fragment, l)
  232. for i := 0; i < l; i++ {
  233. f[i] = exql.ColumnWithName(columns[i])
  234. }
  235. *dst = append(*dst, f...)
  236. return nil
  237. }