Skip to content

Embedded composite types using a pointer #92

Open
@leg100

Description

@leg100

Hello,

I've been using pggen for a long time in my project, OTF and it's worked supremely well. Thank you! I particularly like how you can embed composite types in results:

CREATE TABLE IF NOT EXISTS author (
  author_id  serial PRIMARY KEY,
  first_name text NOT NULL,
  last_name  text NOT NULL,
  suffix text NULL
);

CREATE TABLE IF NOT EXISTS nobel_prize_for_literature (
  year int PRIMARY KEY,
  author_id int REFERENCES author
);
-- name: FindAuthors :many
SELECT a.*, (n.*)::"nobel_prize_for_literature" AS nobel_prize_for_literature
FROM author a
LEFT JOIN nobel_prize_for_literature n USING (author_id);

from which pggen generates:

type FindAuthorsRow struct {
	AuthorID                *int32                  `json:"author_id"`
	FirstName               *string                 `json:"first_name"`
	LastName                *string                 `json:"last_name"`
	Suffix                  *string                 `json:"suffix"`
	NobelPrizeForLiterature NobelPrizeForLiterature `json:"nobel_prize_for_literature"`
}
...
// NobelPrizeForLiterature represents the Postgres composite type "nobel_prize_for_literature".
type NobelPrizeForLiterature struct {
	Year     *int32 `json:"year"`
	AuthorID *int32 `json:"author_id"`
}

Which is great. However, as you can see it's using a LEFT JOIN, because an author may not be a nobel laureate. In that case I want the embedded NobelPrizeForLiterature to instead be a pointer, *NobelPrizeForLiterature:

type FindAuthorsRow struct {
	AuthorID                *int32                  `json:"author_id"`
	FirstName               *string                 `json:"first_name"`
	LastName                *string                 `json:"last_name"`
	Suffix                  *string                 `json:"suffix"`
	NobelPrizeForLiterature *NobelPrizeForLiterature `json:"nobel_prize_for_literature"`
}

That would allow me to differentiate whether an author is a nobel laureate or not.

I therefore created a fork a long while back that uses pointers instead: https://github.com/leg100/pggen. I made no attempt to raise a PR with your project at the time (sorry). The fork has remained stale and it looks like the code in question has totally changed upstream, so much so that any attempt to rebase now results in dozens of conflicts. Which is a shame because I would like to get all the updates that have been made since.

Nonetheless, I'm in two minds as to whether this struct pointer approach is worthwhile. I can see how with a struct value, one could check the fields, e.g. Year and AuthorID, and see if they are nil or zero. Which isn't as nice I think.

What do you think? Is there a better approach?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions