From ff653a456f88abd315ca518c16bef0210d81b27a Mon Sep 17 00:00:00 2001 From: Daniel Kozlowski Date: Thu, 21 Apr 2022 15:44:46 -0700 Subject: [PATCH 1/8] feat: Split models into dedicated package This change allows models to be split into a different package. The major benefit of this is to allow multiple sqlc querier packages to use the same schema, and models. This allows better code modularization and help larger projects keep implementation details independent across logical code modules --- docs/reference/config.md | 6 + examples/split/postgresql/inventory/db.go | 32 +++ .../split/postgresql/inventory/inventory.sql | 3 + .../postgresql/inventory/inventory.sql.go | 55 ++++ .../split/postgresql/inventory/querier.go | 17 ++ examples/split/postgresql/models/models.go | 131 ++++++++++ examples/split/postgresql/schema.sql | 128 ++++++++++ examples/split/postgresql/warehouse/db.go | 32 +++ .../split/postgresql/warehouse/querier.go | 17 ++ .../split/postgresql/warehouse/warehouse.sql | 3 + .../postgresql/warehouse/warehouse.sql.go | 47 ++++ examples/split/sqlc.json | 31 +++ internal/cmd/shim.go | 2 + internal/codegen/golang/gen.go | 43 +++- internal/codegen/golang/imports.go | 10 + internal/codegen/golang/query.go | 3 + internal/codegen/golang/result.go | 7 +- internal/codegen/golang/struct.go | 1 + .../golang/templates/pgx/batchCode.tmpl | 4 +- .../golang/templates/pgx/queryCode.tmpl | 4 +- .../codegen/golang/templates/template.tmpl | 23 +- internal/codegen/sdk/utils.go | 8 + internal/config/config.go | 2 + internal/config/v_one.go | 4 + internal/plugin/codegen.pb.go | 234 ++++++++++-------- internal/plugin/codegen_vtproto.pb.go | 90 +++++++ internal/python/ast/ast.pb.go | 4 +- protos/plugin/codegen.proto | 2 + 28 files changed, 809 insertions(+), 134 deletions(-) create mode 100644 examples/split/postgresql/inventory/db.go create mode 100644 examples/split/postgresql/inventory/inventory.sql create mode 100644 examples/split/postgresql/inventory/inventory.sql.go create mode 100644 examples/split/postgresql/inventory/querier.go create mode 100644 examples/split/postgresql/models/models.go create mode 100644 examples/split/postgresql/schema.sql create mode 100644 examples/split/postgresql/warehouse/db.go create mode 100644 examples/split/postgresql/warehouse/querier.go create mode 100644 examples/split/postgresql/warehouse/warehouse.sql create mode 100644 examples/split/postgresql/warehouse/warehouse.sql.go create mode 100644 examples/split/sqlc.json diff --git a/docs/reference/config.md b/docs/reference/config.md index e87f999258..e1e7fa6d8d 100644 --- a/docs/reference/config.md +++ b/docs/reference/config.md @@ -26,6 +26,8 @@ packages: output_db_file_name: "db.go" output_models_file_name: "models.go" output_querier_file_name: "querier.go" + models_package: "models" + models_path: "models" ``` Each package document has the following keys: @@ -78,6 +80,10 @@ Each package document has the following keys: - Customize the name of the querier file. Defaults to `querier.go`. - `output_files_suffix`: - If specified the suffix will be added to the name of the generated files. +- `models_package`: + - If specified the models will be generated into the provided package, if an absolutle package name is provided the relative path must be given in `model_path`. +- `models_path`: + - The relative path to output the generated the model files into. ## Type Overrides diff --git a/examples/split/postgresql/inventory/db.go b/examples/split/postgresql/inventory/db.go new file mode 100644 index 0000000000..c09ae2ccf1 --- /dev/null +++ b/examples/split/postgresql/inventory/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.13.0 + +package split + +import ( + "context" + + "github.com/jackc/pgconn" + "github.com/jackc/pgx/v4" +) + +type DBTX interface { + Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error) + Query(context.Context, string, ...interface{}) (pgx.Rows, error) + QueryRow(context.Context, string, ...interface{}) pgx.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx pgx.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/examples/split/postgresql/inventory/inventory.sql b/examples/split/postgresql/inventory/inventory.sql new file mode 100644 index 0000000000..25a568453f --- /dev/null +++ b/examples/split/postgresql/inventory/inventory.sql @@ -0,0 +1,3 @@ +-- name: GetStock :many +SELECT * FROM stock +LIMIT 10; diff --git a/examples/split/postgresql/inventory/inventory.sql.go b/examples/split/postgresql/inventory/inventory.sql.go new file mode 100644 index 0000000000..9817563775 --- /dev/null +++ b/examples/split/postgresql/inventory/inventory.sql.go @@ -0,0 +1,55 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.13.0 +// source: inventory.sql + +package split + +import ( + "context" + + "../models" +) + +const getStock = `-- name: GetStock :many +SELECT s_i_id, s_w_id, s_quantity, s_dist_01, s_dist_02, s_dist_03, s_dist_04, s_dist_05, s_dist_06, s_dist_07, s_dist_08, s_dist_09, s_dist_10, s_ytd, s_order_cnt, s_remote_cnt, s_data FROM stock +LIMIT 10 +` + +func (q *Queries) GetStock(ctx context.Context) ([]models.Stock, error) { + rows, err := q.db.Query(ctx, getStock) + if err != nil { + return nil, err + } + defer rows.Close() + var items []models.Stock + for rows.Next() { + var i models.Stock + if err := rows.Scan( + &i.SIID, + &i.SWID, + &i.SQuantity, + &i.SDist01, + &i.SDist02, + &i.SDist03, + &i.SDist04, + &i.SDist05, + &i.SDist06, + &i.SDist07, + &i.SDist08, + &i.SDist09, + &i.SDist10, + &i.SYtd, + &i.SOrderCnt, + &i.SRemoteCnt, + &i.SData, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} diff --git a/examples/split/postgresql/inventory/querier.go b/examples/split/postgresql/inventory/querier.go new file mode 100644 index 0000000000..6b6c5d0dc8 --- /dev/null +++ b/examples/split/postgresql/inventory/querier.go @@ -0,0 +1,17 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.13.0 + +package split + +import ( + "context" + + "../models" +) + +type Querier interface { + GetStock(ctx context.Context) ([]models.Stock, error) +} + +var _ Querier = (*Queries)(nil) diff --git a/examples/split/postgresql/models/models.go b/examples/split/postgresql/models/models.go new file mode 100644 index 0000000000..3ffa291842 --- /dev/null +++ b/examples/split/postgresql/models/models.go @@ -0,0 +1,131 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.13.0 + +package models + +import ( + "database/sql" + + "github.com/jackc/pgtype" +) + +type Customer struct { + CID int32 `json:"c_id"` + CDID int16 `json:"c_d_id"` + CWID int16 `json:"c_w_id"` + CFirst sql.NullString `json:"c_first"` + CMiddle sql.NullString `json:"c_middle"` + CLast sql.NullString `json:"c_last"` + CStreet1 sql.NullString `json:"c_street_1"` + CStreet2 sql.NullString `json:"c_street_2"` + CCity sql.NullString `json:"c_city"` + CState sql.NullString `json:"c_state"` + CZip sql.NullString `json:"c_zip"` + CPhone sql.NullString `json:"c_phone"` + CSince interface{} `json:"c_since"` + CCredit sql.NullString `json:"c_credit"` + CCreditLim sql.NullInt64 `json:"c_credit_lim"` + CDiscount pgtype.Numeric `json:"c_discount"` + CBalance pgtype.Numeric `json:"c_balance"` + CYtdPayment pgtype.Numeric `json:"c_ytd_payment"` + CPaymentCnt sql.NullInt16 `json:"c_payment_cnt"` + CDeliveryCnt sql.NullInt16 `json:"c_delivery_cnt"` + CData sql.NullString `json:"c_data"` +} + +type District struct { + DID int16 `json:"d_id"` + DWID int16 `json:"d_w_id"` + DName sql.NullString `json:"d_name"` + DStreet1 sql.NullString `json:"d_street_1"` + DStreet2 sql.NullString `json:"d_street_2"` + DCity sql.NullString `json:"d_city"` + DState sql.NullString `json:"d_state"` + DZip sql.NullString `json:"d_zip"` + DTax pgtype.Numeric `json:"d_tax"` + DYtd pgtype.Numeric `json:"d_ytd"` + DNextOID sql.NullInt32 `json:"d_next_o_id"` +} + +type History struct { + ID int32 `json:"id"` + HCID sql.NullInt32 `json:"h_c_id"` + HCDID sql.NullInt16 `json:"h_c_d_id"` + HCWID sql.NullInt16 `json:"h_c_w_id"` + HDID sql.NullInt16 `json:"h_d_id"` + HWID sql.NullInt16 `json:"h_w_id"` + HDate sql.NullInt16 `json:"h_date"` + HAmount pgtype.Numeric `json:"h_amount"` + HData sql.NullString `json:"h_data"` +} + +type Item struct { + IID int32 `json:"i_id"` + IImID sql.NullInt32 `json:"i_im_id"` + IName sql.NullString `json:"i_name"` + IPrice pgtype.Numeric `json:"i_price"` + IData sql.NullString `json:"i_data"` +} + +type NewOrder struct { + NoOID int32 `json:"no_o_id"` + NoDID int16 `json:"no_d_id"` + NoWID int16 `json:"no_w_id"` +} + +type Order struct { + OID int32 `json:"o_id"` + ODID int16 `json:"o_d_id"` + OWID int16 `json:"o_w_id"` + OCID sql.NullInt32 `json:"o_c_id"` + OEntryD interface{} `json:"o_entry_d"` + OCarrierID sql.NullInt16 `json:"o_carrier_id"` + OOlCnt sql.NullInt16 `json:"o_ol_cnt"` + OAllLocal sql.NullInt16 `json:"o_all_local"` +} + +type OrderLine struct { + OlOID int32 `json:"ol_o_id"` + OlDID int16 `json:"ol_d_id"` + OlWID int16 `json:"ol_w_id"` + OlNumber int16 `json:"ol_number"` + OlIID sql.NullInt32 `json:"ol_i_id"` + OlSupplyWID sql.NullInt16 `json:"ol_supply_w_id"` + OlDeliveryD interface{} `json:"ol_delivery_d"` + OlQuantity sql.NullInt16 `json:"ol_quantity"` + OlAmount pgtype.Numeric `json:"ol_amount"` + OlDistInfo sql.NullString `json:"ol_dist_info"` +} + +type Stock struct { + SIID int32 `json:"s_i_id"` + SWID int16 `json:"s_w_id"` + SQuantity sql.NullInt16 `json:"s_quantity"` + SDist01 sql.NullString `json:"s_dist_01"` + SDist02 sql.NullString `json:"s_dist_02"` + SDist03 sql.NullString `json:"s_dist_03"` + SDist04 sql.NullString `json:"s_dist_04"` + SDist05 sql.NullString `json:"s_dist_05"` + SDist06 sql.NullString `json:"s_dist_06"` + SDist07 sql.NullString `json:"s_dist_07"` + SDist08 sql.NullString `json:"s_dist_08"` + SDist09 sql.NullString `json:"s_dist_09"` + SDist10 sql.NullString `json:"s_dist_10"` + SYtd pgtype.Numeric `json:"s_ytd"` + SOrderCnt sql.NullInt16 `json:"s_order_cnt"` + SRemoteCnt sql.NullInt16 `json:"s_remote_cnt"` + SData sql.NullString `json:"s_data"` +} + +type Warehouse struct { + WID int16 `json:"w_id"` + WName sql.NullString `json:"w_name"` + WStreet1 sql.NullString `json:"w_street_1"` + WStreet2 sql.NullString `json:"w_street_2"` + WCity sql.NullString `json:"w_city"` + WState sql.NullString `json:"w_state"` + WZip sql.NullString `json:"w_zip"` + WTax pgtype.Numeric `json:"w_tax"` + WYtd pgtype.Numeric `json:"w_ytd"` +} diff --git a/examples/split/postgresql/schema.sql b/examples/split/postgresql/schema.sql new file mode 100644 index 0000000000..1dbf1b0cae --- /dev/null +++ b/examples/split/postgresql/schema.sql @@ -0,0 +1,128 @@ +CREATE TABLE IF NOT EXISTS warehouse ( + w_id smallint not null, + w_name varchar(10), + w_street_1 varchar(20), + w_street_2 varchar(20), + w_city varchar(20), + w_state char(2), + w_zip char(9), + w_tax decimal(4,2), + w_ytd decimal(12,2), + primary key (w_id) +); + +create table IF NOT EXISTS district ( + d_id smallint not null, + d_w_id smallint not null, + d_name varchar(10), + d_street_1 varchar(20), + d_street_2 varchar(20), + d_city varchar(20), + d_state char(2), + d_zip char(9), + d_tax decimal(4,2), + d_ytd decimal(12,2), + d_next_o_id int, + primary key (d_w_id, d_id) +); + +create table IF NOT EXISTS customer ( + c_id int not null, + c_d_id smallint not null, + c_w_id smallint not null, + c_first varchar(16), + c_middle char(2), + c_last varchar(16), + c_street_1 varchar(20), + c_street_2 varchar(20), + c_city varchar(20), + c_state char(2), + c_zip char(9), + c_phone char(16), + c_since timestampz, + c_credit char(2), + c_credit_lim bigint, + c_discount decimal(4,2), + c_balance decimal(12,2), + c_ytd_payment decimal(12,2), + c_payment_cnt smallint, + c_delivery_cnt smallint, + c_data text, + PRIMARY KEY(c_w_id, c_d_id, c_id) +); + +create table IF NOT EXISTS history ( + id serial, + h_c_id int, + h_c_d_id smallint, + h_c_w_id smallint, + h_d_id smallint, + h_w_id smallint, + h_date smallint, + h_amount decimal(6,2), + h_data varchar(24), + PRIMARY KEY(id) +); + +create table IF NOT EXISTS orders ( + o_id int not null, + o_d_id smallint not null, + o_w_id smallint not null, + o_c_id int, + o_entry_d timestampz, + o_carrier_id smallint, + o_ol_cnt smallint, + o_all_local smallint, + PRIMARY KEY(o_w_id, o_d_id, o_id) +); + +create table IF NOT EXISTS new_orders ( + no_o_id int not null, + no_d_id smallint not null, + no_w_id smallint not null, + PRIMARY KEY(no_w_id, no_d_id, no_o_id) +); + +create table IF NOT EXISTS order_line ( + ol_o_id int not null, + ol_d_id smallint not null, + ol_w_id smallint not null, + ol_number smallint not null, + ol_i_id int, + ol_supply_w_id smallint, + ol_delivery_d timestampz, + ol_quantity smallint, + ol_amount decimal(6,2), + ol_dist_info char(24), + PRIMARY KEY(ol_w_id, ol_d_id, ol_o_id, ol_number) +); + +create table IF NOT EXISTS stock ( + s_i_id int not null, + s_w_id smallint not null, + s_quantity smallint, + s_dist_01 char(24), + s_dist_02 char(24), + s_dist_03 char(24), + s_dist_04 char(24), + s_dist_05 char(24), + s_dist_06 char(24), + s_dist_07 char(24), + s_dist_08 char(24), + s_dist_09 char(24), + s_dist_10 char(24), + s_ytd decimal(8,0), + s_order_cnt smallint, + s_remote_cnt smallint, + s_data varchar(50), + PRIMARY KEY(s_w_id, s_i_id) +); + +create table IF NOT EXISTS item ( + i_id int not null, + i_im_id int, + i_name varchar(24), + i_price decimal(5,2), + i_data varchar(50), + PRIMARY KEY(i_id) +); diff --git a/examples/split/postgresql/warehouse/db.go b/examples/split/postgresql/warehouse/db.go new file mode 100644 index 0000000000..c09ae2ccf1 --- /dev/null +++ b/examples/split/postgresql/warehouse/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.13.0 + +package split + +import ( + "context" + + "github.com/jackc/pgconn" + "github.com/jackc/pgx/v4" +) + +type DBTX interface { + Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error) + Query(context.Context, string, ...interface{}) (pgx.Rows, error) + QueryRow(context.Context, string, ...interface{}) pgx.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx pgx.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/examples/split/postgresql/warehouse/querier.go b/examples/split/postgresql/warehouse/querier.go new file mode 100644 index 0000000000..ada41f51aa --- /dev/null +++ b/examples/split/postgresql/warehouse/querier.go @@ -0,0 +1,17 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.13.0 + +package split + +import ( + "context" + + "../models" +) + +type Querier interface { + GetWarehouse(ctx context.Context) ([]models.Warehouse, error) +} + +var _ Querier = (*Queries)(nil) diff --git a/examples/split/postgresql/warehouse/warehouse.sql b/examples/split/postgresql/warehouse/warehouse.sql new file mode 100644 index 0000000000..13c374d771 --- /dev/null +++ b/examples/split/postgresql/warehouse/warehouse.sql @@ -0,0 +1,3 @@ +-- name: GetWarehouse :many +SELECT * FROM warehouse +LIMIT 10; diff --git a/examples/split/postgresql/warehouse/warehouse.sql.go b/examples/split/postgresql/warehouse/warehouse.sql.go new file mode 100644 index 0000000000..710acd7ec8 --- /dev/null +++ b/examples/split/postgresql/warehouse/warehouse.sql.go @@ -0,0 +1,47 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.13.0 +// source: warehouse.sql + +package split + +import ( + "context" + + "../models" +) + +const getWarehouse = `-- name: GetWarehouse :many +SELECT w_id, w_name, w_street_1, w_street_2, w_city, w_state, w_zip, w_tax, w_ytd FROM warehouse +LIMIT 10 +` + +func (q *Queries) GetWarehouse(ctx context.Context) ([]models.Warehouse, error) { + rows, err := q.db.Query(ctx, getWarehouse) + if err != nil { + return nil, err + } + defer rows.Close() + var items []models.Warehouse + for rows.Next() { + var i models.Warehouse + if err := rows.Scan( + &i.WID, + &i.WName, + &i.WStreet1, + &i.WStreet2, + &i.WCity, + &i.WState, + &i.WZip, + &i.WTax, + &i.WYtd, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} diff --git a/examples/split/sqlc.json b/examples/split/sqlc.json new file mode 100644 index 0000000000..9d1617829b --- /dev/null +++ b/examples/split/sqlc.json @@ -0,0 +1,31 @@ +{ + "version": "1", + "packages": [ + { + "path": "postgresql/warehouse", + "name": "split", + "schema": "postgresql/schema.sql", + "queries": "postgresql/warehouse/warehouse.sql", + "engine": "postgresql", + "sql_package": "pgx/v4", + "emit_json_tags": true, + "emit_prepared_queries": true, + "emit_interface": true, + "model_package": "../models", + "model_path": "../models" + }, + { + "path": "postgresql/inventory", + "name": "split", + "schema": "postgresql/schema.sql", + "queries": "postgresql/inventory/inventory.sql", + "engine": "postgresql", + "sql_package": "pgx/v4", + "emit_json_tags": true, + "emit_prepared_queries": true, + "emit_interface": true, + "model_package": "../models", + "model_path": "../models" + } + ] +} diff --git a/internal/cmd/shim.go b/internal/cmd/shim.go index 946e6d338c..c6e077b06b 100644 --- a/internal/cmd/shim.go +++ b/internal/cmd/shim.go @@ -90,6 +90,8 @@ func pluginGoCode(s config.SQLGo) *plugin.GoCode { EmitAllEnumValues: s.EmitAllEnumValues, JsonTagsCaseStyle: s.JSONTagsCaseStyle, Package: s.Package, + ModelPackage: s.ModelPackage, + ModelPath: s.ModelPath, Out: s.Out, SqlPackage: s.SQLPackage, OutputDbFileName: s.OutputDBFileName, diff --git a/internal/codegen/golang/gen.go b/internal/codegen/golang/gen.go index eb21c06875..e9a8eac862 100644 --- a/internal/codegen/golang/gen.go +++ b/internal/codegen/golang/gen.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "go/format" + "path" "strings" "text/template" @@ -15,13 +16,14 @@ import ( ) type tmplCtx struct { - Q string - Package string - SQLPackage SQLPackage - Enums []Enum - Structs []Struct - GoQueries []Query - SqlcVersion string + Q string + Package string + SQLPackage SQLPackage + Enums []Enum + Structs []Struct + GoQueries []Query + SqlcVersion string + ModelPackage string // TODO: Race conditions SourceName string @@ -61,11 +63,12 @@ func generate(req *plugin.CodeGenRequest, enums []Enum, structs []Struct, querie } funcMap := template.FuncMap{ - "lowerTitle": sdk.LowerTitle, - "comment": sdk.DoubleSlashComment, - "escape": sdk.EscapeBacktick, - "imports": i.Imports, - "hasPrefix": strings.HasPrefix, + "lowerTitle": sdk.LowerTitle, + "comment": sdk.DoubleSlashComment, + "escape": sdk.EscapeBacktick, + "imports": i.Imports, + "hasPrefix": strings.HasPrefix, + "packageName": sdk.PackageName, } tmpl := template.Must( @@ -79,6 +82,12 @@ func generate(req *plugin.CodeGenRequest, enums []Enum, structs []Struct, querie ) golang := req.Settings.Go + + modelPackage := golang.ModelPackage + if modelPackage == "" && golang.ModelPath != "" { + modelPackage = golang.ModelPath + } + tctx := tmplCtx{ EmitInterface: golang.EmitInterface, EmitJSONTags: golang.EmitJsonTags, @@ -97,6 +106,7 @@ func generate(req *plugin.CodeGenRequest, enums []Enum, structs []Struct, querie Enums: enums, Structs: structs, SqlcVersion: req.SqlcVersion, + ModelPackage: golang.ModelPackage, } if tctx.UsesCopyFrom && tctx.SQLPackage != SQLPackagePGX { @@ -143,6 +153,15 @@ func generate(req *plugin.CodeGenRequest, enums []Enum, structs []Struct, querie if golang.OutputModelsFileName != "" { modelsFileName = golang.OutputModelsFileName } + + if golang.ModelPackage != "" { + if golang.ModelPath != "" { + modelsFileName = path.Join(golang.ModelPath, modelsFileName) + } else { + modelsFileName = path.Join(golang.ModelPackage, modelsFileName) + } + } + querierFileName := "querier.go" if golang.OutputQuerierFileName != "" { querierFileName = golang.OutputQuerierFileName diff --git a/internal/codegen/golang/imports.go b/internal/codegen/golang/imports.go index e51e751d12..ef17922cb1 100644 --- a/internal/codegen/golang/imports.go +++ b/internal/codegen/golang/imports.go @@ -2,6 +2,7 @@ package golang import ( "fmt" + "path" "sort" "strings" @@ -85,6 +86,15 @@ func (i *importer) Imports(filename string) [][]ImportSpec { if i.Settings.Go.OutputModelsFileName != "" { modelsFileName = i.Settings.Go.OutputModelsFileName } + + if i.Settings.Go.ModelPackage != "" { + if i.Settings.Go.ModelPath != "" { + modelsFileName = path.Join(i.Settings.Go.ModelPath, modelsFileName) + } else { + modelsFileName = path.Join(i.Settings.Go.ModelPackage, modelsFileName) + } + } + querierFileName := "querier.go" if i.Settings.Go.OutputQuerierFileName != "" { querierFileName = i.Settings.Go.OutputQuerierFileName diff --git a/internal/codegen/golang/query.go b/internal/codegen/golang/query.go index 2eed835c6f..5e0ff78360 100644 --- a/internal/codegen/golang/query.go +++ b/internal/codegen/golang/query.go @@ -59,6 +59,9 @@ func (v QueryValue) Type() string { func (v *QueryValue) DefineType() string { t := v.Type() + if v.IsStruct() && v.Struct.Package != "" { + t = v.Struct.Package + "." + t + } if v.IsPointer() { return "*" + t } diff --git a/internal/codegen/golang/result.go b/internal/codegen/golang/result.go index 1feb800b22..cbfbf33d9a 100644 --- a/internal/codegen/golang/result.go +++ b/internal/codegen/golang/result.go @@ -70,6 +70,7 @@ func buildStructs(req *plugin.CodeGenRequest) []Struct { Table: plugin.Identifier{Schema: schema.Name, Name: table.Rel.Name}, Name: StructName(structName, req.Settings), Comment: table.Comment, + Package: sdk.PackageName(req.Settings.Go.ModelPackage), } for _, column := range table.Columns { tags := map[string]string{} @@ -176,6 +177,9 @@ func buildQueries(req *plugin.CodeGenRequest, structs []Struct) ([]Query, error) if err != nil { return nil, err } + // Keep the input arguments in the same package + s.Package = "" + gq.Arg = QueryValue{ Emit: true, Name: "arg", @@ -259,7 +263,8 @@ func buildQueries(req *plugin.CodeGenRequest, structs []Struct) ([]Query, error) // This is unlikely to happen, so don't fix it yet func columnsToStruct(req *plugin.CodeGenRequest, name string, columns []goColumn, useID bool) (*Struct, error) { gs := Struct{ - Name: name, + Name: name, + Package: sdk.PackageName(req.Settings.Go.ModelPackage), } seen := map[string][]int{} suffixes := map[int]int{} diff --git a/internal/codegen/golang/struct.go b/internal/codegen/golang/struct.go index f72a228ae3..c5e00c8fa0 100644 --- a/internal/codegen/golang/struct.go +++ b/internal/codegen/golang/struct.go @@ -13,6 +13,7 @@ type Struct struct { Name string Fields []Field Comment string + Package string } func StructName(name string, settings *plugin.Settings) string { diff --git a/internal/codegen/golang/templates/pgx/batchCode.tmpl b/internal/codegen/golang/templates/pgx/batchCode.tmpl index c48ac5aecc..511996178c 100644 --- a/internal/codegen/golang/templates/pgx/batchCode.tmpl +++ b/internal/codegen/golang/templates/pgx/batchCode.tmpl @@ -73,7 +73,7 @@ func (b *{{.MethodName}}BatchResults) Query(f func(int, []{{.Ret.DefineType}}, e var items []{{.Ret.DefineType}} {{end -}} for rows.Next() { - var {{.Ret.Name}} {{.Ret.Type}} + var {{.Ret.Name}} {{.Ret.DefineType}} if err := rows.Scan({{.Ret.Scan}}); err != nil { break } @@ -92,7 +92,7 @@ func (b *{{.MethodName}}BatchResults) Query(f func(int, []{{.Ret.DefineType}}, e func (b *{{.MethodName}}BatchResults) QueryRow(f func(int, {{.Ret.DefineType}}, error)) { for { row := b.br.QueryRow() - var {{.Ret.Name}} {{.Ret.Type}} + var {{.Ret.Name}} {{.Ret.DefineType}} err := row.Scan({{.Ret.Scan}}) if err != nil && (err.Error() == "no result" || err.Error() == "batch already closed") { break diff --git a/internal/codegen/golang/templates/pgx/queryCode.tmpl b/internal/codegen/golang/templates/pgx/queryCode.tmpl index 230844a58b..d2a36042b8 100644 --- a/internal/codegen/golang/templates/pgx/queryCode.tmpl +++ b/internal/codegen/golang/templates/pgx/queryCode.tmpl @@ -33,7 +33,7 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, db DBTX, {{.Arg.Pair}}) ( func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) ({{.Ret.DefineType}}, error) { row := q.db.QueryRow(ctx, {{.ConstantName}}, {{.Arg.Params}}) {{- end}} - var {{.Ret.Name}} {{.Ret.Type}} + var {{.Ret.Name}} {{.Ret.DefineType}} err := row.Scan({{.Ret.Scan}}) return {{.Ret.ReturnName}}, err } @@ -59,7 +59,7 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) ([]{{.Ret. var items []{{.Ret.DefineType}} {{end -}} for rows.Next() { - var {{.Ret.Name}} {{.Ret.Type}} + var {{.Ret.Name}} {{.Ret.DefineType}} if err := rows.Scan({{.Ret.Scan}}); err != nil { return nil, err } diff --git a/internal/codegen/golang/templates/template.tmpl b/internal/codegen/golang/templates/template.tmpl index 9f8d0d29db..b25dfabbaa 100644 --- a/internal/codegen/golang/templates/template.tmpl +++ b/internal/codegen/golang/templates/template.tmpl @@ -33,8 +33,9 @@ package {{.Package}} import ( {{range imports .SourceName}} {{range .}}{{.}} - {{end}} - {{end}} + {{end}}{{end}}{{ if ne .ModelPackage ""}} + "{{- .ModelPackage}}" + {{end}} ) {{template "interfaceCode" . }} @@ -52,7 +53,11 @@ import ( // versions: // sqlc {{.SqlcVersion}} -package {{.Package}} +package {{ if ne .ModelPackage ""}} + {{- packageName .ModelPackage -}} + {{else}} + {{- .Package -}} + {{end}} import ( {{range imports .SourceName}} @@ -127,8 +132,9 @@ package {{.Package}} import ( {{range imports .SourceName}} {{range .}}{{.}} - {{end}} - {{end}} + {{end}}{{end}}{{ if ne .ModelPackage ""}} + "{{- .ModelPackage}}" + {{end}} ) {{template "queryCode" . }} @@ -153,7 +159,7 @@ import ( {{range imports .SourceName}} {{range .}}{{.}} {{end}} - {{end}} + {{end}} ) {{template "copyfromCode" . }} @@ -174,8 +180,9 @@ package {{.Package}} import ( {{range imports .SourceName}} {{range .}}{{.}} - {{end}} - {{end}} + {{end}}{{end}}{{ if ne .ModelPackage ""}} + "{{- .ModelPackage}}" + {{end}} ) {{template "batchCode" . }} {{end}} diff --git a/internal/codegen/sdk/utils.go b/internal/codegen/sdk/utils.go index 1dffda9e7e..696b2f2989 100644 --- a/internal/codegen/sdk/utils.go +++ b/internal/codegen/sdk/utils.go @@ -38,3 +38,11 @@ func EscapeBacktick(s string) string { func DoubleSlashComment(s string) string { return "// " + strings.ReplaceAll(s, "\n", "\n// ") } + +func PackageName(s string) string { + p := strings.Split(s, "/") + if strings.HasSuffix(s, "/") { + return p[len(p)-2] + } + return p[len(p)-1] +} diff --git a/internal/config/config.go b/internal/config/config.go index 35350ba562..86786b2518 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -136,6 +136,8 @@ type SQLGo struct { Overrides []Override `json:"overrides,omitempty" yaml:"overrides"` Rename map[string]string `json:"rename,omitempty" yaml:"rename"` SQLPackage string `json:"sql_package" yaml:"sql_package"` + ModelPackage string `json:"model_package" yaml:"model_package"` + ModelPath string `json:"model_path" yaml:"model_path"` OutputDBFileName string `json:"output_db_file_name,omitempty" yaml:"output_db_file_name"` OutputModelsFileName string `json:"output_models_file_name,omitempty" yaml:"output_models_file_name"` OutputQuerierFileName string `json:"output_querier_file_name,omitempty" yaml:"output_querier_file_name"` diff --git a/internal/config/v_one.go b/internal/config/v_one.go index 5771971295..06d48efe23 100644 --- a/internal/config/v_one.go +++ b/internal/config/v_one.go @@ -36,6 +36,8 @@ type v1PackageSettings struct { EmitAllEnumValues bool `json:"emit_all_enum_values,omitempty" yaml:"emit_all_enum_values"` JSONTagsCaseStyle string `json:"json_tags_case_style,omitempty" yaml:"json_tags_case_style"` SQLPackage string `json:"sql_package" yaml:"sql_package"` + ModelPackage string `json:"model_package" yaml:"model_package"` + ModelPath string `json:"model_path" yaml:"model_path"` Overrides []Override `json:"overrides" yaml:"overrides"` OutputDBFileName string `json:"output_db_file_name,omitempty" yaml:"output_db_file_name"` OutputModelsFileName string `json:"output_models_file_name,omitempty" yaml:"output_models_file_name"` @@ -133,6 +135,8 @@ func (c *V1GenerateSettings) Translate() Config { Package: pkg.Name, Out: pkg.Path, SQLPackage: pkg.SQLPackage, + ModelPackage: pkg.ModelPackage, + ModelPath: pkg.ModelPath, Overrides: pkg.Overrides, JSONTagsCaseStyle: pkg.JSONTagsCaseStyle, OutputDBFileName: pkg.OutputDBFileName, diff --git a/internal/plugin/codegen.pb.go b/internal/plugin/codegen.pb.go index e28a4e90b9..743587b9b4 100644 --- a/internal/plugin/codegen.pb.go +++ b/internal/plugin/codegen.pb.go @@ -603,6 +603,8 @@ type GoCode struct { OutputFilesSuffix string `protobuf:"bytes,18,opt,name=output_files_suffix,json=outputFilesSuffix,proto3" json:"output_files_suffix,omitempty"` EmitEnumValidMethod bool `protobuf:"varint,19,opt,name=emit_enum_valid_method,json=emitEnumValidMethod,proto3" json:"emit_enum_valid_method,omitempty"` EmitAllEnumValues bool `protobuf:"varint,20,opt,name=emit_all_enum_values,json=emitAllEnumValues,proto3" json:"emit_all_enum_values,omitempty"` + ModelPackage string `protobuf:"bytes,21,opt,name=model_package,json=modelPackage,proto3" json:"model_package,omitempty"` + ModelPath string `protobuf:"bytes,22,opt,name=model_path,json=modelPath,proto3" json:"model_path,omitempty"` } func (x *GoCode) Reset() { @@ -777,6 +779,20 @@ func (x *GoCode) GetEmitAllEnumValues() bool { return false } +func (x *GoCode) GetModelPackage() string { + if x != nil { + return x.ModelPackage + } + return "" +} + +func (x *GoCode) GetModelPath() string { + if x != nil { + return x.ModelPath + } + return "" +} + type JSONCode struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1718,7 +1734,7 @@ var file_plugin_codegen_proto_rawDesc = []byte{ 0x74, 0x45, 0x78, 0x61, 0x63, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6f, 0x75, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6f, 0x75, 0x74, 0x22, 0xb3, 0x07, 0x0a, + 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6f, 0x75, 0x74, 0x22, 0xf7, 0x07, 0x0a, 0x06, 0x47, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x6d, 0x69, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x65, 0x6d, 0x69, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x24, @@ -1778,114 +1794,118 @@ var file_plugin_codegen_proto_rawDesc = []byte{ 0x64, 0x12, 0x2f, 0x0a, 0x14, 0x65, 0x6d, 0x69, 0x74, 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x65, 0x6d, 0x69, 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x73, 0x22, 0x34, 0x0a, 0x08, 0x4a, 0x53, 0x4f, 0x4e, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x10, - 0x0a, 0x03, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6f, 0x75, 0x74, - 0x12, 0x16, 0x0a, 0x06, 0x69, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x69, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x22, 0x88, 0x01, 0x0a, 0x07, 0x43, 0x61, 0x74, - 0x61, 0x6c, 0x6f, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x25, - 0x0a, 0x0e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, - 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x07, 0x73, 0x63, 0x68, - 0x65, 0x6d, 0x61, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x6c, 0x75, - 0x67, 0x69, 0x6e, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x07, 0x73, 0x63, 0x68, 0x65, - 0x6d, 0x61, 0x73, 0x22, 0xc1, 0x01, 0x0a, 0x06, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x18, - 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x06, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, - 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x06, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x05, 0x65, 0x6e, 0x75, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x45, 0x6e, 0x75, 0x6d, - 0x52, 0x05, 0x65, 0x6e, 0x75, 0x6d, 0x73, 0x12, 0x3e, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x15, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0x3d, 0x0a, 0x0d, 0x43, 0x6f, 0x6d, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, - 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, - 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x48, 0x0a, 0x04, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x76, 0x61, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x04, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, - 0x22, 0x71, 0x0a, 0x05, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x24, 0x0a, 0x03, 0x72, 0x65, 0x6c, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, - 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x03, 0x72, 0x65, 0x6c, 0x12, - 0x28, 0x0a, 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x0e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, - 0x52, 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, - 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, - 0x65, 0x6e, 0x74, 0x22, 0x52, 0x0a, 0x0a, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, - 0x72, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x73, - 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x68, - 0x65, 0x6d, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xd5, 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6c, 0x75, - 0x6d, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x6f, 0x74, 0x5f, 0x6e, 0x75, - 0x6c, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x6e, 0x6f, 0x74, 0x4e, 0x75, 0x6c, - 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x41, 0x72, 0x72, 0x61, 0x79, 0x12, 0x18, 0x0a, 0x07, - 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, - 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x24, - 0x0a, 0x0e, 0x69, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x64, 0x50, - 0x61, 0x72, 0x61, 0x6d, 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x5f, - 0x63, 0x61, 0x6c, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x46, 0x75, - 0x6e, 0x63, 0x43, 0x61, 0x6c, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, - 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x28, 0x0a, 0x05, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x6c, - 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, - 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, - 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x26, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, - 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x49, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, - 0x94, 0x02, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x6d, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x63, 0x6d, 0x64, 0x12, 0x28, 0x0a, 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x18, 0x04, + 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x70, 0x61, 0x63, 0x6b, + 0x61, 0x67, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x6f, 0x64, 0x65, 0x6c, + 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x6f, 0x64, 0x65, 0x6c, + 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x6f, 0x64, + 0x65, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x22, 0x34, 0x0a, 0x08, 0x4a, 0x53, 0x4f, 0x4e, 0x43, 0x6f, + 0x64, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6f, 0x75, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x69, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x22, 0x88, 0x01, 0x0a, + 0x07, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, + 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, + 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x73, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x65, 0x66, 0x61, + 0x75, 0x6c, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, + 0x07, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, + 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x07, + 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x22, 0xc1, 0x01, 0x0a, 0x06, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x25, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x0d, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, + 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x05, 0x65, 0x6e, 0x75, 0x6d, 0x73, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, + 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x05, 0x65, 0x6e, 0x75, 0x6d, 0x73, 0x12, 0x3e, 0x0a, 0x0f, 0x63, + 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x05, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x43, 0x6f, + 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0e, 0x63, 0x6f, 0x6d, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0x3d, 0x0a, 0x0d, 0x43, + 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x48, 0x0a, 0x04, 0x45, 0x6e, + 0x75, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x76, 0x61, 0x6c, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, + 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, + 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x71, 0x0a, 0x05, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x24, 0x0a, + 0x03, 0x72, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x6c, 0x75, + 0x67, 0x69, 0x6e, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x03, + 0x72, 0x65, 0x6c, 0x12, 0x28, 0x0a, 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x43, 0x6f, - 0x6c, 0x75, 0x6d, 0x6e, 0x52, 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x12, 0x2d, 0x0a, - 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, - 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, - 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x1a, 0x0a, 0x08, - 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, - 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x40, 0x0a, 0x11, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x5f, 0x69, - 0x6e, 0x74, 0x6f, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x6c, 0x75, 0x6d, 0x6e, 0x52, 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x12, 0x18, 0x0a, + 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x52, 0x0a, 0x0a, 0x49, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, + 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xd5, 0x02, 0x0a, 0x06, + 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x6f, + 0x74, 0x5f, 0x6e, 0x75, 0x6c, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x6e, 0x6f, + 0x74, 0x4e, 0x75, 0x6c, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x61, 0x72, 0x72, 0x61, + 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x41, 0x72, 0x72, 0x61, 0x79, + 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65, + 0x6e, 0x67, 0x74, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6c, 0x65, 0x6e, 0x67, + 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0e, 0x69, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x64, 0x5f, 0x70, + 0x61, 0x72, 0x61, 0x6d, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x73, 0x4e, 0x61, + 0x6d, 0x65, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x66, + 0x75, 0x6e, 0x63, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, + 0x69, 0x73, 0x46, 0x75, 0x6e, 0x63, 0x43, 0x61, 0x6c, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, + 0x6f, 0x70, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, + 0x12, 0x28, 0x0a, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, - 0x69, 0x65, 0x72, 0x52, 0x11, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x6f, - 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x4b, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, - 0x74, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x26, 0x0a, 0x06, 0x63, - 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x6c, - 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x52, 0x06, 0x63, 0x6f, 0x6c, - 0x75, 0x6d, 0x6e, 0x22, 0xb6, 0x01, 0x0a, 0x0e, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, - 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x08, 0x73, 0x65, 0x74, 0x74, - 0x69, 0x6e, 0x67, 0x73, 0x12, 0x29, 0x0a, 0x07, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x43, - 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x07, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, - 0x27, 0x0a, 0x07, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x0d, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, - 0x07, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x71, 0x6c, 0x63, - 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x73, 0x71, 0x6c, 0x63, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x35, 0x0a, 0x0f, - 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x22, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, - 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x05, 0x66, 0x69, - 0x6c, 0x65, 0x73, 0x42, 0x2c, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x6b, 0x79, 0x6c, 0x65, 0x63, 0x6f, 0x6e, 0x72, 0x6f, 0x79, 0x2f, 0x73, 0x71, 0x6c, - 0x63, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, - 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x69, 0x65, 0x72, 0x52, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x26, 0x0a, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x6c, 0x75, 0x67, + 0x69, 0x6e, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x22, 0x94, 0x02, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x12, 0x0a, + 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, + 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x6d, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x63, 0x6d, 0x64, 0x12, 0x28, 0x0a, 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d, + 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, + 0x6e, 0x2e, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x52, 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, + 0x73, 0x12, 0x2d, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, + 0x65, 0x74, 0x65, 0x72, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, + 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1a, 0x0a, 0x08, + 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x40, 0x0a, 0x11, 0x69, 0x6e, 0x73, 0x65, + 0x72, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x6f, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x49, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x11, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x5f, + 0x69, 0x6e, 0x74, 0x6f, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x4b, 0x0a, 0x09, 0x50, 0x61, + 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, + 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, + 0x26, 0x0a, 0x06, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x52, + 0x06, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x22, 0xb6, 0x01, 0x0a, 0x0e, 0x43, 0x6f, 0x64, 0x65, + 0x47, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x08, 0x73, 0x65, + 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x08, + 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x29, 0x0a, 0x07, 0x63, 0x61, 0x74, 0x61, + 0x6c, 0x6f, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x6c, 0x75, 0x67, + 0x69, 0x6e, 0x2e, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x07, 0x63, 0x61, 0x74, 0x61, + 0x6c, 0x6f, 0x67, 0x12, 0x27, 0x0a, 0x07, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x52, 0x07, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c, + 0x73, 0x71, 0x6c, 0x63, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0c, 0x73, 0x71, 0x6c, 0x63, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x22, 0x35, 0x0a, 0x0f, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x46, 0x69, 0x6c, 0x65, + 0x52, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x42, 0x2c, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x79, 0x6c, 0x65, 0x63, 0x6f, 0x6e, 0x72, 0x6f, 0x79, + 0x2f, 0x73, 0x71, 0x6c, 0x63, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/internal/plugin/codegen_vtproto.pb.go b/internal/plugin/codegen_vtproto.pb.go index 0b70319cb4..27597ea03a 100644 --- a/internal/plugin/codegen_vtproto.pb.go +++ b/internal/plugin/codegen_vtproto.pb.go @@ -587,6 +587,24 @@ func (m *GoCode) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if len(m.ModelPath) > 0 { + i -= len(m.ModelPath) + copy(dAtA[i:], m.ModelPath) + i = encodeVarint(dAtA, i, uint64(len(m.ModelPath))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xb2 + } + if len(m.ModelPackage) > 0 { + i -= len(m.ModelPackage) + copy(dAtA[i:], m.ModelPackage) + i = encodeVarint(dAtA, i, uint64(len(m.ModelPackage))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xaa + } if m.EmitAllEnumValues { i-- if m.EmitAllEnumValues { @@ -1898,6 +1916,14 @@ func (m *GoCode) SizeVT() (n int) { if m.EmitAllEnumValues { n += 3 } + l = len(m.ModelPackage) + if l > 0 { + n += 2 + l + sov(uint64(l)) + } + l = len(m.ModelPath) + if l > 0 { + n += 2 + l + sov(uint64(l)) + } if m.unknownFields != nil { n += len(m.unknownFields) } @@ -4307,6 +4333,70 @@ func (m *GoCode) UnmarshalVT(dAtA []byte) error { } } m.EmitAllEnumValues = bool(v != 0) + case 21: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ModelPackage", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ModelPackage = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 22: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ModelPath", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ModelPath = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) diff --git a/internal/python/ast/ast.pb.go b/internal/python/ast/ast.pb.go index fee7ed4ad9..5b6582f9b2 100644 --- a/internal/python/ast/ast.pb.go +++ b/internal/python/ast/ast.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.27.1 -// protoc v3.19.1 +// protoc-gen-go v1.28.0 +// protoc v3.19.4 // source: python/ast.proto package ast diff --git a/protos/plugin/codegen.proto b/protos/plugin/codegen.proto index 8dc6360399..a2d072cfc1 100644 --- a/protos/plugin/codegen.proto +++ b/protos/plugin/codegen.proto @@ -101,6 +101,8 @@ message GoCode string output_files_suffix = 18; bool emit_enum_valid_method = 19; bool emit_all_enum_values = 20; + string model_package = 21; + string model_path = 22; } message JSONCode From 6fce5e5fb30134db80feb92c6033b095b9e45af5 Mon Sep 17 00:00:00 2001 From: jlisthood <98786963+jlisthood@users.noreply.github.com> Date: Sat, 9 Jul 2022 21:42:53 -0700 Subject: [PATCH 2/8] fix: missing imports (#1637) --- internal/codegen/golang/imports.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/internal/codegen/golang/imports.go b/internal/codegen/golang/imports.go index ef17922cb1..59816fd8b9 100644 --- a/internal/codegen/golang/imports.go +++ b/internal/codegen/golang/imports.go @@ -319,7 +319,8 @@ func (i *importer) queryImports(filename string) fileImports { } } } - if strings.HasPrefix(q.Ret.Type(), name) { + retType := strings.TrimPrefix(q.Ret.Type(), "[]") + if strings.HasPrefix(retType, name) { return true } } @@ -332,7 +333,8 @@ func (i *importer) queryImports(filename string) fileImports { } } } - if strings.HasPrefix(q.Arg.Type(), name) { + argType := strings.TrimPrefix(q.Arg.Type(), "[]") + if strings.HasPrefix(argType, name) { return true } } @@ -427,7 +429,8 @@ func (i *importer) batchImports(filename string) fileImports { } } } - if strings.HasPrefix(q.Ret.Type(), name) { + retType := strings.TrimPrefix(q.Ret.Type(), "[]") + if strings.HasPrefix(retType, name) { return true } } @@ -440,7 +443,8 @@ func (i *importer) batchImports(filename string) fileImports { } } } - if strings.HasPrefix(q.Arg.Type(), name) { + argType := strings.TrimPrefix(q.Arg.Type(), "[]") + if strings.HasPrefix(argType, name) { return true } } From 82c254d177ab100411e3fd4bf8714e71249ac17c Mon Sep 17 00:00:00 2001 From: Jesse Liston Date: Wed, 3 Aug 2022 18:22:23 -0700 Subject: [PATCH 3/8] fix: missing import for querier.go --- internal/codegen/golang/imports.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/codegen/golang/imports.go b/internal/codegen/golang/imports.go index 59816fd8b9..8c38f8a026 100644 --- a/internal/codegen/golang/imports.go +++ b/internal/codegen/golang/imports.go @@ -254,7 +254,8 @@ func (i *importer) interfaceImports() fileImports { } } if !q.Arg.isEmpty() { - if strings.HasPrefix(q.Arg.Type(), name) { + argType := strings.TrimPrefix(q.Arg.Type(), "[]") + if strings.HasPrefix(argType, name) { return true } } From b0f56905dd2d2ace9c70e4fdfe42c8d0cc44ff80 Mon Sep 17 00:00:00 2001 From: Daniel Kozlowski Date: Wed, 10 Aug 2022 12:59:14 -0700 Subject: [PATCH 4/8] fix: Updated split models code to handle return values There is an issue with split models that has issues when you have return types and enum's. This change handles both of those cases and makes type generation more robust. It also better handles import statements --- internal/codegen/golang/imports.go | 33 +++++++++++++++++++ internal/codegen/golang/postgresql_type.go | 8 +++-- internal/codegen/golang/result.go | 14 ++++++-- internal/codegen/golang/struct.go | 7 ++++ .../golang/templates/stdlib/queryCode.tmpl | 4 +-- .../codegen/golang/templates/template.tmpl | 12 ++----- 6 files changed, 63 insertions(+), 15 deletions(-) diff --git a/internal/codegen/golang/imports.go b/internal/codegen/golang/imports.go index 8c38f8a026..78ea74dfbb 100644 --- a/internal/codegen/golang/imports.go +++ b/internal/codegen/golang/imports.go @@ -6,6 +6,7 @@ import ( "sort" "strings" + "github.com/kyleconroy/sqlc/internal/codegen/sdk" "github.com/kyleconroy/sqlc/internal/metadata" "github.com/kyleconroy/sqlc/internal/plugin" ) @@ -230,6 +231,12 @@ func buildImports(settings *plugin.Settings, queries []Query, uses func(string) pkg[ImportSpec{Path: "github.com/google/uuid"}] = struct{}{} } + if settings.Go.ModelPackage != "" { + if uses(sdk.PackageName(settings.Go.ModelPackage)) { + pkg[ImportSpec{Path: settings.Go.ModelPackage}] = struct{}{} + } + } + // Custom imports for _, o := range settings.Overrides { if o.GoType.BasicType || o.GoType.TypeName == "" { @@ -251,6 +258,8 @@ func (i *importer) interfaceImports() fileImports { if q.hasRetType() { if strings.HasPrefix(q.Ret.Type(), name) { return true + } else if strings.HasPrefix(q.Ret.DefineType(), name) { + return true } } if !q.Arg.isEmpty() { @@ -312,6 +321,12 @@ func (i *importer) queryImports(filename string) fileImports { std, pkg := buildImports(i.Settings, gq, func(name string) bool { for _, q := range gq { if q.hasRetType() { + if q.Ret.Struct != nil { + fName := strings.TrimPrefix(q.Ret.Struct.FullName(), "[]") + if strings.HasPrefix(fName, name) { + return true + } + } if q.Ret.EmitStruct() { for _, f := range q.Ret.Struct.Fields { fType := strings.TrimPrefix(f.Type, "[]") @@ -326,6 +341,12 @@ func (i *importer) queryImports(filename string) fileImports { } } if !q.Arg.isEmpty() { + if q.Arg.Struct != nil { + fName := strings.TrimPrefix(q.Arg.Struct.FullName(), "[]") + if strings.HasPrefix(fName, name) { + return true + } + } if q.Arg.EmitStruct() { for _, f := range q.Arg.Struct.Fields { fType := strings.TrimPrefix(f.Type, "[]") @@ -422,6 +443,12 @@ func (i *importer) batchImports(filename string) fileImports { continue } if q.hasRetType() { + if q.Ret.Struct != nil { + fName := strings.TrimPrefix(q.Ret.Struct.FullName(), "[]") + if strings.HasPrefix(fName, name) { + return true + } + } if q.Ret.EmitStruct() { for _, f := range q.Ret.Struct.Fields { fType := strings.TrimPrefix(f.Type, "[]") @@ -436,6 +463,12 @@ func (i *importer) batchImports(filename string) fileImports { } } if !q.Arg.isEmpty() { + if q.Arg.Struct != nil { + fName := strings.TrimPrefix(q.Arg.Struct.FullName(), "[]") + if strings.HasPrefix(fName, name) { + return true + } + } if q.Arg.EmitStruct() { for _, f := range q.Arg.Struct.Fields { fType := strings.TrimPrefix(f.Type, "[]") diff --git a/internal/codegen/golang/postgresql_type.go b/internal/codegen/golang/postgresql_type.go index afa5a21aa7..5bdfcc7061 100644 --- a/internal/codegen/golang/postgresql_type.go +++ b/internal/codegen/golang/postgresql_type.go @@ -280,10 +280,14 @@ func postgresType(req *plugin.CodeGenRequest, col *plugin.Column) string { for _, enum := range schema.Enums { if rel.Name == enum.Name && rel.Schema == schema.Name { + var prefix string + if req.Settings.Go.ModelPackage != "" { + prefix = sdk.PackageName(req.Settings.Go.ModelPackage) + "." + } if schema.Name == req.Catalog.DefaultSchema { - return StructName(enum.Name, req.Settings) + return prefix + StructName(enum.Name, req.Settings) } - return StructName(schema.Name+"_"+enum.Name, req.Settings) + return prefix + StructName(schema.Name+"_"+enum.Name, req.Settings) } } diff --git a/internal/codegen/golang/result.go b/internal/codegen/golang/result.go index cbfbf33d9a..73bace0c7b 100644 --- a/internal/codegen/golang/result.go +++ b/internal/codegen/golang/result.go @@ -80,12 +80,19 @@ func buildStructs(req *plugin.CodeGenRequest) []Struct { if req.Settings.Go.EmitJsonTags { tags["json:"] = JSONTagName(column.Name, req.Settings) } + + // For Structs we don't want our enum's to have prefixes + pkg := req.Settings.Go.ModelPackage + req.Settings.Go.ModelPackage = "" + s.Fields = append(s.Fields, Field{ Name: StructName(column.Name, req.Settings), Type: goType(req, column), Tags: tags, Comment: column.Comment, }) + + req.Settings.Go.ModelPackage = pkg } structs = append(structs, s) } @@ -188,8 +195,8 @@ func buildQueries(req *plugin.CodeGenRequest, structs []Struct) ([]Query, error) EmitPointer: req.Settings.Go.EmitParamsStructPointers, } } - if len(query.Columns) == 1 { + c := query.Columns[0] name := columnName(c, 0) if c.IsFuncCall { @@ -212,7 +219,7 @@ func buildQueries(req *plugin.CodeGenRequest, structs []Struct) ([]Query, error) for i, f := range s.Fields { c := query.Columns[i] sameName := f.Name == StructName(columnName(c, i), req.Settings) - sameType := f.Type == goType(req, c) + sameType := (f.Type == goType(req, c)) || (s.Package+"."+f.Type == goType(req, c)) sameTable := sdk.SameTableName(c.Table, &s.Table, req.Catalog.DefaultSchema) if !sameName || !sameType || !sameTable { same = false @@ -238,7 +245,9 @@ func buildQueries(req *plugin.CodeGenRequest, structs []Struct) ([]Query, error) return nil, err } emit = true + gs.Package = "" } + gq.Ret = QueryValue{ Emit: emit, Name: "i", @@ -251,6 +260,7 @@ func buildQueries(req *plugin.CodeGenRequest, structs []Struct) ([]Query, error) qs = append(qs, gq) } sort.Slice(qs, func(i, j int) bool { return qs[i].MethodName < qs[j].MethodName }) + return qs, nil } diff --git a/internal/codegen/golang/struct.go b/internal/codegen/golang/struct.go index c5e00c8fa0..8e3cc832de 100644 --- a/internal/codegen/golang/struct.go +++ b/internal/codegen/golang/struct.go @@ -16,6 +16,13 @@ type Struct struct { Package string } +func (s *Struct) FullName() string { + if s.Package != "" { + return s.Package + "." + s.Name + } + return s.Name +} + func StructName(name string, settings *plugin.Settings) string { if rename := settings.Rename[name]; rename != "" { return rename diff --git a/internal/codegen/golang/templates/stdlib/queryCode.tmpl b/internal/codegen/golang/templates/stdlib/queryCode.tmpl index f496d8959e..1d45e6813b 100644 --- a/internal/codegen/golang/templates/stdlib/queryCode.tmpl +++ b/internal/codegen/golang/templates/stdlib/queryCode.tmpl @@ -35,7 +35,7 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) ({{.Ret.De row := q.db.QueryRowContext(ctx, {{.ConstantName}}, {{.Arg.Params}}) {{- end}} {{- if ne .Arg.Pair .Ret.Pair }} - var {{.Ret.Name}} {{.Ret.Type}} + var {{.Ret.Name}} {{.Ret.DefineType}} {{- end}} err := row.Scan({{.Ret.Scan}}) return {{.Ret.ReturnName}}, err @@ -67,7 +67,7 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) ([]{{.Ret. var items []{{.Ret.DefineType}} {{end -}} for rows.Next() { - var {{.Ret.Name}} {{.Ret.Type}} + var {{.Ret.Name}} {{.Ret.DefineType}} if err := rows.Scan({{.Ret.Scan}}); err != nil { return nil, err } diff --git a/internal/codegen/golang/templates/template.tmpl b/internal/codegen/golang/templates/template.tmpl index b25dfabbaa..40b0aec8f8 100644 --- a/internal/codegen/golang/templates/template.tmpl +++ b/internal/codegen/golang/templates/template.tmpl @@ -33,9 +33,7 @@ package {{.Package}} import ( {{range imports .SourceName}} {{range .}}{{.}} - {{end}}{{end}}{{ if ne .ModelPackage ""}} - "{{- .ModelPackage}}" - {{end}} + {{end}}{{end}} ) {{template "interfaceCode" . }} @@ -132,9 +130,7 @@ package {{.Package}} import ( {{range imports .SourceName}} {{range .}}{{.}} - {{end}}{{end}}{{ if ne .ModelPackage ""}} - "{{- .ModelPackage}}" - {{end}} + {{end}}{{end}} ) {{template "queryCode" . }} @@ -180,9 +176,7 @@ package {{.Package}} import ( {{range imports .SourceName}} {{range .}}{{.}} - {{end}}{{end}}{{ if ne .ModelPackage ""}} - "{{- .ModelPackage}}" - {{end}} + {{end}}{{end}} ) {{template "batchCode" . }} {{end}} From 4ab65bacd55d16a0105e254d79c174883a81319a Mon Sep 17 00:00:00 2001 From: Daniel Kozlowski Date: Tue, 30 Aug 2022 07:51:59 -0700 Subject: [PATCH 5/8] Delete dependabot.yml github isn't recognizing this as a fork, so it is actively running dependabot. We don't want this as we will pull dependencies by syncing the fork with upstream. This will remove the dependabot file and stop the bot from running --- .github/dependabot.yml | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index d86c059c55..0000000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,14 +0,0 @@ -version: 2 -updates: - - package-ecosystem: "gomod" - directory: "/" - schedule: - interval: "daily" - - package-ecosystem: "docker" - directory: "/" - schedule: - interval: "daily" - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "daily" From 559dd20f3e259c17969ee9e4fd09fe76548b6292 Mon Sep 17 00:00:00 2001 From: Chris Lee Date: Wed, 7 Sep 2022 23:06:12 -0700 Subject: [PATCH 6/8] fix: prevent batch infinite loop with arg length (#1794) --- examples/batch/postgresql/batch.go | 134 +++++++++++------- examples/batch/postgresql/db_test.go | 15 +- internal/codegen/golang/imports.go | 1 + .../golang/templates/pgx/batchCode.tmpl | 104 ++++++++------ .../testdata/batch/postgresql/pgx/go/batch.go | 93 +++++++----- .../batch_imports/postgresql/pgx/go/batch.go | 70 +++++---- 6 files changed, 251 insertions(+), 166 deletions(-) diff --git a/examples/batch/postgresql/batch.go b/examples/batch/postgresql/batch.go index cb3331cb0f..4d9403920b 100644 --- a/examples/batch/postgresql/batch.go +++ b/examples/batch/postgresql/batch.go @@ -6,6 +6,7 @@ package batch import ( "context" + "errors" "time" "github.com/jackc/pgx/v4" @@ -17,8 +18,9 @@ WHERE year = $1 ` type BooksByYearBatchResults struct { - br pgx.BatchResults - ind int + br pgx.BatchResults + tot int + closed bool } func (q *Queries) BooksByYear(ctx context.Context, year []int32) *BooksByYearBatchResults { @@ -30,42 +32,51 @@ func (q *Queries) BooksByYear(ctx context.Context, year []int32) *BooksByYearBat batch.Queue(booksByYear, vals...) } br := q.db.SendBatch(ctx, batch) - return &BooksByYearBatchResults{br, 0} + return &BooksByYearBatchResults{br, len(year), false} } func (b *BooksByYearBatchResults) Query(f func(int, []Book, error)) { - for { - rows, err := b.br.Query() - if err != nil && (err.Error() == "no result" || err.Error() == "batch already closed") { - break - } - defer rows.Close() + defer b.br.Close() + for t := 0; t < b.tot; t++ { var items []Book - for rows.Next() { - var i Book - if err := rows.Scan( - &i.BookID, - &i.AuthorID, - &i.Isbn, - &i.BookType, - &i.Title, - &i.Year, - &i.Available, - &i.Tags, - ); err != nil { - break + if b.closed { + if f != nil { + f(t, items, errors.New("batch already closed")) } - items = append(items, i) + continue } - + err := func() error { + rows, err := b.br.Query() + defer rows.Close() + if err != nil { + return err + } + for rows.Next() { + var i Book + if err := rows.Scan( + &i.BookID, + &i.AuthorID, + &i.Isbn, + &i.BookType, + &i.Title, + &i.Year, + &i.Available, + &i.Tags, + ); err != nil { + return err + } + items = append(items, i) + } + return rows.Err() + }() if f != nil { - f(b.ind, items, rows.Err()) + f(t, items, err) } - b.ind++ } } func (b *BooksByYearBatchResults) Close() error { + b.closed = true return b.br.Close() } @@ -91,8 +102,9 @@ RETURNING book_id, author_id, isbn, book_type, title, year, available, tags ` type CreateBookBatchResults struct { - br pgx.BatchResults - ind int + br pgx.BatchResults + tot int + closed bool } type CreateBookParams struct { @@ -120,13 +132,20 @@ func (q *Queries) CreateBook(ctx context.Context, arg []CreateBookParams) *Creat batch.Queue(createBook, vals...) } br := q.db.SendBatch(ctx, batch) - return &CreateBookBatchResults{br, 0} + return &CreateBookBatchResults{br, len(arg), false} } func (b *CreateBookBatchResults) QueryRow(f func(int, Book, error)) { - for { - row := b.br.QueryRow() + defer b.br.Close() + for t := 0; t < b.tot; t++ { var i Book + if b.closed { + if f != nil { + f(t, i, errors.New("batch already closed")) + } + continue + } + row := b.br.QueryRow() err := row.Scan( &i.BookID, &i.AuthorID, @@ -137,17 +156,14 @@ func (b *CreateBookBatchResults) QueryRow(f func(int, Book, error)) { &i.Available, &i.Tags, ) - if err != nil && (err.Error() == "no result" || err.Error() == "batch already closed") { - break - } if f != nil { - f(b.ind, i, err) + f(t, i, err) } - b.ind++ } } func (b *CreateBookBatchResults) Close() error { + b.closed = true return b.br.Close() } @@ -157,8 +173,9 @@ WHERE book_id = $1 ` type DeleteBookBatchResults struct { - br pgx.BatchResults - ind int + br pgx.BatchResults + tot int + closed bool } func (q *Queries) DeleteBook(ctx context.Context, bookID []int32) *DeleteBookBatchResults { @@ -170,23 +187,27 @@ func (q *Queries) DeleteBook(ctx context.Context, bookID []int32) *DeleteBookBat batch.Queue(deleteBook, vals...) } br := q.db.SendBatch(ctx, batch) - return &DeleteBookBatchResults{br, 0} + return &DeleteBookBatchResults{br, len(bookID), false} } func (b *DeleteBookBatchResults) Exec(f func(int, error)) { - for { - _, err := b.br.Exec() - if err != nil && (err.Error() == "no result" || err.Error() == "batch already closed") { - break + defer b.br.Close() + for t := 0; t < b.tot; t++ { + if b.closed { + if f != nil { + f(t, errors.New("batch already closed")) + } + continue } + _, err := b.br.Exec() if f != nil { - f(b.ind, err) + f(t, err) } - b.ind++ } } func (b *DeleteBookBatchResults) Close() error { + b.closed = true return b.br.Close() } @@ -197,8 +218,9 @@ WHERE book_id = $3 ` type UpdateBookBatchResults struct { - br pgx.BatchResults - ind int + br pgx.BatchResults + tot int + closed bool } type UpdateBookParams struct { @@ -218,22 +240,26 @@ func (q *Queries) UpdateBook(ctx context.Context, arg []UpdateBookParams) *Updat batch.Queue(updateBook, vals...) } br := q.db.SendBatch(ctx, batch) - return &UpdateBookBatchResults{br, 0} + return &UpdateBookBatchResults{br, len(arg), false} } func (b *UpdateBookBatchResults) Exec(f func(int, error)) { - for { - _, err := b.br.Exec() - if err != nil && (err.Error() == "no result" || err.Error() == "batch already closed") { - break + defer b.br.Close() + for t := 0; t < b.tot; t++ { + if b.closed { + if f != nil { + f(t, errors.New("batch already closed")) + } + continue } + _, err := b.br.Exec() if f != nil { - f(b.ind, err) + f(t, err) } - b.ind++ } } func (b *UpdateBookBatchResults) Close() error { + b.closed = true return b.br.Close() } diff --git a/examples/batch/postgresql/db_test.go b/examples/batch/postgresql/db_test.go index 6293831efe..4455cfdf33 100644 --- a/examples/batch/postgresql/db_test.go +++ b/examples/batch/postgresql/db_test.go @@ -122,19 +122,24 @@ func TestBatchBooks(t *testing.T) { } batchDelete := dq.DeleteBook(ctx, deleteBooksParams) numDeletesProcessed := 0 + wantNumDeletesProcessed := 2 batchDelete.Exec(func(i int, err error) { - numDeletesProcessed++ - if err != nil { + if err != nil && err.Error() != "batch already closed" { t.Fatalf("error deleting book %d: %s", deleteBooksParams[i], err) } - if i == len(deleteBooksParams)-3 { + + if err == nil { + numDeletesProcessed++ + } + + if i == wantNumDeletesProcessed-1 { // close batch operation before processing all errors from delete operation if err := batchDelete.Close(); err != nil { t.Fatalf("failed to close batch operation: %s", err) } } }) - if numDeletesProcessed != 2 { - t.Fatalf("expected Close to short-circuit record processing (expected 2; got %d)", numDeletesProcessed) + if numDeletesProcessed != wantNumDeletesProcessed { + t.Fatalf("expected Close to short-circuit record processing (expected %d; got %d)", wantNumDeletesProcessed, numDeletesProcessed) } } diff --git a/internal/codegen/golang/imports.go b/internal/codegen/golang/imports.go index 78ea74dfbb..3a85e8bd4f 100644 --- a/internal/codegen/golang/imports.go +++ b/internal/codegen/golang/imports.go @@ -487,6 +487,7 @@ func (i *importer) batchImports(filename string) fileImports { }) std["context"] = struct{}{} + std["errors"] = struct{}{} pkg[ImportSpec{Path: "github.com/jackc/pgx/v4"}] = struct{}{} return sortedImports(std, pkg) diff --git a/internal/codegen/golang/templates/pgx/batchCode.tmpl b/internal/codegen/golang/templates/pgx/batchCode.tmpl index 511996178c..b89fa13efd 100644 --- a/internal/codegen/golang/templates/pgx/batchCode.tmpl +++ b/internal/codegen/golang/templates/pgx/batchCode.tmpl @@ -7,7 +7,8 @@ const {{.ConstantName}} = {{$.Q}}-- name: {{.MethodName}} {{.Cmd}} type {{.MethodName}}BatchResults struct { br pgx.BatchResults - ind int + tot int + closed bool } {{if .Arg.EmitStruct}} @@ -41,71 +42,86 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{ if $.EmitMethodsWithDB batch.Queue({{.ConstantName}}, vals...) } br := {{if not $.EmitMethodsWithDBArgument}}q.{{end}}db.SendBatch(ctx, batch) - return &{{.MethodName}}BatchResults{br,0} + return &{{.MethodName}}BatchResults{br,len({{.Arg.Name}}),false} } {{if eq .Cmd ":batchexec"}} func (b *{{.MethodName}}BatchResults) Exec(f func(int, error)) { - for { - _, err := b.br.Exec() - if err != nil && (err.Error() == "no result" || err.Error() == "batch already closed"){ - break - } - if f != nil { - f(b.ind, err) - } - b.ind++ - } + defer b.br.Close() + for t := 0; t < b.tot; t++ { + if b.closed { + if f != nil { + f(t, errors.New("batch already closed")) + } + continue + } + _, err := b.br.Exec() + if f != nil { + f(t, err) + } + } } {{end}} {{if eq .Cmd ":batchmany"}} func (b *{{.MethodName}}BatchResults) Query(f func(int, []{{.Ret.DefineType}}, error)) { - for { - rows, err := b.br.Query() - if err != nil && (err.Error() == "no result" || err.Error() == "batch already closed") { - break - } - defer rows.Close() - {{- if $.EmitEmptySlices}} - items := []{{.Ret.DefineType}}{} - {{else}} - var items []{{.Ret.DefineType}} - {{end -}} - for rows.Next() { - var {{.Ret.Name}} {{.Ret.DefineType}} - if err := rows.Scan({{.Ret.Scan}}); err != nil { - break - } - items = append(items, {{.Ret.ReturnName}}) - } - + defer b.br.Close() + for t := 0; t < b.tot; t++ { + {{- if $.EmitEmptySlices}} + items := []{{.Ret.DefineType}}{} + {{else}} + var items []{{.Ret.DefineType}} + {{end -}} + if b.closed { if f != nil { - f(b.ind, items, rows.Err()) + f(t, items, errors.New("batch already closed")) + } + continue + } + err := func() error { + rows, err := b.br.Query() + defer rows.Close() + if err != nil { + return err + } + for rows.Next() { + var {{.Ret.Name}} {{.Ret.Type}} + if err := rows.Scan({{.Ret.Scan}}); err != nil { + return err + } + items = append(items, {{.Ret.ReturnName}}) } - b.ind++ - } + return rows.Err() + }() + if f != nil { + f(t, items, err) + } + } } {{end}} {{if eq .Cmd ":batchone"}} func (b *{{.MethodName}}BatchResults) QueryRow(f func(int, {{.Ret.DefineType}}, error)) { - for { - row := b.br.QueryRow() - var {{.Ret.Name}} {{.Ret.DefineType}} - err := row.Scan({{.Ret.Scan}}) - if err != nil && (err.Error() == "no result" || err.Error() == "batch already closed") { - break - } + defer b.br.Close() + for t := 0; t < b.tot; t++ { + var {{.Ret.Name}} {{.Ret.Type}} + if b.closed { if f != nil { - f(b.ind, {{.Ret.ReturnName}}, err) + f(t, {{.Ret.Name}}, errors.New("batch already closed")) } - b.ind++ - } + continue + } + row := b.br.QueryRow() + err := row.Scan({{.Ret.Scan}}) + if f != nil { + f(t, {{.Ret.ReturnName}}, err) + } + } } {{end}} func (b *{{.MethodName}}BatchResults) Close() error { + b.closed = true return b.br.Close() } {{end}} diff --git a/internal/endtoend/testdata/batch/postgresql/pgx/go/batch.go b/internal/endtoend/testdata/batch/postgresql/pgx/go/batch.go index e0b5c1e017..65a8775dc0 100644 --- a/internal/endtoend/testdata/batch/postgresql/pgx/go/batch.go +++ b/internal/endtoend/testdata/batch/postgresql/pgx/go/batch.go @@ -7,6 +7,7 @@ package querytest import ( "context" "database/sql" + "errors" "github.com/jackc/pgx/v4" ) @@ -18,8 +19,9 @@ WHERE b = $1 ` type GetValuesBatchResults struct { - br pgx.BatchResults - ind int + br pgx.BatchResults + tot int + closed bool } func (q *Queries) GetValues(ctx context.Context, b []sql.NullInt32) *GetValuesBatchResults { @@ -31,33 +33,42 @@ func (q *Queries) GetValues(ctx context.Context, b []sql.NullInt32) *GetValuesBa batch.Queue(getValues, vals...) } br := q.db.SendBatch(ctx, batch) - return &GetValuesBatchResults{br, 0} + return &GetValuesBatchResults{br, len(b), false} } func (b *GetValuesBatchResults) Query(f func(int, []MyschemaFoo, error)) { - for { - rows, err := b.br.Query() - if err != nil && (err.Error() == "no result" || err.Error() == "batch already closed") { - break - } - defer rows.Close() + defer b.br.Close() + for t := 0; t < b.tot; t++ { var items []MyschemaFoo - for rows.Next() { - var i MyschemaFoo - if err := rows.Scan(&i.A, &i.B); err != nil { - break + if b.closed { + if f != nil { + f(t, items, errors.New("batch already closed")) } - items = append(items, i) + continue } - + err := func() error { + rows, err := b.br.Query() + defer rows.Close() + if err != nil { + return err + } + for rows.Next() { + var i MyschemaFoo + if err := rows.Scan(&i.A, &i.B); err != nil { + return err + } + items = append(items, i) + } + return rows.Err() + }() if f != nil { - f(b.ind, items, rows.Err()) + f(t, items, err) } - b.ind++ } } func (b *GetValuesBatchResults) Close() error { + b.closed = true return b.br.Close() } @@ -68,8 +79,9 @@ RETURNING a ` type InsertValuesBatchResults struct { - br pgx.BatchResults - ind int + br pgx.BatchResults + tot int + closed bool } type InsertValuesParams struct { @@ -87,25 +99,29 @@ func (q *Queries) InsertValues(ctx context.Context, arg []InsertValuesParams) *I batch.Queue(insertValues, vals...) } br := q.db.SendBatch(ctx, batch) - return &InsertValuesBatchResults{br, 0} + return &InsertValuesBatchResults{br, len(arg), false} } func (b *InsertValuesBatchResults) QueryRow(f func(int, sql.NullString, error)) { - for { - row := b.br.QueryRow() + defer b.br.Close() + for t := 0; t < b.tot; t++ { var a sql.NullString - err := row.Scan(&a) - if err != nil && (err.Error() == "no result" || err.Error() == "batch already closed") { - break + if b.closed { + if f != nil { + f(t, a, errors.New("batch already closed")) + } + continue } + row := b.br.QueryRow() + err := row.Scan(&a) if f != nil { - f(b.ind, a, err) + f(t, a, err) } - b.ind++ } } func (b *InsertValuesBatchResults) Close() error { + b.closed = true return b.br.Close() } @@ -114,8 +130,9 @@ UPDATE myschema.foo SET a = $1, b = $2 ` type UpdateValuesBatchResults struct { - br pgx.BatchResults - ind int + br pgx.BatchResults + tot int + closed bool } type UpdateValuesParams struct { @@ -133,22 +150,26 @@ func (q *Queries) UpdateValues(ctx context.Context, arg []UpdateValuesParams) *U batch.Queue(updateValues, vals...) } br := q.db.SendBatch(ctx, batch) - return &UpdateValuesBatchResults{br, 0} + return &UpdateValuesBatchResults{br, len(arg), false} } func (b *UpdateValuesBatchResults) Exec(f func(int, error)) { - for { - _, err := b.br.Exec() - if err != nil && (err.Error() == "no result" || err.Error() == "batch already closed") { - break + defer b.br.Close() + for t := 0; t < b.tot; t++ { + if b.closed { + if f != nil { + f(t, errors.New("batch already closed")) + } + continue } + _, err := b.br.Exec() if f != nil { - f(b.ind, err) + f(t, err) } - b.ind++ } } func (b *UpdateValuesBatchResults) Close() error { + b.closed = true return b.br.Close() } diff --git a/internal/endtoend/testdata/batch_imports/postgresql/pgx/go/batch.go b/internal/endtoend/testdata/batch_imports/postgresql/pgx/go/batch.go index c98cf42025..eb80e89f34 100644 --- a/internal/endtoend/testdata/batch_imports/postgresql/pgx/go/batch.go +++ b/internal/endtoend/testdata/batch_imports/postgresql/pgx/go/batch.go @@ -7,6 +7,7 @@ package querytest import ( "context" "database/sql" + "errors" "github.com/jackc/pgx/v4" ) @@ -18,8 +19,9 @@ WHERE b = $1 ` type GetValuesBatchResults struct { - br pgx.BatchResults - ind int + br pgx.BatchResults + tot int + closed bool } func (q *Queries) GetValues(ctx context.Context, b []sql.NullInt32) *GetValuesBatchResults { @@ -31,33 +33,42 @@ func (q *Queries) GetValues(ctx context.Context, b []sql.NullInt32) *GetValuesBa batch.Queue(getValues, vals...) } br := q.db.SendBatch(ctx, batch) - return &GetValuesBatchResults{br, 0} + return &GetValuesBatchResults{br, len(b), false} } func (b *GetValuesBatchResults) Query(f func(int, []MyschemaFoo, error)) { - for { - rows, err := b.br.Query() - if err != nil && (err.Error() == "no result" || err.Error() == "batch already closed") { - break - } - defer rows.Close() + defer b.br.Close() + for t := 0; t < b.tot; t++ { var items []MyschemaFoo - for rows.Next() { - var i MyschemaFoo - if err := rows.Scan(&i.A, &i.B); err != nil { - break + if b.closed { + if f != nil { + f(t, items, errors.New("batch already closed")) } - items = append(items, i) + continue } - + err := func() error { + rows, err := b.br.Query() + defer rows.Close() + if err != nil { + return err + } + for rows.Next() { + var i MyschemaFoo + if err := rows.Scan(&i.A, &i.B); err != nil { + return err + } + items = append(items, i) + } + return rows.Err() + }() if f != nil { - f(b.ind, items, rows.Err()) + f(t, items, err) } - b.ind++ } } func (b *GetValuesBatchResults) Close() error { + b.closed = true return b.br.Close() } @@ -68,8 +79,9 @@ RETURNING a ` type InsertValuesBatchResults struct { - br pgx.BatchResults - ind int + br pgx.BatchResults + tot int + closed bool } type InsertValuesParams struct { @@ -87,24 +99,28 @@ func (q *Queries) InsertValues(ctx context.Context, arg []InsertValuesParams) *I batch.Queue(insertValues, vals...) } br := q.db.SendBatch(ctx, batch) - return &InsertValuesBatchResults{br, 0} + return &InsertValuesBatchResults{br, len(arg), false} } func (b *InsertValuesBatchResults) QueryRow(f func(int, sql.NullString, error)) { - for { - row := b.br.QueryRow() + defer b.br.Close() + for t := 0; t < b.tot; t++ { var a sql.NullString - err := row.Scan(&a) - if err != nil && (err.Error() == "no result" || err.Error() == "batch already closed") { - break + if b.closed { + if f != nil { + f(t, a, errors.New("batch already closed")) + } + continue } + row := b.br.QueryRow() + err := row.Scan(&a) if f != nil { - f(b.ind, a, err) + f(t, a, err) } - b.ind++ } } func (b *InsertValuesBatchResults) Close() error { + b.closed = true return b.br.Close() } From 2f891db4275565374d71a03769b27b662852a9b9 Mon Sep 17 00:00:00 2001 From: "jesse.liston" Date: Thu, 29 Dec 2022 09:50:46 -0800 Subject: [PATCH 7/8] chore: Fix generated code comments --- internal/codegen/golang/templates/template.tmpl | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/codegen/golang/templates/template.tmpl b/internal/codegen/golang/templates/template.tmpl index 40b0aec8f8..805da314cd 100644 --- a/internal/codegen/golang/templates/template.tmpl +++ b/internal/codegen/golang/templates/template.tmpl @@ -171,6 +171,7 @@ import ( // versions: // sqlc {{.SqlcVersion}} // source: {{.SourceName}} + package {{.Package}} import ( From 2953ca2e08b90971a6d570f824649c56fe1ce6ad Mon Sep 17 00:00:00 2001 From: "jesse.liston" Date: Tue, 25 Apr 2023 18:31:18 -0700 Subject: [PATCH 8/8] fix: split model bug with matching package prefix and slices in model structs --- internal/codegen/golang/result.go | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/internal/codegen/golang/result.go b/internal/codegen/golang/result.go index 73bace0c7b..9a8abf2a8f 100644 --- a/internal/codegen/golang/result.go +++ b/internal/codegen/golang/result.go @@ -10,6 +10,10 @@ import ( "github.com/kyleconroy/sqlc/internal/plugin" ) +const ( + golangSliceSyntax = "[]" +) + func buildEnums(req *plugin.CodeGenRequest) []Enum { var enums []Enum for _, schema := range req.Catalog.Schemas { @@ -219,7 +223,8 @@ func buildQueries(req *plugin.CodeGenRequest, structs []Struct) ([]Query, error) for i, f := range s.Fields { c := query.Columns[i] sameName := f.Name == StructName(columnName(c, i), req.Settings) - sameType := (f.Type == goType(req, c)) || (s.Package+"."+f.Type == goType(req, c)) + + sameType := (f.Type == goType(req, c)) || (addPackagePrefixToType(s.Package, f.Type) == goType(req, c)) sameTable := sdk.SameTableName(c.Table, &s.Table, req.Catalog.DefaultSchema) if !sameName || !sameType || !sameTable { same = false @@ -266,8 +271,9 @@ func buildQueries(req *plugin.CodeGenRequest, structs []Struct) ([]Query, error) // It's possible that this method will generate duplicate JSON tag values // -// Columns: count, count, count_2 -// Fields: Count, Count_2, Count2 +// Columns: count, count, count_2 +// Fields: Count, Count_2, Count2 +// // JSON tags: count, count_2, count_2 // // This is unlikely to happen, so don't fix it yet @@ -353,3 +359,10 @@ func checkIncompatibleFieldTypes(fields []Field) error { } return nil } + +func addPackagePrefixToType(pkg string, typ string) string { + if strings.HasPrefix(typ, golangSliceSyntax) { + return golangSliceSyntax + pkg + "." + typ[len(golangSliceSyntax):] + } + return pkg + "." + typ +}