github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/depends/kit/sqlx/scanner/scan_test.go (about) 1 package scanner_test 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/DATA-DOG/go-sqlmock" 8 "github.com/onsi/gomega" 9 10 . "github.com/machinefi/w3bstream/pkg/depends/kit/sqlx/scanner" 11 ) 12 13 type T struct { 14 I int `db:"f_i"` 15 S string `db:"f_s"` 16 } 17 18 type Any string 19 20 type T2 T 21 22 func (t *T2) ColumnReceivers() map[string]interface{} { 23 return map[string]interface{}{ 24 "f_i": &t.I, 25 "f_s": &t.S, 26 } 27 } 28 29 type TDataList struct { 30 Data []T 31 } 32 33 func (*TDataList) New() interface{} { return &T{} } 34 35 func (l *TDataList) Next(v interface{}) error { 36 t := v.(*T) 37 l.Data = append(l.Data, *t) 38 return nil 39 } 40 41 func BenchmarkScan(b *testing.B) { 42 db, mock, _ := sqlmock.New() 43 defer db.Close() 44 45 b.Run("ScanToStruct", func(b *testing.B) { 46 query := "SELECT f_i,f_s FROM t" 47 _ = mock.ExpectQuery(query). 48 WillReturnRows( 49 mock.NewRows([]string{"f_i", "f_s"}).AddRow(2, "4"), 50 ) 51 target := &T{} 52 for i := 0; i < b.N; i++ { 53 rows, _ := db.Query(query) 54 _ = Scan(context.Background(), rows, target) 55 } 56 b.Log(target) 57 }) 58 b.Run("ScanToColumnReceivers", func(b *testing.B) { 59 sql := "SELECT f_i,f_s from t" 60 61 mockRows := mock.NewRows([]string{"f_i", "f_s"}) 62 mockRows.AddRow(2, "4") 63 64 _ = mock.ExpectQuery(sql).WillReturnRows(mockRows) 65 66 target := &T2{} 67 68 for i := 0; i < b.N; i++ { 69 rows, _ := db.Query(sql) 70 _ = Scan(context.Background(), rows, target) 71 } 72 73 b.Log(target) 74 }) 75 } 76 77 func TestScan(t *testing.T) { 78 db, mock, _ := sqlmock.New() 79 defer db.Close() 80 81 t.Run("ScanToStruct", func(t *testing.T) { 82 sql := "SELECT f_i,f_s from t" 83 84 mockRows := mock.NewRows([]string{"f_i", "f_s"}) 85 mockRows.AddRow(2, "4") 86 87 _ = mock.ExpectQuery(sql).WillReturnRows(mockRows) 88 89 target := &T{} 90 rows, _ := db.Query(sql) 91 err := Scan(context.Background(), rows, target) 92 gomega.NewWithT(t).Expect(err).To(gomega.BeNil()) 93 gomega.NewWithT(t).Expect(target).To(gomega.Equal(&T{ 94 I: 2, 95 S: "4", 96 })) 97 }) 98 99 t.Run("ScanToStructWithColumnReceivers", func(t *testing.T) { 100 sql := "SELECT f_i,f_s from t" 101 102 mockRows := mock.NewRows([]string{"f_i", "f_s"}) 103 mockRows.AddRow(2, "4") 104 105 _ = mock.ExpectQuery(sql).WillReturnRows(mockRows) 106 107 target := &T2{} 108 rows, _ := db.Query(sql) 109 err := Scan(context.Background(), rows, target) 110 gomega.NewWithT(t).Expect(err).To(gomega.BeNil()) 111 gomega.NewWithT(t).Expect(target).To(gomega.Equal(&T2{ 112 I: 2, 113 S: "4", 114 })) 115 }) 116 117 t.Run("ScanToStructWithoutNoRecord", func(t *testing.T) { 118 sql := "SELECT f_i,f_s from t" 119 120 mockRows := mock.NewRows([]string{"f_i", "f_s"}) 121 122 _ = mock.ExpectQuery(sql).WillReturnRows(mockRows) 123 124 target := &T{} 125 rows, err := db.Query(sql) 126 gomega.NewWithT(t).Expect(err).To(gomega.BeNil()) 127 128 err = Scan(context.Background(), rows, target) 129 gomega.NewWithT(t).Expect(err).To(gomega.Equal(RecordNotFound)) 130 }) 131 132 t.Run("Scan to count", func(t *testing.T) { 133 mockRows := mock.NewRows([]string{"count(1)"}) 134 mockRows.AddRow(10) 135 136 _ = mock.ExpectQuery("SELECT .+ from t").WillReturnRows(mockRows) 137 138 count := 0 139 rows, err := db.Query("SELECT count(1) from t") 140 gomega.NewWithT(t).Expect(err).To(gomega.BeNil()) 141 142 err = Scan(context.Background(), rows, &count) 143 gomega.NewWithT(t).Expect(err).To(gomega.BeNil()) 144 gomega.NewWithT(t).Expect(count).To(gomega.Equal(10)) 145 }) 146 147 t.Run("ScanToCountFailedWhenBadReceiver", func(t *testing.T) { 148 mockRows := mock.NewRows([]string{"count(1)"}) 149 mockRows.AddRow(10) 150 151 _ = mock.ExpectQuery("SELECT .+ from t").WillReturnRows(mockRows) 152 153 v := Any("") 154 rows, err := db.Query("SELECT count(1) from t") 155 gomega.NewWithT(t).Expect(err).To(gomega.BeNil()) 156 157 err = Scan(context.Background(), rows, &v) 158 gomega.NewWithT(t).Expect(err).NotTo(gomega.BeNil()) 159 }) 160 161 t.Run("ScanToSlice", func(t *testing.T) { 162 mockRows := mock.NewRows([]string{"f_i", "f_s"}) 163 mockRows.AddRow(2, "2") 164 mockRows.AddRow(3, "3") 165 166 _ = mock.ExpectQuery("SELECT .+ from t").WillReturnRows(mockRows) 167 168 list := make([]T, 0) 169 rows, err := db.Query("SELECT f_i,f_b from t") 170 gomega.NewWithT(t).Expect(err).To(gomega.BeNil()) 171 172 err = Scan(context.Background(), rows, &list) 173 174 gomega.NewWithT(t).Expect(err).To(gomega.BeNil()) 175 gomega.NewWithT(t).Expect(list).To(gomega.Equal([]T{ 176 { 177 I: 2, 178 S: "2", 179 }, 180 { 181 I: 3, 182 S: "3", 183 }, 184 })) 185 }) 186 187 t.Run("ScanToIter", func(t *testing.T) { 188 mockRows := mock.NewRows([]string{"f_i", "f_s"}) 189 mockRows.AddRow(2, "2") 190 mockRows.AddRow(3, "3") 191 192 _ = mock.ExpectQuery("SELECT .+ from t").WillReturnRows(mockRows) 193 194 rows, err := db.Query("SELECT f_i,f_b from t") 195 gomega.NewWithT(t).Expect(err).To(gomega.BeNil()) 196 197 list := TDataList{} 198 199 err = Scan(context.Background(), rows, &list) 200 201 gomega.NewWithT(t).Expect(err).To(gomega.BeNil()) 202 gomega.NewWithT(t).Expect(list.Data).To(gomega.Equal([]T{ 203 { 204 I: 2, 205 S: "2", 206 }, 207 { 208 I: 3, 209 S: "3", 210 }, 211 })) 212 }) 213 }