...

Source file src/github.com/doug-martin/goqu/v9/exec/query_executor_internal_test.go

Documentation: github.com/doug-martin/goqu/v9/exec

     1  package exec
     2  
     3  import (
     4  	"context"
     5  	"database/sql"
     6  	"encoding/json"
     7  	"fmt"
     8  	"strings"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/DATA-DOG/go-sqlmock"
    13  	"github.com/stretchr/testify/suite"
    14  )
    15  
    16  var (
    17  	testAddr1                  = "111 Test Addr"
    18  	testAddr2                  = "211 Test Addr"
    19  	testName1                  = "Test1"
    20  	testName2                  = "Test2"
    21  	testPhone1                 = "111-111-1111"
    22  	testPhone2                 = "222-222-2222"
    23  	testAge1             int64 = 10
    24  	testAge2             int64 = 20
    25  	testByteSliceContent       = "byte slice result"
    26  	otherAddr1                 = "111 Test Addr Other"
    27  	otherAddr2                 = "211 Test Addr Other"
    28  	otherName1                 = "Test1 Other"
    29  	otherName2                 = "Test2 Other"
    30  )
    31  
    32  type queryExecutorSuite struct {
    33  	suite.Suite
    34  }
    35  
    36  func (qes *queryExecutorSuite) TestWithError() {
    37  	type StructWithTags struct {
    38  		Address string `db:"address"`
    39  		Name    string `db:"name"`
    40  	}
    41  
    42  	ctx := context.Background()
    43  	db, _, err := sqlmock.New()
    44  	qes.NoError(err)
    45  	expectedErr := fmt.Errorf("crud exec error")
    46  	e := newQueryExecutor(db, expectedErr, `SELECT * FROM "items"`)
    47  	var items []StructWithTags
    48  	qes.EqualError(e.ScanStructs(&items), expectedErr.Error())
    49  	qes.EqualError(e.ScanStructsContext(ctx, &items), expectedErr.Error())
    50  	found, err := e.ScanStruct(&StructWithTags{})
    51  	qes.EqualError(err, expectedErr.Error())
    52  	qes.False(found)
    53  	found, err = e.ScanStructContext(ctx, &StructWithTags{})
    54  	qes.EqualError(err, expectedErr.Error())
    55  	qes.False(found)
    56  	var vals []string
    57  	qes.EqualError(e.ScanVals(&vals), expectedErr.Error())
    58  	qes.EqualError(e.ScanValsContext(ctx, &vals), expectedErr.Error())
    59  	var val string
    60  	found, err = e.ScanVal(&val)
    61  	qes.EqualError(err, expectedErr.Error())
    62  	qes.False(found)
    63  	found, err = e.ScanValContext(ctx, &val)
    64  	qes.EqualError(err, expectedErr.Error())
    65  	qes.False(found)
    66  }
    67  
    68  func (qes *queryExecutorSuite) TestToSQL() {
    69  	db, _, err := sqlmock.New()
    70  	qes.NoError(err)
    71  
    72  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
    73  	query, args, err := e.ToSQL()
    74  	qes.NoError(err)
    75  	qes.Equal(`SELECT * FROM "items"`, query)
    76  	qes.Empty(args)
    77  }
    78  
    79  func (qes *queryExecutorSuite) TestScanStructs_withTaggedFields() {
    80  	type StructWithTags struct {
    81  		Address string `db:"address"`
    82  		Name    string `db:"name"`
    83  	}
    84  
    85  	db, mock, err := sqlmock.New()
    86  	qes.NoError(err)
    87  
    88  	mock.ExpectQuery(`SELECT \* FROM "items"`).
    89  		WithArgs().
    90  		WillReturnRows(sqlmock.NewRows([]string{"address", "name"}).
    91  			AddRow(testAddr1, testName1).
    92  			AddRow(testAddr2, testName2),
    93  		)
    94  
    95  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
    96  
    97  	var items []StructWithTags
    98  	qes.NoError(e.ScanStructs(&items))
    99  	qes.Equal([]StructWithTags{
   100  		{Address: testAddr1, Name: testName1},
   101  		{Address: testAddr2, Name: testName2},
   102  	}, items)
   103  }
   104  
   105  func (qes *queryExecutorSuite) TestScanStructs_withUntaggedFields() {
   106  	type StructWithNoTags struct {
   107  		Address string
   108  		Name    string
   109  	}
   110  	db, mock, err := sqlmock.New()
   111  	qes.NoError(err)
   112  
   113  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   114  		WithArgs().
   115  		WillReturnRows(sqlmock.NewRows([]string{"address", "name"}).
   116  			AddRow(testAddr1, testName1).
   117  			AddRow(testAddr2, testName2))
   118  
   119  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   120  
   121  	var items []StructWithNoTags
   122  	qes.NoError(e.ScanStructs(&items))
   123  	qes.Equal([]StructWithNoTags{
   124  		{Address: testAddr1, Name: testName1},
   125  		{Address: testAddr2, Name: testName2},
   126  	}, items)
   127  }
   128  
   129  func (qes *queryExecutorSuite) TestScanStructs_withPointerFields() {
   130  	type StructWithPointerFields struct {
   131  		Str   *string
   132  		Time  *time.Time
   133  		Bool  *bool
   134  		Int   *int64
   135  		Float *float64
   136  	}
   137  	db, mock, err := sqlmock.New()
   138  	qes.NoError(err)
   139  	now := time.Now()
   140  	str1, str2 := "str1", "str2"
   141  	t := true
   142  	var i1, i2 int64 = 1, 2
   143  	f1, f2 := 1.1, 2.1
   144  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   145  		WithArgs().
   146  		WillReturnRows(sqlmock.NewRows([]string{"str", "time", "bool", "int", "float"}).
   147  			AddRow(str1, now, true, i1, f1).
   148  			AddRow(str2, now, true, i2, f2).
   149  			AddRow(nil, nil, nil, nil, nil),
   150  		)
   151  
   152  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   153  
   154  	var items []StructWithPointerFields
   155  	qes.NoError(e.ScanStructs(&items))
   156  	qes.Equal([]StructWithPointerFields{
   157  		{Str: &str1, Time: &now, Bool: &t, Int: &i1, Float: &f1},
   158  		{Str: &str2, Time: &now, Bool: &t, Int: &i2, Float: &f2},
   159  		{},
   160  	}, items)
   161  }
   162  
   163  func (qes *queryExecutorSuite) TestScanStructs_withPrivateFields() {
   164  	type StructWithPrivateTags struct {
   165  		private string // nolint:structcheck,unused // need for test
   166  		Address string `db:"address"`
   167  		Name    string `db:"name"`
   168  	}
   169  
   170  	db, mock, err := sqlmock.New()
   171  	qes.NoError(err)
   172  
   173  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   174  		WithArgs().
   175  		WillReturnRows(sqlmock.NewRows([]string{"address", "name"}).
   176  			AddRow(testAddr1, testName1).
   177  			AddRow(testAddr2, testName2),
   178  		)
   179  
   180  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   181  
   182  	var items []StructWithPrivateTags
   183  	qes.NoError(e.ScanStructs(&items))
   184  	qes.Equal([]StructWithPrivateTags{
   185  		{Address: testAddr1, Name: testName1},
   186  		{Address: testAddr2, Name: testName2},
   187  	}, items)
   188  }
   189  
   190  func (qes *queryExecutorSuite) TestScanStructs_pointers() {
   191  	type StructWithTags struct {
   192  		Address string `db:"address"`
   193  		Name    string `db:"name"`
   194  	}
   195  
   196  	db, mock, err := sqlmock.New()
   197  	qes.NoError(err)
   198  
   199  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   200  		WithArgs().
   201  		WillReturnRows(sqlmock.NewRows([]string{"address", "name"}).
   202  			AddRow(testAddr1, testName1).
   203  			AddRow(testAddr2, testName2),
   204  		)
   205  
   206  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   207  
   208  	var items []*StructWithTags
   209  	qes.NoError(e.ScanStructs(&items))
   210  	qes.Equal([]*StructWithTags{
   211  		{Address: testAddr1, Name: testName1},
   212  		{Address: testAddr2, Name: testName2},
   213  	}, items)
   214  }
   215  
   216  func (qes *queryExecutorSuite) TestScanStructs_withIgnoredEmbeddedStruct() {
   217  	type StructWithTags struct {
   218  		Address string `db:"address"`
   219  		Name    string `db:"name"`
   220  	}
   221  
   222  	type ComposedIgnoredStruct struct {
   223  		StructWithTags `db:"-"`
   224  		PhoneNumber    string `db:"phone_number"`
   225  		Age            int64  `db:"age"`
   226  	}
   227  
   228  	db, mock, err := sqlmock.New()
   229  	qes.NoError(err)
   230  
   231  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   232  		WithArgs().
   233  		WillReturnRows(sqlmock.NewRows([]string{"phone_number", "age"}).
   234  			AddRow(testPhone1, testAge1).AddRow(testPhone2, testAge2),
   235  		)
   236  
   237  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   238  
   239  	var composed []ComposedIgnoredStruct
   240  	qes.NoError(e.ScanStructs(&composed))
   241  	qes.Equal([]ComposedIgnoredStruct{
   242  		{StructWithTags: StructWithTags{}, PhoneNumber: testPhone1, Age: testAge1},
   243  		{StructWithTags: StructWithTags{}, PhoneNumber: testPhone2, Age: testAge2},
   244  	}, composed)
   245  }
   246  
   247  func (qes *queryExecutorSuite) TestScanStructs_withEmbeddedStruct() {
   248  	type StructWithTags struct {
   249  		Address string `db:"address"`
   250  		Name    string `db:"name"`
   251  	}
   252  	type ComposedStruct struct {
   253  		StructWithTags
   254  		PhoneNumber string `db:"phone_number"`
   255  		Age         int64  `db:"age"`
   256  	}
   257  	db, mock, err := sqlmock.New()
   258  	qes.NoError(err)
   259  
   260  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   261  		WithArgs().
   262  		WillReturnRows(sqlmock.NewRows([]string{"address", "name", "phone_number", "age"}).
   263  			AddRow(testAddr1, testName1, testPhone1, testAge1).
   264  			AddRow(testAddr2, testName2, testPhone2, testAge2),
   265  		)
   266  
   267  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   268  
   269  	var composed []ComposedStruct
   270  	qes.NoError(e.ScanStructs(&composed))
   271  	qes.Equal([]ComposedStruct{
   272  		{StructWithTags: StructWithTags{Address: testAddr1, Name: testName1}, PhoneNumber: testPhone1, Age: testAge1},
   273  		{StructWithTags: StructWithTags{Address: testAddr2, Name: testName2}, PhoneNumber: testPhone2, Age: testAge2},
   274  	}, composed)
   275  }
   276  
   277  func (qes *queryExecutorSuite) TestScanStructs_pointersWithEmbeddedStruct() {
   278  	type StructWithTags struct {
   279  		Address string `db:"address"`
   280  		Name    string `db:"name"`
   281  	}
   282  	type ComposedStruct struct {
   283  		StructWithTags
   284  		PhoneNumber string `db:"phone_number"`
   285  		Age         int64  `db:"age"`
   286  	}
   287  
   288  	db, mock, err := sqlmock.New()
   289  	qes.NoError(err)
   290  
   291  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   292  		WithArgs().
   293  		WillReturnRows(sqlmock.NewRows([]string{"address", "name", "phone_number", "age"}).
   294  			AddRow(testAddr1, testName1, testPhone1, testAge1).
   295  			AddRow(testAddr2, testName2, testPhone2, testAge2),
   296  		)
   297  
   298  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   299  
   300  	var composed []*ComposedStruct
   301  	qes.NoError(e.ScanStructs(&composed))
   302  	qes.Equal([]*ComposedStruct{
   303  		{StructWithTags: StructWithTags{Address: testAddr1, Name: testName1}, PhoneNumber: testPhone1, Age: testAge1},
   304  		{StructWithTags: StructWithTags{Address: testAddr2, Name: testName2}, PhoneNumber: testPhone2, Age: testAge2},
   305  	}, composed)
   306  }
   307  
   308  func (qes *queryExecutorSuite) TestScanStructs_pointersWithEmbeddedStructDuplicateFields() {
   309  	type StructWithTags struct {
   310  		Address string `db:"address"`
   311  		Name    string `db:"name"`
   312  	}
   313  
   314  	type ComposedStructWithDuplicateFields struct {
   315  		StructWithTags
   316  		Address string `db:"other_address"`
   317  		Name    string `db:"other_name"`
   318  	}
   319  
   320  	db, mock, err := sqlmock.New()
   321  	qes.NoError(err)
   322  
   323  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   324  		WithArgs().
   325  		WillReturnRows(sqlmock.NewRows([]string{"address", "name", "other_address", "other_name"}).
   326  			AddRow(testAddr1, testName1, otherAddr1, otherName1).
   327  			AddRow(testAddr2, testName2, otherAddr2, otherName2),
   328  		)
   329  
   330  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   331  
   332  	var composed []*ComposedStructWithDuplicateFields
   333  	qes.NoError(e.ScanStructs(&composed))
   334  	qes.Equal([]*ComposedStructWithDuplicateFields{
   335  		{
   336  			StructWithTags: StructWithTags{Address: testAddr1, Name: testName1},
   337  			Address:        otherAddr1,
   338  			Name:           otherName1,
   339  		},
   340  		{
   341  			StructWithTags: StructWithTags{Address: testAddr2, Name: testName2},
   342  			Address:        otherAddr2,
   343  			Name:           otherName2,
   344  		},
   345  	}, composed)
   346  }
   347  
   348  func (qes *queryExecutorSuite) TestScanStructs_pointersWithEmbeddedPointerDuplicateFields() {
   349  	type StructWithTags struct {
   350  		Address string `db:"address"`
   351  		Name    string `db:"name"`
   352  	}
   353  
   354  	type ComposedWithWithPointerWithDuplicateFields struct {
   355  		*StructWithTags
   356  		Address string `db:"other_address"`
   357  		Name    string `db:"other_name"`
   358  	}
   359  
   360  	db, mock, err := sqlmock.New()
   361  	qes.NoError(err)
   362  
   363  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   364  		WithArgs().
   365  		WillReturnRows(sqlmock.NewRows([]string{"address", "name", "other_address", "other_name"}).
   366  			AddRow(testAddr1, testName1, otherAddr1, otherName1).
   367  			AddRow(testAddr2, testName2, otherAddr2, otherName2),
   368  		)
   369  
   370  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   371  
   372  	var composed []*ComposedWithWithPointerWithDuplicateFields
   373  	qes.NoError(e.ScanStructs(&composed))
   374  	qes.Equal([]*ComposedWithWithPointerWithDuplicateFields{
   375  		{
   376  			StructWithTags: &StructWithTags{Address: testAddr1, Name: testName1},
   377  			Address:        otherAddr1,
   378  			Name:           otherName1,
   379  		},
   380  		{
   381  			StructWithTags: &StructWithTags{Address: testAddr2, Name: testName2},
   382  			Address:        otherAddr2,
   383  			Name:           otherName2,
   384  		},
   385  	}, composed)
   386  }
   387  
   388  func (qes *queryExecutorSuite) TestScanStructs_withIgnoredEmbeddedPointerStruct() {
   389  	type StructWithTags struct {
   390  		Address string `db:"address"`
   391  		Name    string `db:"name"`
   392  	}
   393  
   394  	type ComposedIgnoredPointerStruct struct {
   395  		*StructWithTags `db:"-"`
   396  		PhoneNumber     string `db:"phone_number"`
   397  		Age             int64  `db:"age"`
   398  	}
   399  
   400  	db, mock, err := sqlmock.New()
   401  	qes.NoError(err)
   402  
   403  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   404  		WithArgs().
   405  		WillReturnRows(sqlmock.NewRows([]string{"phone_number", "age"}).
   406  			AddRow(testPhone1, testAge1).
   407  			AddRow(testPhone2, testAge2),
   408  		)
   409  
   410  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   411  
   412  	var composed []ComposedIgnoredPointerStruct
   413  	qes.NoError(e.ScanStructs(&composed))
   414  	qes.Equal([]ComposedIgnoredPointerStruct{
   415  		{PhoneNumber: testPhone1, Age: testAge1},
   416  		{PhoneNumber: testPhone2, Age: testAge2},
   417  	}, composed)
   418  }
   419  
   420  func (qes *queryExecutorSuite) TestScanStructs_withEmbeddedStructPointer() {
   421  	type StructWithTags struct {
   422  		Address string `db:"address"`
   423  		Name    string `db:"name"`
   424  	}
   425  
   426  	type ComposedWithPointerStruct struct {
   427  		*StructWithTags
   428  		PhoneNumber string `db:"phone_number"`
   429  		Age         int64  `db:"age"`
   430  	}
   431  
   432  	db, mock, err := sqlmock.New()
   433  	qes.NoError(err)
   434  
   435  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   436  		WithArgs().
   437  		WillReturnRows(sqlmock.NewRows([]string{"address", "name", "phone_number", "age"}).
   438  			AddRow(testAddr1, testName1, testPhone1, testAge1).
   439  			AddRow(testAddr2, testName2, testPhone2, testAge2),
   440  		)
   441  
   442  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   443  
   444  	var composed []ComposedWithPointerStruct
   445  	qes.NoError(e.ScanStructs(&composed))
   446  	qes.Equal([]ComposedWithPointerStruct{
   447  		{StructWithTags: &StructWithTags{Address: testAddr1, Name: testName1}, PhoneNumber: testPhone1, Age: testAge1},
   448  		{StructWithTags: &StructWithTags{Address: testAddr2, Name: testName2}, PhoneNumber: testPhone2, Age: testAge2},
   449  	}, composed)
   450  }
   451  
   452  func (qes *queryExecutorSuite) TestScanStructs_pointersWithEmbeddedStructPointer() {
   453  	type StructWithTags struct {
   454  		Address string `db:"address"`
   455  		Name    string `db:"name"`
   456  	}
   457  
   458  	type ComposedWithPointerStruct struct {
   459  		*StructWithTags
   460  		PhoneNumber string `db:"phone_number"`
   461  		Age         int64  `db:"age"`
   462  	}
   463  	db, mock, err := sqlmock.New()
   464  	qes.NoError(err)
   465  
   466  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   467  		WithArgs().
   468  		WillReturnRows(sqlmock.NewRows([]string{"address", "name", "phone_number", "age"}).
   469  			AddRow(testAddr1, testName1, testPhone1, testAge1).
   470  			AddRow(testAddr2, testName2, testPhone2, testAge2),
   471  		)
   472  
   473  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   474  
   475  	var composed []*ComposedWithPointerStruct
   476  	qes.NoError(e.ScanStructs(&composed))
   477  	qes.Equal([]*ComposedWithPointerStruct{
   478  		{StructWithTags: &StructWithTags{Address: testAddr1, Name: testName1}, PhoneNumber: testPhone1, Age: testAge1},
   479  		{StructWithTags: &StructWithTags{Address: testAddr2, Name: testName2}, PhoneNumber: testPhone2, Age: testAge2},
   480  	}, composed)
   481  }
   482  
   483  func (qes *queryExecutorSuite) TestScanStructs_badValue() {
   484  	type StructWithTags struct {
   485  		Address string `db:"address"`
   486  		Name    string `db:"name"`
   487  	}
   488  
   489  	tests := []struct {
   490  		name  string
   491  		items interface{}
   492  	}{
   493  		{
   494  			name:  "non-pointer items",
   495  			items: []StructWithTags{},
   496  		},
   497  		{
   498  			name:  "non-slice items",
   499  			items: &StructWithTags{},
   500  		},
   501  	}
   502  	for i := range tests {
   503  		test := tests[i]
   504  		qes.Run(test.name, func() {
   505  			db, mock, err := sqlmock.New()
   506  			qes.NoError(err)
   507  			mock.ExpectQuery(`SELECT \* FROM "items"`).
   508  				WithArgs().
   509  				WillReturnRows(sqlmock.NewRows([]string{"address", "name"}).
   510  					AddRow(testAddr1, testName1).AddRow(testAddr2, testName2),
   511  				)
   512  			e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   513  			qes.Equal(errUnsupportedScanStructsType, e.ScanStructs(test.items))
   514  		})
   515  	}
   516  }
   517  
   518  func (qes *queryExecutorSuite) TestScanStructs_queryError() {
   519  	type StructWithTags struct {
   520  		Address string `db:"address"`
   521  		Name    string `db:"name"`
   522  	}
   523  
   524  	db, mock, err := sqlmock.New()
   525  	qes.NoError(err)
   526  
   527  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   528  		WillReturnError(fmt.Errorf("queryExecutor error"))
   529  
   530  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   531  
   532  	var items []StructWithTags
   533  	qes.EqualError(e.ScanStructs(&items), "queryExecutor error")
   534  }
   535  
   536  func (qes *queryExecutorSuite) TestScanStructsContext_withTaggedFields() {
   537  	type StructWithTags struct {
   538  		Address string `db:"address"`
   539  		Name    string `db:"name"`
   540  	}
   541  
   542  	ctx := context.Background()
   543  	db, mock, err := sqlmock.New()
   544  	qes.NoError(err)
   545  
   546  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   547  		WithArgs().
   548  		WillReturnRows(sqlmock.NewRows([]string{"address", "name"}).
   549  			AddRow(testAddr1, testName1).
   550  			AddRow(testAddr2, testName2),
   551  		)
   552  
   553  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   554  
   555  	var items []StructWithTags
   556  	qes.NoError(e.ScanStructsContext(ctx, &items))
   557  	qes.Equal([]StructWithTags{
   558  		{Address: testAddr1, Name: testName1},
   559  		{Address: testAddr2, Name: testName2},
   560  	}, items)
   561  }
   562  
   563  func (qes *queryExecutorSuite) TestScanStructsContext_withUntaggedFields() {
   564  	type StructWithNoTags struct {
   565  		Address string
   566  		Name    string
   567  	}
   568  
   569  	ctx := context.Background()
   570  	db, mock, err := sqlmock.New()
   571  	qes.NoError(err)
   572  
   573  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   574  		WithArgs().
   575  		WillReturnRows(sqlmock.NewRows([]string{"address", "name"}).
   576  			AddRow(testAddr1, testName1).
   577  			AddRow(testAddr2, testName2),
   578  		)
   579  
   580  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   581  
   582  	var items []StructWithNoTags
   583  	qes.NoError(e.ScanStructsContext(ctx, &items))
   584  	qes.Equal([]StructWithNoTags{
   585  		{Address: testAddr1, Name: testName1},
   586  		{Address: testAddr2, Name: testName2},
   587  	}, items)
   588  }
   589  
   590  func (qes *queryExecutorSuite) TestScanStructsContext_withPointerFields() {
   591  	type StructWithPointerFields struct {
   592  		Address *string
   593  		Name    *string
   594  	}
   595  	ctx := context.Background()
   596  	db, mock, err := sqlmock.New()
   597  	qes.NoError(err)
   598  
   599  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   600  		WithArgs().
   601  		WillReturnRows(sqlmock.NewRows([]string{"address", "name"}).
   602  			AddRow(testAddr1, testName1).
   603  			AddRow(testAddr2, testName2),
   604  		)
   605  
   606  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   607  
   608  	var items []StructWithPointerFields
   609  	qes.NoError(e.ScanStructsContext(ctx, &items))
   610  	qes.Equal([]StructWithPointerFields{
   611  		{Address: &testAddr1, Name: &testName1},
   612  		{Address: &testAddr2, Name: &testName2},
   613  	}, items)
   614  }
   615  
   616  func (qes *queryExecutorSuite) TestScanStructsContext_pointers() {
   617  	type StructWithTags struct {
   618  		Address string `db:"address"`
   619  		Name    string `db:"name"`
   620  	}
   621  
   622  	ctx := context.Background()
   623  	db, mock, err := sqlmock.New()
   624  	qes.NoError(err)
   625  
   626  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   627  		WithArgs().
   628  		WillReturnRows(sqlmock.NewRows([]string{"address", "name"}).
   629  			AddRow(testAddr1, testName1).
   630  			AddRow(testAddr2, testName2),
   631  		)
   632  
   633  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   634  
   635  	var items []*StructWithTags
   636  	qes.NoError(e.ScanStructsContext(ctx, &items))
   637  	qes.Equal([]*StructWithTags{
   638  		{Address: testAddr1, Name: testName1},
   639  		{Address: testAddr2, Name: testName2},
   640  	}, items)
   641  }
   642  
   643  func (qes *queryExecutorSuite) TestScanStructsContext_withEmbeddedStruct() {
   644  	type StructWithTags struct {
   645  		Address string `db:"address"`
   646  		Name    string `db:"name"`
   647  	}
   648  	type ComposedStruct struct {
   649  		StructWithTags
   650  		PhoneNumber string `db:"phone_number"`
   651  		Age         int64  `db:"age"`
   652  	}
   653  	ctx := context.Background()
   654  	db, mock, err := sqlmock.New()
   655  	qes.NoError(err)
   656  
   657  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   658  		WithArgs().
   659  		WillReturnRows(sqlmock.NewRows([]string{"address", "name", "phone_number", "age"}).
   660  			AddRow(testAddr1, testName1, testPhone1, testAge1).
   661  			AddRow(testAddr2, testName2, testPhone2, testAge2),
   662  		)
   663  
   664  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   665  
   666  	var composed []ComposedStruct
   667  	qes.NoError(e.ScanStructsContext(ctx, &composed))
   668  	qes.Equal([]ComposedStruct{
   669  		{StructWithTags: StructWithTags{Address: testAddr1, Name: testName1}, PhoneNumber: testPhone1, Age: testAge1},
   670  		{StructWithTags: StructWithTags{Address: testAddr2, Name: testName2}, PhoneNumber: testPhone2, Age: testAge2},
   671  	}, composed)
   672  }
   673  
   674  func (qes *queryExecutorSuite) TestScanStructsContext_withIgnoredEmbeddedStruct() {
   675  	type StructWithTags struct {
   676  		Address string `db:"address"`
   677  		Name    string `db:"name"`
   678  	}
   679  
   680  	type ComposedIgnoredStruct struct {
   681  		StructWithTags `db:"-"`
   682  		PhoneNumber    string `db:"phone_number"`
   683  		Age            int64  `db:"age"`
   684  	}
   685  
   686  	ctx := context.Background()
   687  	db, mock, err := sqlmock.New()
   688  	qes.NoError(err)
   689  
   690  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   691  		WithArgs().
   692  		WillReturnRows(sqlmock.NewRows([]string{"phone_number", "age"}).
   693  			AddRow(testPhone1, testAge1).
   694  			AddRow(testPhone2, testAge2),
   695  		)
   696  
   697  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   698  
   699  	var composed []ComposedIgnoredStruct
   700  	qes.NoError(e.ScanStructsContext(ctx, &composed))
   701  	qes.Equal([]ComposedIgnoredStruct{
   702  		{StructWithTags: StructWithTags{}, PhoneNumber: testPhone1, Age: testAge1},
   703  		{StructWithTags: StructWithTags{}, PhoneNumber: testPhone2, Age: testAge2},
   704  	}, composed)
   705  }
   706  
   707  func (qes *queryExecutorSuite) TestScanStructsContext_pointersWithEmbeddedStruct() {
   708  	type StructWithTags struct {
   709  		Address string `db:"address"`
   710  		Name    string `db:"name"`
   711  	}
   712  	type ComposedStruct struct {
   713  		StructWithTags
   714  		PhoneNumber string `db:"phone_number"`
   715  		Age         int64  `db:"age"`
   716  	}
   717  	ctx := context.Background()
   718  	db, mock, err := sqlmock.New()
   719  	qes.NoError(err)
   720  
   721  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   722  		WithArgs().
   723  		WillReturnRows(sqlmock.NewRows([]string{"address", "name", "phone_number", "age"}).
   724  			AddRow(testAddr1, testName1, testPhone1, testAge1).
   725  			AddRow(testAddr2, testName2, testPhone2, testAge2),
   726  		)
   727  
   728  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   729  
   730  	var composed []*ComposedStruct
   731  	qes.NoError(e.ScanStructsContext(ctx, &composed))
   732  	qes.Equal([]*ComposedStruct{
   733  		{StructWithTags: StructWithTags{Address: testAddr1, Name: testName1}, PhoneNumber: testPhone1, Age: testAge1},
   734  		{StructWithTags: StructWithTags{Address: testAddr2, Name: testName2}, PhoneNumber: testPhone2, Age: testAge2},
   735  	}, composed)
   736  }
   737  
   738  func (qes *queryExecutorSuite) TestScanStructsContext_withEmbeddedStructPointer() {
   739  	type StructWithTags struct {
   740  		Address string `db:"address"`
   741  		Name    string `db:"name"`
   742  	}
   743  
   744  	type ComposedWithPointerStruct struct {
   745  		*StructWithTags
   746  		PhoneNumber string `db:"phone_number"`
   747  		Age         int64  `db:"age"`
   748  	}
   749  
   750  	ctx := context.Background()
   751  	db, mock, err := sqlmock.New()
   752  	qes.NoError(err)
   753  
   754  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   755  		WithArgs().
   756  		WillReturnRows(sqlmock.NewRows([]string{"address", "name", "phone_number", "age"}).
   757  			AddRow(testAddr1, testName1, testPhone1, testAge1).
   758  			AddRow(testAddr2, testName2, testPhone2, testAge2),
   759  		)
   760  
   761  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   762  
   763  	var composed []ComposedWithPointerStruct
   764  	qes.NoError(e.ScanStructsContext(ctx, &composed))
   765  	qes.Equal([]ComposedWithPointerStruct{
   766  		{StructWithTags: &StructWithTags{Address: testAddr1, Name: testName1}, PhoneNumber: testPhone1, Age: testAge1},
   767  		{StructWithTags: &StructWithTags{Address: testAddr2, Name: testName2}, PhoneNumber: testPhone2, Age: testAge2},
   768  	}, composed)
   769  }
   770  
   771  func (qes *queryExecutorSuite) TestScanStructsContext_pointersWithEmbeddedStructPointer() {
   772  	type StructWithTags struct {
   773  		Address string `db:"address"`
   774  		Name    string `db:"name"`
   775  	}
   776  
   777  	type ComposedWithPointerStruct struct {
   778  		*StructWithTags
   779  		PhoneNumber string `db:"phone_number"`
   780  		Age         int64  `db:"age"`
   781  	}
   782  
   783  	ctx := context.Background()
   784  	db, mock, err := sqlmock.New()
   785  	qes.NoError(err)
   786  
   787  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   788  		WithArgs().
   789  		WillReturnRows(sqlmock.NewRows([]string{"address", "name", "phone_number", "age"}).
   790  			AddRow(testAddr1, testName1, testPhone1, testAge1).
   791  			AddRow(testAddr2, testName2, testPhone2, testAge2),
   792  		)
   793  
   794  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   795  
   796  	var composed []*ComposedWithPointerStruct
   797  	qes.NoError(e.ScanStructsContext(ctx, &composed))
   798  	qes.Equal([]*ComposedWithPointerStruct{
   799  		{StructWithTags: &StructWithTags{Address: testAddr1, Name: testName1}, PhoneNumber: testPhone1, Age: testAge1},
   800  		{StructWithTags: &StructWithTags{Address: testAddr2, Name: testName2}, PhoneNumber: testPhone2, Age: testAge2},
   801  	}, composed)
   802  }
   803  
   804  func (qes *queryExecutorSuite) TestScanStructsContext_badValue() {
   805  	type StructWithTags struct {
   806  		Address string `db:"address"`
   807  		Name    string `db:"name"`
   808  	}
   809  
   810  	tests := []struct {
   811  		name  string
   812  		items interface{}
   813  	}{
   814  		{
   815  			name:  "non-pointer items",
   816  			items: []StructWithTags{},
   817  		},
   818  		{
   819  			name:  "non-slice items",
   820  			items: &StructWithTags{},
   821  		},
   822  	}
   823  	for i := range tests {
   824  		test := tests[i]
   825  		qes.Run(test.name, func() {
   826  			db, mock, err := sqlmock.New()
   827  			qes.NoError(err)
   828  			mock.ExpectQuery(`SELECT \* FROM "items"`).
   829  				WithArgs().
   830  				WillReturnRows(sqlmock.NewRows([]string{"address", "name"}).
   831  					AddRow(testAddr1, testName1).AddRow(testAddr2, testName2),
   832  				)
   833  			e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   834  			qes.Equal(errUnsupportedScanStructsType, e.ScanStructsContext(context.Background(), test.items))
   835  		})
   836  	}
   837  }
   838  
   839  func (qes *queryExecutorSuite) TestScanStructsContext_queryError() {
   840  	type StructWithTags struct {
   841  		Address string `db:"address"`
   842  		Name    string `db:"name"`
   843  	}
   844  
   845  	ctx := context.Background()
   846  	db, mock, err := sqlmock.New()
   847  	qes.NoError(err)
   848  
   849  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   850  		WillReturnError(fmt.Errorf("queryExecutor error"))
   851  
   852  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   853  
   854  	var items []StructWithTags
   855  	qes.EqualError(e.ScanStructsContext(ctx, &items), "queryExecutor error")
   856  }
   857  
   858  func (qes *queryExecutorSuite) TestScanStruct() {
   859  	type StructWithNoTags struct {
   860  		Address string
   861  		Name    string
   862  	}
   863  
   864  	type StructWithTags struct {
   865  		Address string `db:"address"`
   866  		Name    string `db:"name"`
   867  	}
   868  
   869  	type ComposedStruct struct {
   870  		StructWithTags
   871  		PhoneNumber string `db:"phone_number"`
   872  		Age         int64  `db:"age"`
   873  	}
   874  	type ComposedWithPointerStruct struct {
   875  		*StructWithTags
   876  		PhoneNumber string `db:"phone_number"`
   877  		Age         int64  `db:"age"`
   878  	}
   879  
   880  	db, mock, err := sqlmock.New()
   881  	qes.NoError(err)
   882  
   883  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   884  		WillReturnError(fmt.Errorf("queryExecutor error"))
   885  
   886  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   887  		WithArgs().
   888  		WillReturnRows(sqlmock.NewRows([]string{"address", "name"}).
   889  			AddRow(nil, nil),
   890  		)
   891  
   892  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   893  		WithArgs().
   894  		WillReturnRows(sqlmock.NewRows([]string{"address", "name"}))
   895  
   896  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   897  		WithArgs().
   898  		WillReturnRows(sqlmock.NewRows([]string{"address", "name"}).
   899  			AddRow(testAddr1, testName1),
   900  		)
   901  
   902  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   903  		WithArgs().
   904  		WillReturnRows(sqlmock.NewRows([]string{"address", "name", "phone_number", "age"}).
   905  			AddRow(testAddr1, testName1, testPhone1, testAge1),
   906  		)
   907  
   908  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   909  		WithArgs().
   910  		WillReturnRows(sqlmock.NewRows([]string{"address", "name", "phone_number", "age"}).
   911  			AddRow(testAddr1, testName1, testPhone1, testAge1),
   912  		)
   913  
   914  	mock.ExpectQuery(`SELECT \* FROM "items"`).
   915  		WithArgs().
   916  		WillReturnRows(sqlmock.NewRows([]string{"address", "name"}).AddRow(testAddr1, testName1))
   917  
   918  	e := newQueryExecutor(db, nil, `SELECT * FROM "items"`)
   919  
   920  	var slicePtr []StructWithTags
   921  	var item StructWithTags
   922  	found, err := e.ScanStruct(item)
   923  	qes.Equal(errUnsupportedScanStructType, err)
   924  	qes.False(found)
   925  	found, err = e.ScanStruct(&slicePtr)
   926  	qes.Equal(errUnsupportedScanStructType, err)
   927  	qes.False(found)
   928  	found, err = e.ScanStruct(&item)
   929  	qes.EqualError(err, "queryExecutor error")
   930  	qes.False(found)
   931  
   932  	found, err = e.ScanStruct(&item)
   933  	qes.Error(err)
   934  	qes.False(found)
   935  
   936  	found, err = e.ScanStruct(&item)
   937  	qes.NoError(err)
   938  	qes.False(found)
   939  
   940  	found, err = e.ScanStruct(&item)
   941  	qes.NoError(err)
   942  	qes.True(found)
   943  	qes.Equal(StructWithTags{
   944  		Address: testAddr1,
   945  		Name:    testName1,
   946  	}, item)
   947  
   948  	var composed ComposedStruct
   949  	found, err = e.ScanStruct(&composed)
   950  	qes.NoError(err)
   951  	qes.True(found)
   952  	qes.Equal(ComposedStruct{
   953  		StructWithTags: StructWithTags{Address: testAddr1, Name: testName1},
   954  		PhoneNumber:    testPhone1,
   955  		Age:            testAge1,
   956  	}, composed)
   957  
   958  	var embeddedPtr ComposedWithPointerStruct
   959  	found, err = e.ScanStruct(&embeddedPtr)
   960  	qes.NoError(err)
   961  	qes.True(found)
   962  	qes.Equal(ComposedWithPointerStruct{
   963  		StructWithTags: &StructWithTags{
   964  			Address: testAddr1,
   965  			Name:    testName1,
   966  		},
   967  		PhoneNumber: testPhone1,
   968  		Age:         testAge1,
   969  	}, embeddedPtr)
   970  
   971  	var noTag StructWithNoTags
   972  	found, err = e.ScanStruct(&noTag)
   973  	qes.NoError(err)
   974  	qes.True(found)
   975  	qes.Equal(StructWithNoTags{
   976  		Address: testAddr1,
   977  		Name:    testName1,
   978  	}, noTag)
   979  }
   980  
   981  func (qes *queryExecutorSuite) TestScanStruct_taggedStructs() {
   982  	type StructWithNoTags struct {
   983  		Address string
   984  		Name    string
   985  	}
   986  
   987  	type StructWithTags struct {
   988  		Address string `db:"address"`
   989  		Name    string `db:"name"`
   990  	}
   991  
   992  	type ComposedStruct struct {
   993  		StructWithTags
   994  		PhoneNumber string `db:"phone_number"`
   995  		Age         int64  `db:"age"`
   996  	}
   997  	type ComposedWithPointerStruct struct {
   998  		*StructWithTags
   999  		PhoneNumber string `db:"phone_number"`
  1000  		Age         int64  `db:"age"`
  1001  	}
  1002  
  1003  	type StructWithTaggedStructs struct {
  1004  		NoTags          StructWithNoTags          `db:"notags"`
  1005  		Tags            StructWithTags            `db:"tags"`
  1006  		Composed        ComposedStruct            `db:"composedstruct"`
  1007  		ComposedPointer ComposedWithPointerStruct `db:"composedptrstruct"`
  1008  	}
  1009  
  1010  	db, mock, err := sqlmock.New()
  1011  	qes.NoError(err)
  1012  
  1013  	cols := []string{
  1014  		"notags.address", "notags.name",
  1015  		"tags.address", "tags.name",
  1016  		"composedstruct.address", "composedstruct.name", "composedstruct.phone_number", "composedstruct.age",
  1017  		"composedptrstruct.address", "composedptrstruct.name", "composedptrstruct.phone_number", "composedptrstruct.age",
  1018  	}
  1019  
  1020  	q := `SELECT` + strings.Join(cols, ", ") + ` FROM "items"`
  1021  
  1022  	mock.ExpectQuery(q).
  1023  		WithArgs().
  1024  		WillReturnRows(sqlmock.NewRows(cols).AddRow(
  1025  			testAddr1, testName1,
  1026  			testAddr2, testName2,
  1027  			testAddr1, testName1, testPhone1, testAge1,
  1028  			testAddr2, testName2, testPhone2, testAge2,
  1029  		))
  1030  
  1031  	e := newQueryExecutor(db, nil, q)
  1032  
  1033  	var item StructWithTaggedStructs
  1034  	found, err := e.ScanStruct(&item)
  1035  	qes.NoError(err)
  1036  	qes.True(found)
  1037  	qes.Equal(StructWithTaggedStructs{
  1038  		NoTags: StructWithNoTags{Address: testAddr1, Name: testName1},
  1039  		Tags:   StructWithTags{Address: testAddr2, Name: testName2},
  1040  		Composed: ComposedStruct{
  1041  			StructWithTags: StructWithTags{Address: testAddr1, Name: testName1},
  1042  			PhoneNumber:    testPhone1,
  1043  			Age:            testAge1,
  1044  		},
  1045  		ComposedPointer: ComposedWithPointerStruct{
  1046  			StructWithTags: &StructWithTags{Address: testAddr2, Name: testName2},
  1047  			PhoneNumber:    testPhone2,
  1048  			Age:            testAge2,
  1049  		},
  1050  	}, item)
  1051  }
  1052  
  1053  func (qes *queryExecutorSuite) TestScanVals() {
  1054  	db, mock, err := sqlmock.New()
  1055  	qes.NoError(err)
  1056  
  1057  	var id1, id2 int64 = 1, 2
  1058  
  1059  	mock.ExpectQuery(`SELECT "id" FROM "items"`).
  1060  		WillReturnError(fmt.Errorf("queryExecutor error"))
  1061  
  1062  	mock.ExpectQuery(`SELECT "id" FROM "items"`).
  1063  		WithArgs().
  1064  		WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(id1).RowError(0, fmt.Errorf("row error")))
  1065  
  1066  	mock.ExpectQuery(`SELECT "id" FROM "items"`).
  1067  		WithArgs().
  1068  		WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(id1).AddRow("a"))
  1069  
  1070  	mock.ExpectQuery(`SELECT "id" FROM "items"`).
  1071  		WithArgs().
  1072  		WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(id1).AddRow(id2))
  1073  
  1074  	mock.ExpectQuery(`SELECT "id" FROM "items"`).
  1075  		WithArgs().
  1076  		WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(id1).AddRow(id2))
  1077  
  1078  	e := newQueryExecutor(db, nil, `SELECT "id" FROM "items"`)
  1079  
  1080  	var ids []int64
  1081  	qes.EqualError(e.ScanVals(&ids), "queryExecutor error")
  1082  	qes.EqualError(e.ScanVals(&ids), "row error")
  1083  	qes.Error(e.ScanVals(&ids))
  1084  
  1085  	ids = ids[0:0]
  1086  	qes.NoError(e.ScanVals(&ids))
  1087  	qes.Equal(ids, []int64{id1, id2})
  1088  
  1089  	var pointers []*int64
  1090  	qes.NoError(e.ScanVals(&pointers))
  1091  	qes.Len(pointers, 2)
  1092  	qes.Equal(&id1, pointers[0])
  1093  	qes.Equal(&id2, pointers[1])
  1094  }
  1095  
  1096  func (qes *queryExecutorSuite) TestScanValsError() {
  1097  	var id int64
  1098  
  1099  	tests := []struct {
  1100  		name  string
  1101  		items interface{}
  1102  	}{
  1103  		{
  1104  			name:  "non-pointer items",
  1105  			items: []int64{},
  1106  		},
  1107  		{
  1108  			name:  "non-slice items",
  1109  			items: &id,
  1110  		},
  1111  	}
  1112  	for i := range tests {
  1113  		test := tests[i]
  1114  		qes.Run(test.name, func() {
  1115  			db, mock, err := sqlmock.New()
  1116  			qes.NoError(err)
  1117  			mock.ExpectQuery(`SELECT "id" FROM "items"`).
  1118  				WithArgs().
  1119  				WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1).AddRow(2))
  1120  
  1121  			e := newQueryExecutor(db, nil, `SELECT "id" FROM "items"`)
  1122  			qes.Equal(errUnsupportedScanValsType, e.ScanVals(test.items))
  1123  		})
  1124  	}
  1125  }
  1126  
  1127  func (qes *queryExecutorSuite) TestScanVal() {
  1128  	db, mock, err := sqlmock.New()
  1129  	qes.NoError(err)
  1130  
  1131  	id1 := int64(1)
  1132  	mock.ExpectQuery(`SELECT "id" FROM "items"`).
  1133  		WillReturnError(fmt.Errorf("queryExecutor error"))
  1134  
  1135  	mock.ExpectQuery(`SELECT "id" FROM "items"`).
  1136  		WithArgs().
  1137  		WillReturnRows(sqlmock.NewRows([]string{"id"}).RowError(0, fmt.Errorf("row error")).AddRow(id1))
  1138  
  1139  	mock.ExpectQuery(`SELECT "id" FROM "items"`).
  1140  		WithArgs().
  1141  		WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow("c"))
  1142  
  1143  	mock.ExpectQuery(`SELECT "id" FROM "items"`).
  1144  		WithArgs().
  1145  		WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(id1))
  1146  
  1147  	e := newQueryExecutor(db, nil, `SELECT "id" FROM "items"`)
  1148  
  1149  	var id int64
  1150  	var ids []int64
  1151  	found, err := e.ScanVal(id)
  1152  	qes.Equal(errScanValPointer, err)
  1153  	qes.False(found)
  1154  	found, err = e.ScanVal(&ids)
  1155  	qes.Equal(errScanValNonSlice, err)
  1156  	qes.False(found)
  1157  	found, err = e.ScanVal(&id)
  1158  	qes.EqualError(err, "queryExecutor error")
  1159  	qes.False(found)
  1160  
  1161  	found, err = e.ScanVal(&id)
  1162  	qes.EqualError(err, "row error")
  1163  	qes.False(found)
  1164  
  1165  	found, err = e.ScanVal(&id)
  1166  	qes.Error(err)
  1167  	qes.False(found)
  1168  
  1169  	var ptrID *int64
  1170  	found, err = e.ScanVal(&ptrID)
  1171  	qes.NoError(err)
  1172  	qes.True(found)
  1173  	qes.Equal(&id1, ptrID)
  1174  }
  1175  
  1176  func (qes *queryExecutorSuite) TestScanVal_withByteSlice() {
  1177  	db, mock, err := sqlmock.New()
  1178  	qes.NoError(err)
  1179  
  1180  	mock.ExpectQuery(`SELECT "name" FROM "items"`).
  1181  		WithArgs().
  1182  		WillReturnRows(sqlmock.NewRows([]string{"name"}).AddRow(testByteSliceContent))
  1183  
  1184  	e := newQueryExecutor(db, nil, `SELECT "name" FROM "items"`)
  1185  
  1186  	var bytes []byte
  1187  	found, err := e.ScanVal(bytes)
  1188  	qes.Equal(errScanValPointer, err)
  1189  	qes.False(found)
  1190  
  1191  	found, err = e.ScanVal(&bytes)
  1192  	qes.NoError(err)
  1193  	qes.True(found)
  1194  	qes.Equal([]byte(testByteSliceContent), bytes)
  1195  }
  1196  
  1197  func (qes *queryExecutorSuite) TestScanVal_withRawBytes() {
  1198  	db, mock, err := sqlmock.New()
  1199  	qes.NoError(err)
  1200  
  1201  	mock.ExpectQuery(`SELECT "name" FROM "items"`).
  1202  		WithArgs().
  1203  		WillReturnRows(sqlmock.NewRows([]string{"name"}).AddRow(testByteSliceContent))
  1204  
  1205  	e := newQueryExecutor(db, nil, `SELECT "name" FROM "items"`)
  1206  
  1207  	var bytes sql.RawBytes
  1208  	found, err := e.ScanVal(bytes)
  1209  	qes.Equal(errScanValPointer, err)
  1210  	qes.False(found)
  1211  
  1212  	found, err = e.ScanVal(&bytes)
  1213  	qes.NoError(err)
  1214  	qes.True(found)
  1215  	qes.Equal(sql.RawBytes(testByteSliceContent), bytes)
  1216  }
  1217  
  1218  type JSONBoolArray []bool
  1219  
  1220  func (b *JSONBoolArray) Scan(src interface{}) error {
  1221  	return json.Unmarshal(src.([]byte), b)
  1222  }
  1223  
  1224  func (qes *queryExecutorSuite) TestScanVal_withValuerSlice() {
  1225  	db, mock, err := sqlmock.New()
  1226  	qes.NoError(err)
  1227  
  1228  	mock.ExpectQuery(`SELECT "bools" FROM "items"`).
  1229  		WithArgs().
  1230  		WillReturnRows(sqlmock.NewRows([]string{"bools"}).FromCSVString(`"[true, false, true]"`))
  1231  
  1232  	e := newQueryExecutor(db, nil, `SELECT "bools" FROM "items"`)
  1233  
  1234  	var bools JSONBoolArray
  1235  	found, err := e.ScanVal(bools)
  1236  	qes.Equal(errScanValPointer, err)
  1237  	qes.False(found)
  1238  
  1239  	found, err = e.ScanVal(&bools)
  1240  	qes.NoError(err)
  1241  	qes.True(found)
  1242  	qes.Equal(JSONBoolArray{true, false, true}, bools)
  1243  }
  1244  
  1245  func TestQueryExecutorSuite(t *testing.T) {
  1246  	suite.Run(t, new(queryExecutorSuite))
  1247  }
  1248  

View as plain text