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