sqlc icon indicating copy to clipboard operation
sqlc copied to clipboard

Renaming generated struct from a query that selects from multiple tables

Open jacob-winkler opened this issue 1 year ago • 3 comments

Version

1.26.0

What happened?

I have a query like

-- name: MembersWithExternalId :many
SELECT m.*, mp.external_id
FROM member m
INNER JOIN member_provider mp ON mp.member_id = m.id;

This generates a query and struct like MembersWithExternalIdRow

I want to rename this generated struct to be ExternalMember

I've tried using the config rename to do this in many different forms, but none of the rename configs are working.

overrides:
  go:
    rename:
      members_with_external_id_row: "ExternalMember"
      memberswithexternalidrow: "ExternalMember"
      members_with_external_id: "ExternalMember"
      memberswithexternalid: "ExternalMember"

Relevant log output

No response

Database schema

No response

SQL queries

-- name: MembersWithExternalId :many
SELECT m.*, mp.external_id
FROM member m
INNER JOIN member_provider mp ON mp.member_id = m.id;

Configuration

overrides:
  go:
    rename:
      members_with_external_id_row: "ExternalMember"
      memberswithexternalidrow: "ExternalMember"
      members_with_external_id: "ExternalMember"
      memberswithexternalid: "ExternalMember"

Playground URL

No response

What operating system are you using?

Linux

What database engines are you using?

PostgreSQL

What type of code are you generating?

Go

jacob-winkler avatar Jul 24 '24 15:07 jacob-winkler

Is this a user error on my part, or is this just not working? Has anyone successfully managed to do what I'm describing above?

jacob-winkler avatar Oct 02 '24 18:10 jacob-winkler

It would be nice if we could re-use the same "custom" struct across different queries.

Continuing with the example above

-- name: MembersWithExternalId :many
SELECT m.*, mp.external_id
FROM member m
INNER JOIN member_provider mp ON mp.member_id = m.id;

-- name MembersWithExternalIdByLastName :many
SELECT m.*, mp.external_id
FROM member m
INNER JOIN member_provider mp ON mp.member_id = m.id
WHERE m.last_name = @last_name

Being able to configure sqlc so that both of these to return a collection of ExternalMember based on the composition of the columns that they return would be :pinched_fingers:

As an example, if I have a function that I want to operate on an ExternalMember with, if this same struct can't be used as the output for multiple different queries, then I would have to account for handling both a MembersWithExternalIdRow and MembersWithExternalIdByLastNameRow to perform the same function.

Something like this is not possible

func memberToMemberResponse(member ExternalMember) MemberResponse {
	return MemberResponse{
		Name:       member.Name,
		SpecialID: member.ExternalID,
	}
}

If someone could point me to the right files to start digging around in, I would consider making a PR for this myself!

jacob-winkler avatar Oct 02 '24 18:10 jacob-winkler

OK I have a stop gap solution here. In short: use a database view!

CREATE VIEW external_member AS
SELECT m.*, mp.external_id
FROM member m
INNER JOIN member_provider mp ON mp.member_id = m.id;

And then you can create your queries as follows

-- name: MembersWithExternalId :many
SELECT m.*
FROM external_member

-- name MembersWithExternalIdByLastName :many
SELECT m.*
FROM external_member
WHERE m.last_name = @last_name

And this results in

type Querier interface {
    ...
	MembersWithExternalId(ctx context.Context) ([]ExternalMember, error)
	MembersWithExternalIdByLastName(ctx context.Context, lastName string) ([]ExternalMember, error)
    ...
}

jacob-winkler avatar Oct 02 '24 21:10 jacob-winkler