sqlc-dev / sqlc

Generate type-safe code from SQL
https://sqlc.dev
MIT License
13.41k stars 803 forks source link

Rename struct property name when using sqlc.embed in multiple joins from same table #3177

Open lcnlvrz opened 9 months ago

lcnlvrz commented 9 months ago

Version

1.25.0

What happened?

I just need to perform a query that joins multiple rows from same table and i expect sqlc to take alias from query when build final go structs

In current version when you join multiple times from same table, the final struct looks something like:

struct QueryOutput {
TableRow1  Table
TableRow2 Table
}

Relevant log output

No response

Database schema

CREATE TABLE tracks(
    id SERIAL PRIMARY KEY,
    driver_id INTEGER NOT NULL REFERENCES persons(id),
    recipient_id INTEGER NOT NULL REFERENCES persons(id)
);

CREATE TABLE persons(
    id SERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255),
    phone VARCHAR(255) NOT NULL,
    created_at TIMESTAMP NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMP NOT NULL DEFAULT NOW()
);

SQL queries

SELECT * FROM tracks
LEFT JOIN persons as driver ON tracks.driver_id = driver.id
LEFT JOIN persons as recipient ON tracks.recipient_id = recipient.id
WHERE id = $1 LIMIT 1;

Configuration

version: '2'
sql:
  - engine: 'postgresql'
    queries: 'query.sql'
    schema: 'migrations'
    gen:
      go:
        package: 'db'
        out: 'db'
        sql_package: 'pgx/v5'
        emit_json_tags: true
        emit_pointers_for_null_types: true
        emit_all_enum_values: true
        overrides:
          - go_struct_tag: 'json:"-"'
            column: '*.password'

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

lcnlvrz commented 9 months ago

By the moment the workaround that works for me is to create views and then use sqlc.embed

schema.sql

CREATE VIEW drivers AS (
    SELECT * FROM persons WHERE type = 'driver'
);

CREATE VIEW recipients AS (
    SELECT * FROM persons WHERE type = 'recipient'
);

query.sql

SELECT sqlc.embed(track), sqlc.embed(driver), sqlc.embed(recipient)
FROM tracks track
JOIN drivers driver ON track.driver_id = driver.id
JOIN recipients recipient ON track.recipient_id = recipient.id
WHERE track.id = $1 LIMIT 1;
ErikKalkoken commented 7 months ago

The workaround is great, however it also leads to new types in the response struct, which makes it less useful in some cases.

e.g. the example would create something like this:

type GetTrackRow {
    Track   Track
    Driver   Driver
    Recipient Recipient
}