From 86899b53cc9b83cdb34a912e2fc8062f9df62f0f Mon Sep 17 00:00:00 2001 From: Andrew Benton Date: Mon, 16 Oct 2023 21:55:05 -0700 Subject: [PATCH] fix(codegen/go): Prevent filtering of embedded struct fields Resolves https://github.com/sqlc-dev/sqlc/issues/2860 --- internal/codegen/golang/gen.go | 3 ++ .../postgresql/stdlib/go/models.go | 47 +++++++++++++++++++ .../postgresql/stdlib/go/query.sql.go | 15 ++++++ .../postgresql/stdlib/query.sql | 5 +- .../postgresql/stdlib/schema.sql | 10 +++- 5 files changed, 78 insertions(+), 2 deletions(-) diff --git a/internal/codegen/golang/gen.go b/internal/codegen/golang/gen.go index c5f1956e0d..ea3d8384cd 100644 --- a/internal/codegen/golang/gen.go +++ b/internal/codegen/golang/gen.go @@ -345,6 +345,9 @@ func filterUnusedStructs(enums []Enum, structs []Struct, queries []Query) ([]Enu if query.Ret.IsStruct() { for _, field := range query.Ret.Struct.Fields { keepTypes[field.Type] = struct{}{} + for _, embedField := range field.EmbedFields { + keepTypes[embedField.Type] = struct{}{} + } } } } diff --git a/internal/endtoend/testdata/omit_unused_structs/postgresql/stdlib/go/models.go b/internal/endtoend/testdata/omit_unused_structs/postgresql/stdlib/go/models.go index b1624997b9..d918dc44c1 100644 --- a/internal/endtoend/testdata/omit_unused_structs/postgresql/stdlib/go/models.go +++ b/internal/endtoend/testdata/omit_unused_structs/postgresql/stdlib/go/models.go @@ -219,6 +219,48 @@ func (ns NullQueryReturnStructEnumTableEnum) Value() (driver.Value, error) { return string(ns.QueryReturnStructEnumTableEnum), nil } +type QuerySqlcEmbedEnum string + +const ( + QuerySqlcEmbedEnumM QuerySqlcEmbedEnum = "m" + QuerySqlcEmbedEnumN QuerySqlcEmbedEnum = "n" +) + +func (e *QuerySqlcEmbedEnum) Scan(src interface{}) error { + switch s := src.(type) { + case []byte: + *e = QuerySqlcEmbedEnum(s) + case string: + *e = QuerySqlcEmbedEnum(s) + default: + return fmt.Errorf("unsupported scan type for QuerySqlcEmbedEnum: %T", src) + } + return nil +} + +type NullQuerySqlcEmbedEnum struct { + QuerySqlcEmbedEnum QuerySqlcEmbedEnum + Valid bool // Valid is true if QuerySqlcEmbedEnum is not NULL +} + +// Scan implements the Scanner interface. +func (ns *NullQuerySqlcEmbedEnum) Scan(value interface{}) error { + if value == nil { + ns.QuerySqlcEmbedEnum, ns.Valid = "", false + return nil + } + ns.Valid = true + return ns.QuerySqlcEmbedEnum.Scan(value) +} + +// Value implements the driver Valuer interface. +func (ns NullQuerySqlcEmbedEnum) Value() (driver.Value, error) { + if !ns.Valid { + return nil, nil + } + return string(ns.QuerySqlcEmbedEnum), nil +} + type QueryParamEnumTable struct { ID int32 Other QueryParamEnumTableEnum @@ -229,3 +271,8 @@ type QueryReturnFullTable struct { ID int32 Value NullQueryReturnFullTableEnum } + +type QuerySqlcEmbedTable struct { + ID int32 + Value NullQuerySqlcEmbedEnum +} diff --git a/internal/endtoend/testdata/omit_unused_structs/postgresql/stdlib/go/query.sql.go b/internal/endtoend/testdata/omit_unused_structs/postgresql/stdlib/go/query.sql.go index f659102696..91457e09ab 100644 --- a/internal/endtoend/testdata/omit_unused_structs/postgresql/stdlib/go/query.sql.go +++ b/internal/endtoend/testdata/omit_unused_structs/postgresql/stdlib/go/query.sql.go @@ -90,3 +90,18 @@ func (q *Queries) query_return_struct_enum_table(ctx context.Context, id int32) err := row.Scan(&i.Value, &i.Another) return i, err } + +const query_sqlc_embed_table = `-- name: query_sqlc_embed_table :one +SELECT query_sqlc_embed_table.id, query_sqlc_embed_table.value FROM query_sqlc_embed_table WHERE id = $1 +` + +type query_sqlc_embed_tableRow struct { + QuerySqlcEmbedTable QuerySqlcEmbedTable +} + +func (q *Queries) query_sqlc_embed_table(ctx context.Context, id int32) (query_sqlc_embed_tableRow, error) { + row := q.db.QueryRowContext(ctx, query_sqlc_embed_table, id) + var i query_sqlc_embed_tableRow + err := row.Scan(&i.QuerySqlcEmbedTable.ID, &i.QuerySqlcEmbedTable.Value) + return i, err +} diff --git a/internal/endtoend/testdata/omit_unused_structs/postgresql/stdlib/query.sql b/internal/endtoend/testdata/omit_unused_structs/postgresql/stdlib/query.sql index 1420d869d3..599a227482 100644 --- a/internal/endtoend/testdata/omit_unused_structs/postgresql/stdlib/query.sql +++ b/internal/endtoend/testdata/omit_unused_structs/postgresql/stdlib/query.sql @@ -11,4 +11,7 @@ SELECT id FROM query_param_struct_enum_table WHERE id = $1 AND value = $2; SELECT value FROM query_return_enum_table WHERE id = $1; -- name: query_return_struct_enum_table :one -SELECT value, another FROM query_return_struct_enum_table WHERE id = $1; \ No newline at end of file +SELECT value, another FROM query_return_struct_enum_table WHERE id = $1; + +-- name: query_sqlc_embed_table :one +SELECT sqlc.embed(query_sqlc_embed_table) FROM query_sqlc_embed_table WHERE id = $1; diff --git a/internal/endtoend/testdata/omit_unused_structs/postgresql/stdlib/schema.sql b/internal/endtoend/testdata/omit_unused_structs/postgresql/stdlib/schema.sql index cc2ae14b28..486119c334 100644 --- a/internal/endtoend/testdata/omit_unused_structs/postgresql/stdlib/schema.sql +++ b/internal/endtoend/testdata/omit_unused_structs/postgresql/stdlib/schema.sql @@ -50,4 +50,12 @@ CREATE TABLE query_return_struct_enum_table ( id INTEGER PRIMARY KEY, value query_return_struct_enum_table_enum, another INTEGER -); \ No newline at end of file +); + +CREATE TYPE query_sqlc_embed_enum AS ENUM ( + 'm', 'n' +); +CREATE TABLE query_sqlc_embed_table ( + id INTEGER PRIMARY KEY, + value query_sqlc_embed_enum +)