sqlc icon indicating copy to clipboard operation
sqlc copied to clipboard

sqlc ignores model and instead creates inline struct suffixed with Row

Open AndrewRayCode opened this issue 3 years ago • 3 comments

Version

1.13.0

What happened?

sqlc generate creates a model in models.go like

// Code generated by sqlc. DO NOT EDIT.
// versions:
//   sqlc v1.13.0

type QuestionnaireResponseItem struct {
...
}

But given a query like


/* name: GetQuestionnaireResponseItemsByQuestionnaireResponseID :many */
SELECT
...
FROM
    questionnaire_response_item
WHERE
    questionnaire_response_id = ?
ORDER BY
    id ASC;

It ignores the model in the model file, and generates a query function that looks like:

type GetQuestionnaireResponseItemsByQuestionnaireResponseIDRow struct {
...
}

func (q *Queries) GetQuestionnaireResponseItemsByQuestionnaireResponseID(ctx context.Context, questionnaireResponseID string) ([]GetQuestionnaireResponseItemsByQuestionnaireResponseIDRow, error) {

This return type should be QuestionnaireResponseItem from the models, instead it's GetQuestionnaireResponseItemsByQuestionnaireResponseIDRow generated as an inline struct.

The bodies of the struct in the models file and the struct in the query file are identical.

What would cause this behavior?

Relevant log output

No response

Database schema

No response

SQL queries

No response

Configuration

version: "1"
packages:
  - name: "database"
    path: "."
    queries: "./queries.sql"
    schema: "./migrations/"
    engine: "mysql"
    emit_json_tags: true
    emit_prepared_queries: true
    emit_interface: true
    emit_exact_table_names: false
    emit_empty_slices: false

Playground URL

No response

What operating system are you using?

macOS

What database engines are you using?

MySQL

What type of code are you generating?

Go

AndrewRayCode avatar May 27 '22 04:05 AndrewRayCode

Additional context, I'm pointing sqlc to my migrations/ folder, to which I also added a new column to the database in a new migration. I don't know if relevant, but the existing file is 0000001_init_schema.up.sql and the new file is 000002_add_question_item_parent.up.sql the number of zeroes is different, but I don't know if that matters to sqlc

Hmm, I see the note here - i'm using golang-migrate https://docs.sqlc.dev/en/stable/howto/ddl.html#golang-migrate

but I get the same result if I name the second file to the same number of zeroes 0000002_add_question_item_parent.up.sql

AndrewRayCode avatar May 27 '22 04:05 AndrewRayCode

Hmm ok, after some trial and error, the separate struct is generated if the order of the columns in queries.sql.go is different than the order of the fields listed in the model struct definition. If i make the query columns match the order of the struct, then it works.

Again, not sure if relevant, I'm using an AFTER clause in my second migration

ALTER TABLE questionnaire_response_item
ADD COLUMN parent_response_id VARCHAR(255) AFTER questionnaire_item_id;

AndrewRayCode avatar May 27 '22 04:05 AndrewRayCode

Same problems, Is there any progress ? Both queries have the same fields, but two ResultRow struct objects are generated.

  • query.sql
-- name: SelectBriefInfoById  :one
select id, slug, name,  value1, value2 from table1 where id = ? limit 1;

-- name: SelectBriefInfoBySlug :one
select id, slug, name,  value1, value2 from table1 where slug = ? limit 1;
  • query.sql.go
type SelectBriefInfoById struct {
        ... ...
}
type SelectBriefInfoBySlugRow struct {
        ... ...
}

And I have to repackage these two results separately.

lucifer-wsp avatar Aug 13 '22 10:08 lucifer-wsp

@lucifer-wsp I believe the "sqlc-way" of doing this is to select *, when you want the type to be the whole row.

-- name: SelectBriefInfoById  :one
select table1.*  from table1 where id = ? limit 1;

-- name: SelectBriefInfoBySlug :one
select table1.* from table1 where slug = ? limit 1;

You'll see that sqlc actually expands those columns for you when it generates the queries (it does not run a select * at runtime).

I then when done that way, you'll see that sqlc always chooses to use the model, not an inline struct.

skabbes avatar Nov 27 '22 17:11 skabbes