sqlc
sqlc copied to clipboard
Support creating new objects for sql.Scanner
What do you want to change?
sqlc has support for custom data types, including pointer types. I was hoping to use it to support custom deserialization for a type that supports the sql.Scanner interface. I tried this:
overrides:
go:
overrides:
- column: customer.val
go_type:
import: "github.com/mycompany/app/proto/golang/data"
type: Customer
pointer: true
And the generated code looks like this:
func (q *Queries) FindCustomerById(ctx context.Context, id string) (*data.Customer, error) {
row := q.db.QueryRow(ctx, findCustomerById, id)
var val *data.Customer
err := row.Scan(&val)
return val, err
}
This predictably fails at runtime, because the database driver does not know what to do with a double pointer. It would be nice to add a feature to support creation of new objects:
func (q *Queries) FindCustomerById(ctx context.Context, id string) (*data.Customer, error) {
row := q.db.QueryRow(ctx, findCustomerById, id)
var val *data.Customer = new(data.Customer)
err := row.Scan(&val)
return val, err
}
I can use values without pointer: true, but it's a pain because Protobuf objects have embedded mutexes. And all of the Protobuf infrastructure is designed to deal with pointers.
If there is a consensus that it's a feature worth implementing, I'll provide a PR with it.
What database engines need to be changed?
PostgreSQL, MySQL, SQLite
What programming language backends need to be changed?
Go
The with: pointer was originally designed for mapping NULL values to nil. This feels like a power-user feature, so maybe we add another field like pointer_new: true? We probably need to workshop the name a bit.
Of course. Simply changing the behavior will break the backwards compatibility, so I was planning to add a new field. pointer_new sounds fine to me, or maybe construct_object.
I'll send a PR soon.