sqlc icon indicating copy to clipboard operation
sqlc copied to clipboard

Support creating new objects for sql.Scanner

Open Cyberax opened this issue 1 year ago • 2 comments
trafficstars

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

Cyberax avatar Aug 11 '24 16:08 Cyberax

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.

kyleconroy avatar Aug 12 '24 01:08 kyleconroy

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.

Cyberax avatar Aug 14 '24 03:08 Cyberax