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  }