bulkinserter_test.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. package sqlx
  2. import (
  3. "database/sql"
  4. "errors"
  5. "strconv"
  6. "testing"
  7. "github.com/DATA-DOG/go-sqlmock"
  8. "github.com/stretchr/testify/assert"
  9. "github.com/tal-tech/go-zero/core/logx"
  10. )
  11. type mockedConn struct {
  12. query string
  13. args []interface{}
  14. execErr error
  15. }
  16. func (c *mockedConn) Exec(query string, args ...interface{}) (sql.Result, error) {
  17. c.query = query
  18. c.args = args
  19. return nil, c.execErr
  20. }
  21. func (c *mockedConn) Prepare(query string) (StmtSession, error) {
  22. panic("should not called")
  23. }
  24. func (c *mockedConn) QueryRow(v interface{}, query string, args ...interface{}) error {
  25. panic("should not called")
  26. }
  27. func (c *mockedConn) QueryRowPartial(v interface{}, query string, args ...interface{}) error {
  28. panic("should not called")
  29. }
  30. func (c *mockedConn) QueryRows(v interface{}, query string, args ...interface{}) error {
  31. panic("should not called")
  32. }
  33. func (c *mockedConn) QueryRowsPartial(v interface{}, query string, args ...interface{}) error {
  34. panic("should not called")
  35. }
  36. func (c *mockedConn) Transact(func(session Session) error) error {
  37. panic("should not called")
  38. }
  39. func TestBulkInserter(t *testing.T) {
  40. runSqlTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) {
  41. var conn mockedConn
  42. inserter, err := NewBulkInserter(&conn, `INSERT INTO classroom_dau(classroom, user, count) VALUES(?, ?, ?)`)
  43. assert.Nil(t, err)
  44. for i := 0; i < 5; i++ {
  45. assert.Nil(t, inserter.Insert("class_"+strconv.Itoa(i), "user_"+strconv.Itoa(i), i))
  46. }
  47. inserter.Flush()
  48. assert.Equal(t, `INSERT INTO classroom_dau(classroom, user, count) VALUES `+
  49. `('class_0', 'user_0', 0), ('class_1', 'user_1', 1), ('class_2', 'user_2', 2), `+
  50. `('class_3', 'user_3', 3), ('class_4', 'user_4', 4)`,
  51. conn.query)
  52. assert.Nil(t, conn.args)
  53. })
  54. }
  55. func TestBulkInserterSuffix(t *testing.T) {
  56. runSqlTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) {
  57. var conn mockedConn
  58. inserter, err := NewBulkInserter(&conn, `INSERT INTO classroom_dau(classroom, user, count) VALUES`+
  59. `(?, ?, ?) ON DUPLICATE KEY UPDATE is_overtime=VALUES(is_overtime)`)
  60. assert.Nil(t, err)
  61. assert.Nil(t, inserter.UpdateStmt(`INSERT INTO classroom_dau(classroom, user, count) VALUES`+
  62. `(?, ?, ?) ON DUPLICATE KEY UPDATE is_overtime=VALUES(is_overtime)`))
  63. for i := 0; i < 5; i++ {
  64. assert.Nil(t, inserter.Insert("class_"+strconv.Itoa(i), "user_"+strconv.Itoa(i), i))
  65. }
  66. inserter.SetResultHandler(func(result sql.Result, err error) {})
  67. inserter.Flush()
  68. assert.Equal(t, `INSERT INTO classroom_dau(classroom, user, count) VALUES `+
  69. `('class_0', 'user_0', 0), ('class_1', 'user_1', 1), ('class_2', 'user_2', 2), `+
  70. `('class_3', 'user_3', 3), ('class_4', 'user_4', 4) ON DUPLICATE KEY UPDATE is_overtime=VALUES(is_overtime)`,
  71. conn.query)
  72. assert.Nil(t, conn.args)
  73. })
  74. }
  75. func TestBulkInserterBadStatement(t *testing.T) {
  76. runSqlTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) {
  77. var conn mockedConn
  78. _, err := NewBulkInserter(&conn, "foo")
  79. assert.NotNil(t, err)
  80. })
  81. }
  82. func TestBulkInserter_Update(t *testing.T) {
  83. conn := mockedConn{
  84. execErr: errors.New("foo"),
  85. }
  86. _, err := NewBulkInserter(&conn, `INSERT INTO classroom_dau(classroom, user, count) VALUES()`)
  87. assert.NotNil(t, err)
  88. _, err = NewBulkInserter(&conn, `INSERT INTO classroom_dau(classroom, user, count) VALUES(?)`)
  89. assert.NotNil(t, err)
  90. inserter, err := NewBulkInserter(&conn, `INSERT INTO classroom_dau(classroom, user, count) VALUES(?, ?, ?)`)
  91. assert.Nil(t, err)
  92. inserter.inserter.Execute([]string{"bar"})
  93. inserter.SetResultHandler(func(result sql.Result, err error) {
  94. })
  95. inserter.UpdateOrDelete(func() {})
  96. inserter.inserter.Execute([]string(nil))
  97. assert.NotNil(t, inserter.UpdateStmt("foo"))
  98. assert.NotNil(t, inserter.Insert("foo", "bar"))
  99. }
  100. func runSqlTest(t *testing.T, fn func(db *sql.DB, mock sqlmock.Sqlmock)) {
  101. logx.Disable()
  102. db, mock, err := sqlmock.New()
  103. if err != nil {
  104. t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
  105. }
  106. defer db.Close()
  107. fn(db, mock)
  108. if err := mock.ExpectationsWereMet(); err != nil {
  109. t.Errorf("there were unfulfilled expectations: %s", err)
  110. }
  111. }