sqlc icon indicating copy to clipboard operation
sqlc copied to clipboard

SQLC generates duplicate field names with numeric suffixes when joining the same table multiple times

Open patriarch11 opened this issue 8 months ago • 1 comments

Version

1.28.0

What happened?

Description: When executing a SQL query that JOINs the same table multiple times with different aliases, SQLC generates Go structs with numbered field suffixes (e.g., Company_2, Company_3) instead of using the specified aliases. This occurs even when using explicit table aliases in the query.

Reproduction Steps:

Create a SQL query with multiple joins to the same table:

-- name: GetProjectDetails :one
SELECT
    p.*,
    sqlc.embed(m) AS manager_company,
    sqlc.embed(c) AS client_company,
    sqlc.embed(v) AS vendor_company
FROM projects p
LEFT JOIN companies m ON p.manager_id = m.id  -- Manager company
LEFT JOIN companies c ON p.client_id = c.id   -- Client company
LEFT JOIN companies v ON p.vendor_id = v.id   -- Vendor company
WHERE p.id = $1;

Run sqlc generate

Actual Behavior: Generated Go struct contains numbered fields:

type GetProjectDetailsRow struct {
    ProjectID   int32         `json:"project_id"`
    // ...
    Company     Company `json:"company"`
    Company_2   Company `json:"company_2"`  // Expected: Manager
    Company_3   Company `json:"company_3"`  // Expected: Client
}

Expected Behavior: Struct fields should respect SQL aliases:

type GetProjectDetailsRow struct {
    ProjectID    int32    `json:"project_id"`
    // ...
    Manager      Company `json:"manager"`
    Client       Company `json:"client"`
    Vendor       Company `json:"vendor"`
}

Relevant log output


Database schema


SQL queries


Configuration


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

patriarch11 avatar Mar 29 '25 22:03 patriarch11

The other approach to this issue is to use sqlc.embed param as the name (same pattern as sqlc.arg).

Example

-- name: GetProjectDetails :one
SELECT
    p.*,
    sqlc.embed(manager),
    sqlc.embed(client),
    sqlc.embed(vendor)
FROM projects p
LEFT JOIN companies manager ON p.manager_id = manager.id  -- Manager company
LEFT JOIN companies client ON p.client_id = client.id   -- Client company
LEFT JOIN companies vendor ON p.vendor_id = vendor.id   -- Vendor company
WHERE p.id = $1;

generates

type GetProjectDetailsRow struct {
    ProjectID    int32    `json:"project_id"`
    // ...
    Manager      Company `json:"manager"`
    Client       Company `json:"client"`
    Vendor       Company `json:"vendor"`
}

krhubert avatar Apr 11 '25 15:04 krhubert