diff --git a/docs/reference/config.md b/docs/reference/config.md index 96bf7fe794..a3c430744f 100644 --- a/docs/reference/config.md +++ b/docs/reference/config.md @@ -189,7 +189,7 @@ Each mapping of the `overrides` collection has the following keys: - `db_type`: - The PostgreSQL or MySQL type to override. Find the full list of supported types in [postgresql_type.go](https://github.com/kyleconroy/sqlc/blob/main/internal/codegen/golang/postgresql_type.go#L12) or [mysql_type.go](https://github.com/kyleconroy/sqlc/blob/main/internal/codegen/golang/mysql_type.go#L12). Note that for Postgres you must use the pg_catalog prefixed names where available. Can't be used if the `column` key is defined. -- `column` +- `column`: - In case the type overriding should be done on specific a column of a table instead of a type. `column` should be of the form `table.column` but you can be even more specific by specifying `schema.table.column` or `catalog.schema.table.column`. Can't be used if the `db_type` key is defined. - `go_type`: - A fully qualified name to a Go type to use in the generated code. @@ -197,9 +197,25 @@ Each mapping of the `overrides` collection has the following keys: - A reflect-style struct tag to use in the generated code, e.g. `a:"b" x:"y,z"`. If you want general json/db tags for all fields, use `emit_db_tags` and/or `emit_json_tags` instead. - `nullable`: - - If true, use this type when a column is nullable. Defaults to `false`. + - If `true`, use this type when a column is nullable. Defaults to `false`. -For more complicated import paths, the `go_type` can also be an object. +When generating code, entries using the `column` key will always have preference over +entries using the `db_type` key in order to generate the struct. + +For more complicated import paths, the `go_type` can also be an object with the following keys: + +- `import`: + - The import path for the package where the type is defined. +- `package`: + - The package name where the type is defined. This should only be necessary when your import path doesn't end with the desired package name. +- `type`: + - The type name itself, without any package prefix. +- `pointer`: + - If set to `true`, generated code will use pointers to the type rather than the type itself. +- `slice`: + - If set to `true`, generated code will use a slice of the type rather than the type itself. + +An example: ```yaml version: "2" @@ -220,9 +236,6 @@ sql: pointer: true ``` -When generating code, entries using the `column` key will always have preference over -entries using the `db_type` key in order to generate the struct. - #### kotlin > Removed in v1.17.0 and replaced by the [sqlc-gen-kotlin](https://github.com/tabbed/sqlc-gen-kotlin) plugin. Follow the [migration guide](../guides/migrating-to-sqlc-gen-kotlin) to switch. diff --git a/internal/cmd/shim.go b/internal/cmd/shim.go index 838d344cc3..a616cbc02e 100644 --- a/internal/cmd/shim.go +++ b/internal/cmd/shim.go @@ -114,7 +114,7 @@ func pluginGoType(o config.Override) *plugin.ParsedGoType { // Note that there is a slight mismatch between this and the // proto api. The GoType on the override is the unparsed type, // which could be a qualified path or an object, as per - // https://docs.sqlc.dev/en/latest/reference/config.html#renaming-struct-fields + // https://docs.sqlc.dev/en/v1.18.0/reference/config.html#type-overriding return &plugin.ParsedGoType{ ImportPath: o.GoImportPath, Package: o.GoPackage, diff --git a/internal/codegen/golang/imports.go b/internal/codegen/golang/imports.go index 3ec00432a2..083762b1d9 100644 --- a/internal/codegen/golang/imports.go +++ b/internal/codegen/golang/imports.go @@ -257,9 +257,7 @@ func (i *importer) interfaceImports() fileImports { } func (i *importer) modelImports() fileImports { - std, pkg := buildImports(i.Settings, nil, func(prefix string) bool { - return i.usesType(prefix) - }) + std, pkg := buildImports(i.Settings, nil, i.usesType) if len(i.Enums) > 0 { std["fmt"] = struct{}{} diff --git a/internal/config/go_type.go b/internal/config/go_type.go index 7ed266a9fc..078360e57d 100644 --- a/internal/config/go_type.go +++ b/internal/config/go_type.go @@ -13,6 +13,7 @@ type GoType struct { Package string `json:"package" yaml:"package"` Name string `json:"type" yaml:"type"` Pointer bool `json:"pointer" yaml:"pointer"` + Slice bool `json:"slice" yaml:"slice"` Spec string BuiltIn bool } @@ -104,6 +105,9 @@ func (gt GoType) Parse() (*ParsedGoType, error) { if gt.Pointer { o.TypeName = "*" + o.TypeName } + if gt.Slice { + o.TypeName = "[]" + o.TypeName + } return &o, nil } diff --git a/internal/endtoend/testdata/overrides_array/postgresql/pgx/v4/query.sql b/internal/endtoend/testdata/overrides_array/postgresql/pgx/v4/query.sql new file mode 100644 index 0000000000..bd444c6987 --- /dev/null +++ b/internal/endtoend/testdata/overrides_array/postgresql/pgx/v4/query.sql @@ -0,0 +1,11 @@ +-- Example queries for sqlc +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + name text NOT NULL, + bio text, + tags string[] +); + +-- name: GetAuthor :one +SELECT * FROM authors +WHERE id = $1 LIMIT 1; \ No newline at end of file diff --git a/internal/endtoend/testdata/overrides_array/postgresql/pgx/v4/query/db.go b/internal/endtoend/testdata/overrides_array/postgresql/pgx/v4/query/db.go new file mode 100644 index 0000000000..a3a4e5f7fd --- /dev/null +++ b/internal/endtoend/testdata/overrides_array/postgresql/pgx/v4/query/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 + +package query + +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/internal/endtoend/testdata/overrides_array/postgresql/pgx/v4/query/models.go b/internal/endtoend/testdata/overrides_array/postgresql/pgx/v4/query/models.go new file mode 100644 index 0000000000..7804374211 --- /dev/null +++ b/internal/endtoend/testdata/overrides_array/postgresql/pgx/v4/query/models.go @@ -0,0 +1,16 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 + +package query + +import ( + "database/sql" +) + +type Author struct { + ID int64 + Name string + Bio sql.NullString + Tags []sql.NullInt64 +} diff --git a/internal/endtoend/testdata/overrides_array/postgresql/pgx/v4/query/query.sql.go b/internal/endtoend/testdata/overrides_array/postgresql/pgx/v4/query/query.sql.go new file mode 100644 index 0000000000..1f59eff9f6 --- /dev/null +++ b/internal/endtoend/testdata/overrides_array/postgresql/pgx/v4/query/query.sql.go @@ -0,0 +1,27 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 +// source: query.sql + +package query + +import ( + "context" +) + +const getAuthor = `-- name: GetAuthor :one +SELECT id, name, bio, tags FROM authors +WHERE id = $1 LIMIT 1 +` + +func (q *Queries) GetAuthor(ctx context.Context, id int64) (Author, error) { + row := q.db.QueryRow(ctx, getAuthor, id) + var i Author + err := row.Scan( + &i.ID, + &i.Name, + &i.Bio, + &i.Tags, + ) + return i, err +} diff --git a/internal/endtoend/testdata/overrides_array/postgresql/pgx/v4/sqlc.json b/internal/endtoend/testdata/overrides_array/postgresql/pgx/v4/sqlc.json new file mode 100644 index 0000000000..ca45f06cab --- /dev/null +++ b/internal/endtoend/testdata/overrides_array/postgresql/pgx/v4/sqlc.json @@ -0,0 +1,23 @@ +{ + "version": "2", + "sql": [{ + "schema": "query.sql", + "queries": "query.sql", + "engine": "postgresql", + "gen": { + "go": { + "sql_package": "pgx/v4", + "package": "query", + "out": "query", + "overrides": [{ + "column": "authors.tags", + "go_type": { + "type": "NullInt64", + "import": "database/sql", + "slice": true + } + }] + } + } + }] +} \ No newline at end of file diff --git a/internal/endtoend/testdata/overrides_array/postgresql/pgx/v5/query.sql b/internal/endtoend/testdata/overrides_array/postgresql/pgx/v5/query.sql new file mode 100644 index 0000000000..bd444c6987 --- /dev/null +++ b/internal/endtoend/testdata/overrides_array/postgresql/pgx/v5/query.sql @@ -0,0 +1,11 @@ +-- Example queries for sqlc +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + name text NOT NULL, + bio text, + tags string[] +); + +-- name: GetAuthor :one +SELECT * FROM authors +WHERE id = $1 LIMIT 1; \ No newline at end of file diff --git a/internal/endtoend/testdata/overrides_array/postgresql/pgx/v5/query/db.go b/internal/endtoend/testdata/overrides_array/postgresql/pgx/v5/query/db.go new file mode 100644 index 0000000000..10fd0cb8ec --- /dev/null +++ b/internal/endtoend/testdata/overrides_array/postgresql/pgx/v5/query/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 + +package query + +import ( + "context" + + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgconn" +) + +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/internal/endtoend/testdata/overrides_array/postgresql/pgx/v5/query/models.go b/internal/endtoend/testdata/overrides_array/postgresql/pgx/v5/query/models.go new file mode 100644 index 0000000000..cddc9c15ea --- /dev/null +++ b/internal/endtoend/testdata/overrides_array/postgresql/pgx/v5/query/models.go @@ -0,0 +1,18 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 + +package query + +import ( + "database/sql" + + "github.com/jackc/pgx/v5/pgtype" +) + +type Author struct { + ID int64 + Name string + Bio pgtype.Text + Tags []sql.NullInt64 +} diff --git a/internal/endtoend/testdata/overrides_array/postgresql/pgx/v5/query/query.sql.go b/internal/endtoend/testdata/overrides_array/postgresql/pgx/v5/query/query.sql.go new file mode 100644 index 0000000000..1f59eff9f6 --- /dev/null +++ b/internal/endtoend/testdata/overrides_array/postgresql/pgx/v5/query/query.sql.go @@ -0,0 +1,27 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 +// source: query.sql + +package query + +import ( + "context" +) + +const getAuthor = `-- name: GetAuthor :one +SELECT id, name, bio, tags FROM authors +WHERE id = $1 LIMIT 1 +` + +func (q *Queries) GetAuthor(ctx context.Context, id int64) (Author, error) { + row := q.db.QueryRow(ctx, getAuthor, id) + var i Author + err := row.Scan( + &i.ID, + &i.Name, + &i.Bio, + &i.Tags, + ) + return i, err +} diff --git a/internal/endtoend/testdata/overrides_array/postgresql/pgx/v5/sqlc.json b/internal/endtoend/testdata/overrides_array/postgresql/pgx/v5/sqlc.json new file mode 100644 index 0000000000..f43f1b43ec --- /dev/null +++ b/internal/endtoend/testdata/overrides_array/postgresql/pgx/v5/sqlc.json @@ -0,0 +1,23 @@ +{ + "version": "2", + "sql": [{ + "schema": "query.sql", + "queries": "query.sql", + "engine": "postgresql", + "gen": { + "go": { + "sql_package": "pgx/v5", + "package": "query", + "out": "query", + "overrides": [{ + "column": "authors.tags", + "go_type": { + "type": "NullInt64", + "import": "database/sql", + "slice": true + } + }] + } + } + }] + } \ No newline at end of file diff --git a/internal/endtoend/testdata/overrides_array/postgresql/stdlib/query.sql b/internal/endtoend/testdata/overrides_array/postgresql/stdlib/query.sql new file mode 100644 index 0000000000..bd444c6987 --- /dev/null +++ b/internal/endtoend/testdata/overrides_array/postgresql/stdlib/query.sql @@ -0,0 +1,11 @@ +-- Example queries for sqlc +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + name text NOT NULL, + bio text, + tags string[] +); + +-- name: GetAuthor :one +SELECT * FROM authors +WHERE id = $1 LIMIT 1; \ No newline at end of file diff --git a/internal/endtoend/testdata/overrides_array/postgresql/stdlib/query/db.go b/internal/endtoend/testdata/overrides_array/postgresql/stdlib/query/db.go new file mode 100644 index 0000000000..2d7b74d9e1 --- /dev/null +++ b/internal/endtoend/testdata/overrides_array/postgresql/stdlib/query/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 + +package query + +import ( + "context" + "database/sql" +) + +type DBTX interface { + ExecContext(context.Context, string, ...interface{}) (sql.Result, error) + PrepareContext(context.Context, string) (*sql.Stmt, error) + QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) + QueryRowContext(context.Context, string, ...interface{}) *sql.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx *sql.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/internal/endtoend/testdata/overrides_array/postgresql/stdlib/query/models.go b/internal/endtoend/testdata/overrides_array/postgresql/stdlib/query/models.go new file mode 100644 index 0000000000..7804374211 --- /dev/null +++ b/internal/endtoend/testdata/overrides_array/postgresql/stdlib/query/models.go @@ -0,0 +1,16 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 + +package query + +import ( + "database/sql" +) + +type Author struct { + ID int64 + Name string + Bio sql.NullString + Tags []sql.NullInt64 +} diff --git a/internal/endtoend/testdata/overrides_array/postgresql/stdlib/query/query.sql.go b/internal/endtoend/testdata/overrides_array/postgresql/stdlib/query/query.sql.go new file mode 100644 index 0000000000..e4c63e0e67 --- /dev/null +++ b/internal/endtoend/testdata/overrides_array/postgresql/stdlib/query/query.sql.go @@ -0,0 +1,29 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 +// source: query.sql + +package query + +import ( + "context" + + "github.com/lib/pq" +) + +const getAuthor = `-- name: GetAuthor :one +SELECT id, name, bio, tags FROM authors +WHERE id = $1 LIMIT 1 +` + +func (q *Queries) GetAuthor(ctx context.Context, id int64) (Author, error) { + row := q.db.QueryRowContext(ctx, getAuthor, id) + var i Author + err := row.Scan( + &i.ID, + &i.Name, + &i.Bio, + pq.Array(&i.Tags), + ) + return i, err +} diff --git a/internal/endtoend/testdata/overrides_array/postgresql/stdlib/sqlc.json b/internal/endtoend/testdata/overrides_array/postgresql/stdlib/sqlc.json new file mode 100644 index 0000000000..d1f756add5 --- /dev/null +++ b/internal/endtoend/testdata/overrides_array/postgresql/stdlib/sqlc.json @@ -0,0 +1,22 @@ +{ + "version": "2", + "sql": [{ + "schema": "query.sql", + "queries": "query.sql", + "engine": "postgresql", + "gen": { + "go": { + "package": "query", + "out": "query", + "overrides": [{ + "column": "authors.tags", + "go_type": { + "type": "NullInt64", + "import": "database/sql", + "slice": true + } + }] + } + } + }] + } \ No newline at end of file