Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[+] convert types in Scan if possible #232

Merged
merged 2 commits into from
Mar 3, 2025

Conversation

ertaquo
Copy link
Contributor

@ertaquo ertaquo commented Mar 3, 2025

rowSets.Scan() checks if value type assignable to destination element type or destination type implements sql.Scanner interface. It doesn't check if value type can be converted to destination element type.

Using primitive type alias will result in error:

rs := NewRows([]string{"id", "active", "created", "status"}).        
        AddRow(1, true, NullTime{time.Now(), true}, NullInt{5, true}).        
        AddRow(2, false, NullTime{Valid: false}, NullInt{Valid: false})        
 
mock.ExpectQuery("SELECT (.+) FROM sales").WillReturnRows(rs)        
 
rows, err := mock.Query(context.Background(), "SELECT * FROM sales")        
if err != nil {        
        t.Fatalf("error '%s' was not expected while retrieving mock rows", err)        
}        
defer rows.Close()        
 
type boolAlias bool
 
// NullTime and NullInt are used from stubs_test.go        
var (        
        id      int        
        active  boolAlias        
        created NullTime        
        status  NullInt        
)        
 
if !rows.Next() {        
        t.Fatal("it must have had row in rows, but got empty result set instead")        
}        
 
err = rows.Scan(&id, &active, &created, &status)        
if err != nil {        
        t.Errorf("error '%s' was not expected while trying to scan row", err)        
}
pgxmock_test.go:514: error 'Destination kind 'bool' not supported for value kind 'bool' of column 'active'' was not expected while trying to scan row
pgxmock_test.go:522: expected 'active' to be 'true', but got 'false' instead
pgxmock_test.go:526: expected 'created' to be valid, but it {Time:0001-01-01 00:00:00 +0000 UTC Valid:false} is not
pgxmock_test.go:530: expected 'status' to be valid, but it {Integer:0 Valid:false} is not
pgxmock_test.go:534: expected 'status' to be '5', but got '0'
pgxmock_test.go:544: error 'Destination kind 'bool' not supported for value kind 'bool' of column 'active'' was not expected while trying to scan row

Of course, there won't be any problems if specify the type at AddRow() call, but it doesn't looks elegant:

type boolAlias bool

rs := NewRows([]string{"id", "active", "created", "status"}).        
        AddRow(1, boolAlias(true), NullTime{time.Now(), true}, NullInt{5, true}).        
        AddRow(2, boolAlias(false), NullTime{Valid: false}, NullInt{Valid: false})        

So I offer to use type conversion if possible.

The type conversion is being used within standard database/sql package, so I think it's compliant to use it in pgxmock library too:

	if dv.Kind() == sv.Kind() && sv.Type().ConvertibleTo(dv.Type()) {
		dv.Set(sv.Convert(dv.Type()))
		return nil
	}

@coveralls
Copy link

coveralls commented Mar 3, 2025

Coverage Status

coverage: 93.975% (-0.2%) from 94.179%
when pulling a4e1308 on ertaquo:convert-on-scan
into ca59591 on pashagolub:master.

@pashagolub pashagolub self-assigned this Mar 3, 2025
@pashagolub pashagolub added the enhancement New feature or request label Mar 3, 2025
@pashagolub pashagolub changed the title Convert types in Scan if possible [+] convert types in Scan if possible Mar 3, 2025
@pashagolub pashagolub merged commit fef6b63 into pashagolub:master Mar 3, 2025
3 checks passed
@pashagolub
Copy link
Owner

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants