diff --git a/examples/batch/postgresql/models.go b/examples/batch/postgresql/models.go index 241276effc..616552eba7 100644 --- a/examples/batch/postgresql/models.go +++ b/examples/batch/postgresql/models.go @@ -32,8 +32,8 @@ func (e *BookType) Scan(src interface{}) error { } type NullBookType struct { - BookType BookType - Valid bool // Valid is true if BookType is not NULL + BookType BookType `json:"book_type"` + Valid bool `json:"valid"` // Valid is true if BookType is not NULL } // Scan implements the Scanner interface. diff --git a/examples/ondeck/mysql/models.go b/examples/ondeck/mysql/models.go index fa9588c77b..b9a9a47f98 100644 --- a/examples/ondeck/mysql/models.go +++ b/examples/ondeck/mysql/models.go @@ -31,8 +31,8 @@ func (e *VenuesStatus) Scan(src interface{}) error { } type NullVenuesStatus struct { - VenuesStatus VenuesStatus - Valid bool // Valid is true if VenuesStatus is not NULL + VenuesStatus VenuesStatus `json:"venues_status"` + Valid bool `json:"valid"` // Valid is true if VenuesStatus is not NULL } // Scan implements the Scanner interface. diff --git a/examples/ondeck/postgresql/models.go b/examples/ondeck/postgresql/models.go index d45fa05607..d04b1ee0b7 100644 --- a/examples/ondeck/postgresql/models.go +++ b/examples/ondeck/postgresql/models.go @@ -32,8 +32,8 @@ func (e *Status) Scan(src interface{}) error { } type NullStatus struct { - Status Status - Valid bool // Valid is true if Status is not NULL + Status Status `json:"status"` + Valid bool `json:"valid"` // Valid is true if Status is not NULL } // Scan implements the Scanner interface. diff --git a/internal/codegen/golang/enum.go b/internal/codegen/golang/enum.go index c6a0d1ccbf..75291d3ace 100644 --- a/internal/codegen/golang/enum.go +++ b/internal/codegen/golang/enum.go @@ -17,6 +17,16 @@ type Enum struct { Name string Comment string Constants []Constant + NameTags map[string]string + ValidTags map[string]string +} + +func (e Enum) NameTag() string { + return TagsToString(e.NameTags) +} + +func (e Enum) ValidTag() string { + return TagsToString(e.ValidTags) } func EnumReplace(value string) string { diff --git a/internal/codegen/golang/field.go b/internal/codegen/golang/field.go index c3504c4c2b..6a8a2b6372 100644 --- a/internal/codegen/golang/field.go +++ b/internal/codegen/golang/field.go @@ -16,26 +16,30 @@ type Field struct { Tags map[string]string Comment string Column *plugin.Column - // EmbedFields contains the embedded fields that reuqire scanning. + // EmbedFields contains the embedded fields that require scanning. EmbedFields []string } func (gf Field) Tag() string { - tags := make([]string, 0, len(gf.Tags)) - for key, val := range gf.Tags { - tags = append(tags, fmt.Sprintf("%s:\"%s\"", key, val)) - } - if len(tags) == 0 { - return "" - } - sort.Strings(tags) - return strings.Join(tags, " ") + return TagsToString(gf.Tags) } func (gf Field) HasSqlcSlice() bool { return gf.Column.IsSqlcSlice } +func TagsToString(tags map[string]string) string { + if len(tags) == 0 { + return "" + } + tagParts := make([]string, 0, len(tags)) + for key, val := range tags { + tagParts = append(tagParts, fmt.Sprintf("%s:\"%s\"", key, val)) + } + sort.Strings(tagParts) + return strings.Join(tagParts, " ") +} + func JSONTagName(name string, settings *plugin.Settings) string { style := settings.Go.JsonTagsCaseStyle if style == "" || style == "none" { diff --git a/internal/codegen/golang/result.go b/internal/codegen/golang/result.go index e4b83fa868..f5ecd124a1 100644 --- a/internal/codegen/golang/result.go +++ b/internal/codegen/golang/result.go @@ -24,10 +24,18 @@ func buildEnums(req *plugin.CodeGenRequest) []Enum { } else { enumName = schema.Name + "_" + enum.Name } + e := Enum{ - Name: StructName(enumName, req.Settings), - Comment: enum.Comment, + Name: StructName(enumName, req.Settings), + Comment: enum.Comment, + NameTags: map[string]string{}, + ValidTags: map[string]string{}, + } + if req.Settings.Go.EmitJsonTags { + e.NameTags["json"] = JSONTagName(enumName, req.Settings) + e.ValidTags["json"] = JSONTagName("valid", req.Settings) } + seen := make(map[string]struct{}, len(enum.Vals)) for i, v := range enum.Vals { value := EnumReplace(v) diff --git a/internal/codegen/golang/templates/template.tmpl b/internal/codegen/golang/templates/template.tmpl index 9b730db073..519c693bc4 100644 --- a/internal/codegen/golang/templates/template.tmpl +++ b/internal/codegen/golang/templates/template.tmpl @@ -88,8 +88,8 @@ func (e *{{.Name}}) Scan(src interface{}) error { } type Null{{.Name}} struct { - {{.Name}} {{.Name}} - Valid bool // Valid is true if {{.Name}} is not NULL + {{.Name}} {{.Name}} {{if .NameTag}}{{$.Q}}{{.NameTag}}{{$.Q}}{{end}} + Valid bool {{if .ValidTag}}{{$.Q}}{{.ValidTag}}{{$.Q}}{{end}} // Valid is true if {{.Name}} is not NULL } // Scan implements the Scanner interface. diff --git a/internal/endtoend/testdata/json_tags_null_enum/camel_case/postgresql/stdlib/go/db.go b/internal/endtoend/testdata/json_tags_null_enum/camel_case/postgresql/stdlib/go/db.go new file mode 100644 index 0000000000..e0b5347fe3 --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/camel_case/postgresql/stdlib/go/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 + +package db + +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/json_tags_null_enum/camel_case/postgresql/stdlib/go/models.go b/internal/endtoend/testdata/json_tags_null_enum/camel_case/postgresql/stdlib/go/models.go new file mode 100644 index 0000000000..e2b8f9bc4a --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/camel_case/postgresql/stdlib/go/models.go @@ -0,0 +1,61 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 + +package db + +import ( + "database/sql" + "database/sql/driver" + "fmt" +) + +type JobPostLocationType string + +const ( + JobPostLocationTypeRemote JobPostLocationType = "remote" + JobPostLocationTypeInOffice JobPostLocationType = "in_office" + JobPostLocationTypeHybrid JobPostLocationType = "hybrid" +) + +func (e *JobPostLocationType) Scan(src interface{}) error { + switch s := src.(type) { + case []byte: + *e = JobPostLocationType(s) + case string: + *e = JobPostLocationType(s) + default: + return fmt.Errorf("unsupported scan type for JobPostLocationType: %T", src) + } + return nil +} + +type NullJobPostLocationType struct { + JobPostLocationType JobPostLocationType `json:"jobPostLocationType"` + Valid bool `json:"valid"` // Valid is true if JobPostLocationType is not NULL +} + +// Scan implements the Scanner interface. +func (ns *NullJobPostLocationType) Scan(value interface{}) error { + if value == nil { + ns.JobPostLocationType, ns.Valid = "", false + return nil + } + ns.Valid = true + return ns.JobPostLocationType.Scan(value) +} + +// Value implements the driver Valuer interface. +func (ns NullJobPostLocationType) Value() (driver.Value, error) { + if !ns.Valid { + return nil, nil + } + return string(ns.JobPostLocationType), nil +} + +type Author struct { + ID int64 `json:"id"` + Type NullJobPostLocationType `json:"type"` + Name string `json:"name"` + Bio sql.NullString `json:"bio"` +} diff --git a/internal/endtoend/testdata/json_tags_null_enum/camel_case/postgresql/stdlib/go/query.sql.go b/internal/endtoend/testdata/json_tags_null_enum/camel_case/postgresql/stdlib/go/query.sql.go new file mode 100644 index 0000000000..47da950842 --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/camel_case/postgresql/stdlib/go/query.sql.go @@ -0,0 +1,27 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 +// source: query.sql + +package db + +import ( + "context" +) + +const getAuthor = `-- name: GetAuthor :one +SELECT id, type, name, bio 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.Type, + &i.Name, + &i.Bio, + ) + return i, err +} diff --git a/internal/endtoend/testdata/json_tags_null_enum/camel_case/postgresql/stdlib/query.sql b/internal/endtoend/testdata/json_tags_null_enum/camel_case/postgresql/stdlib/query.sql new file mode 100644 index 0000000000..b6e9878359 --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/camel_case/postgresql/stdlib/query.sql @@ -0,0 +1,12 @@ +CREATE TYPE job_post_location_type AS ENUM('remote', 'in_office', 'hybrid'); + +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + type job_post_location_type, + name text NOT NULL, + bio text +); + +-- name: GetAuthor :one +SELECT * FROM authors +WHERE id = $1 LIMIT 1; \ No newline at end of file diff --git a/internal/endtoend/testdata/json_tags_null_enum/camel_case/postgresql/stdlib/sqlc.json b/internal/endtoend/testdata/json_tags_null_enum/camel_case/postgresql/stdlib/sqlc.json new file mode 100644 index 0000000000..9172e686fc --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/camel_case/postgresql/stdlib/sqlc.json @@ -0,0 +1,14 @@ +{ + "version": "1", + "packages": [ + { + "path": "go", + "engine": "postgresql", + "name": "db", + "schema": "query.sql", + "queries": "query.sql", + "emit_json_tags": true, + "json_tags_case_style": "camel" + } + ] +} diff --git a/internal/endtoend/testdata/json_tags_null_enum/none/postgresql/stdlib/go/db.go b/internal/endtoend/testdata/json_tags_null_enum/none/postgresql/stdlib/go/db.go new file mode 100644 index 0000000000..e0b5347fe3 --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/none/postgresql/stdlib/go/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 + +package db + +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/json_tags_null_enum/none/postgresql/stdlib/go/models.go b/internal/endtoend/testdata/json_tags_null_enum/none/postgresql/stdlib/go/models.go new file mode 100644 index 0000000000..ec72ed0d95 --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/none/postgresql/stdlib/go/models.go @@ -0,0 +1,61 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 + +package db + +import ( + "database/sql" + "database/sql/driver" + "fmt" +) + +type JobPostLocationType string + +const ( + JobPostLocationTypeRemote JobPostLocationType = "remote" + JobPostLocationTypeInOffice JobPostLocationType = "in_office" + JobPostLocationTypeHybrid JobPostLocationType = "hybrid" +) + +func (e *JobPostLocationType) Scan(src interface{}) error { + switch s := src.(type) { + case []byte: + *e = JobPostLocationType(s) + case string: + *e = JobPostLocationType(s) + default: + return fmt.Errorf("unsupported scan type for JobPostLocationType: %T", src) + } + return nil +} + +type NullJobPostLocationType struct { + JobPostLocationType JobPostLocationType `json:"job_post_location_type"` + Valid bool `json:"valid"` // Valid is true if JobPostLocationType is not NULL +} + +// Scan implements the Scanner interface. +func (ns *NullJobPostLocationType) Scan(value interface{}) error { + if value == nil { + ns.JobPostLocationType, ns.Valid = "", false + return nil + } + ns.Valid = true + return ns.JobPostLocationType.Scan(value) +} + +// Value implements the driver Valuer interface. +func (ns NullJobPostLocationType) Value() (driver.Value, error) { + if !ns.Valid { + return nil, nil + } + return string(ns.JobPostLocationType), nil +} + +type Author struct { + ID int64 `json:"id"` + Type NullJobPostLocationType `json:"type"` + Name string `json:"name"` + Bio sql.NullString `json:"bio"` +} diff --git a/internal/endtoend/testdata/json_tags_null_enum/none/postgresql/stdlib/go/query.sql.go b/internal/endtoend/testdata/json_tags_null_enum/none/postgresql/stdlib/go/query.sql.go new file mode 100644 index 0000000000..47da950842 --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/none/postgresql/stdlib/go/query.sql.go @@ -0,0 +1,27 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 +// source: query.sql + +package db + +import ( + "context" +) + +const getAuthor = `-- name: GetAuthor :one +SELECT id, type, name, bio 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.Type, + &i.Name, + &i.Bio, + ) + return i, err +} diff --git a/internal/endtoend/testdata/json_tags_null_enum/none/postgresql/stdlib/query.sql b/internal/endtoend/testdata/json_tags_null_enum/none/postgresql/stdlib/query.sql new file mode 100644 index 0000000000..b6e9878359 --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/none/postgresql/stdlib/query.sql @@ -0,0 +1,12 @@ +CREATE TYPE job_post_location_type AS ENUM('remote', 'in_office', 'hybrid'); + +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + type job_post_location_type, + name text NOT NULL, + bio text +); + +-- name: GetAuthor :one +SELECT * FROM authors +WHERE id = $1 LIMIT 1; \ No newline at end of file diff --git a/internal/endtoend/testdata/json_tags_null_enum/none/postgresql/stdlib/sqlc.json b/internal/endtoend/testdata/json_tags_null_enum/none/postgresql/stdlib/sqlc.json new file mode 100644 index 0000000000..5afd45bd23 --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/none/postgresql/stdlib/sqlc.json @@ -0,0 +1,14 @@ +{ + "version": "1", + "packages": [ + { + "path": "go", + "engine": "postgresql", + "name": "db", + "schema": "query.sql", + "queries": "query.sql", + "emit_json_tags": true, + "json_tags_case_style": "none" + } + ] +} diff --git a/internal/endtoend/testdata/json_tags_null_enum/pascal_case/postgresql/stdlib/go/db.go b/internal/endtoend/testdata/json_tags_null_enum/pascal_case/postgresql/stdlib/go/db.go new file mode 100644 index 0000000000..e0b5347fe3 --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/pascal_case/postgresql/stdlib/go/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 + +package db + +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/json_tags_null_enum/pascal_case/postgresql/stdlib/go/models.go b/internal/endtoend/testdata/json_tags_null_enum/pascal_case/postgresql/stdlib/go/models.go new file mode 100644 index 0000000000..51035306b8 --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/pascal_case/postgresql/stdlib/go/models.go @@ -0,0 +1,61 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 + +package db + +import ( + "database/sql" + "database/sql/driver" + "fmt" +) + +type JobPostLocationType string + +const ( + JobPostLocationTypeRemote JobPostLocationType = "remote" + JobPostLocationTypeInOffice JobPostLocationType = "in_office" + JobPostLocationTypeHybrid JobPostLocationType = "hybrid" +) + +func (e *JobPostLocationType) Scan(src interface{}) error { + switch s := src.(type) { + case []byte: + *e = JobPostLocationType(s) + case string: + *e = JobPostLocationType(s) + default: + return fmt.Errorf("unsupported scan type for JobPostLocationType: %T", src) + } + return nil +} + +type NullJobPostLocationType struct { + JobPostLocationType JobPostLocationType `json:"JobPostLocationType"` + Valid bool `json:"Valid"` // Valid is true if JobPostLocationType is not NULL +} + +// Scan implements the Scanner interface. +func (ns *NullJobPostLocationType) Scan(value interface{}) error { + if value == nil { + ns.JobPostLocationType, ns.Valid = "", false + return nil + } + ns.Valid = true + return ns.JobPostLocationType.Scan(value) +} + +// Value implements the driver Valuer interface. +func (ns NullJobPostLocationType) Value() (driver.Value, error) { + if !ns.Valid { + return nil, nil + } + return string(ns.JobPostLocationType), nil +} + +type Author struct { + ID int64 `json:"ID"` + Type NullJobPostLocationType `json:"Type"` + Name string `json:"Name"` + Bio sql.NullString `json:"Bio"` +} diff --git a/internal/endtoend/testdata/json_tags_null_enum/pascal_case/postgresql/stdlib/go/query.sql.go b/internal/endtoend/testdata/json_tags_null_enum/pascal_case/postgresql/stdlib/go/query.sql.go new file mode 100644 index 0000000000..47da950842 --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/pascal_case/postgresql/stdlib/go/query.sql.go @@ -0,0 +1,27 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 +// source: query.sql + +package db + +import ( + "context" +) + +const getAuthor = `-- name: GetAuthor :one +SELECT id, type, name, bio 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.Type, + &i.Name, + &i.Bio, + ) + return i, err +} diff --git a/internal/endtoend/testdata/json_tags_null_enum/pascal_case/postgresql/stdlib/query.sql b/internal/endtoend/testdata/json_tags_null_enum/pascal_case/postgresql/stdlib/query.sql new file mode 100644 index 0000000000..b6e9878359 --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/pascal_case/postgresql/stdlib/query.sql @@ -0,0 +1,12 @@ +CREATE TYPE job_post_location_type AS ENUM('remote', 'in_office', 'hybrid'); + +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + type job_post_location_type, + name text NOT NULL, + bio text +); + +-- name: GetAuthor :one +SELECT * FROM authors +WHERE id = $1 LIMIT 1; \ No newline at end of file diff --git a/internal/endtoend/testdata/json_tags_null_enum/pascal_case/postgresql/stdlib/sqlc.json b/internal/endtoend/testdata/json_tags_null_enum/pascal_case/postgresql/stdlib/sqlc.json new file mode 100644 index 0000000000..f5800af321 --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/pascal_case/postgresql/stdlib/sqlc.json @@ -0,0 +1,14 @@ +{ + "version": "1", + "packages": [ + { + "path": "go", + "engine": "postgresql", + "name": "db", + "schema": "query.sql", + "queries": "query.sql", + "emit_json_tags": true, + "json_tags_case_style": "pascal" + } + ] +} diff --git a/internal/endtoend/testdata/json_tags_null_enum/snake_case/postgresql/stdlib/go/db.go b/internal/endtoend/testdata/json_tags_null_enum/snake_case/postgresql/stdlib/go/db.go new file mode 100644 index 0000000000..e0b5347fe3 --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/snake_case/postgresql/stdlib/go/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 + +package db + +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/json_tags_null_enum/snake_case/postgresql/stdlib/go/models.go b/internal/endtoend/testdata/json_tags_null_enum/snake_case/postgresql/stdlib/go/models.go new file mode 100644 index 0000000000..ec72ed0d95 --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/snake_case/postgresql/stdlib/go/models.go @@ -0,0 +1,61 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 + +package db + +import ( + "database/sql" + "database/sql/driver" + "fmt" +) + +type JobPostLocationType string + +const ( + JobPostLocationTypeRemote JobPostLocationType = "remote" + JobPostLocationTypeInOffice JobPostLocationType = "in_office" + JobPostLocationTypeHybrid JobPostLocationType = "hybrid" +) + +func (e *JobPostLocationType) Scan(src interface{}) error { + switch s := src.(type) { + case []byte: + *e = JobPostLocationType(s) + case string: + *e = JobPostLocationType(s) + default: + return fmt.Errorf("unsupported scan type for JobPostLocationType: %T", src) + } + return nil +} + +type NullJobPostLocationType struct { + JobPostLocationType JobPostLocationType `json:"job_post_location_type"` + Valid bool `json:"valid"` // Valid is true if JobPostLocationType is not NULL +} + +// Scan implements the Scanner interface. +func (ns *NullJobPostLocationType) Scan(value interface{}) error { + if value == nil { + ns.JobPostLocationType, ns.Valid = "", false + return nil + } + ns.Valid = true + return ns.JobPostLocationType.Scan(value) +} + +// Value implements the driver Valuer interface. +func (ns NullJobPostLocationType) Value() (driver.Value, error) { + if !ns.Valid { + return nil, nil + } + return string(ns.JobPostLocationType), nil +} + +type Author struct { + ID int64 `json:"id"` + Type NullJobPostLocationType `json:"type"` + Name string `json:"name"` + Bio sql.NullString `json:"bio"` +} diff --git a/internal/endtoend/testdata/json_tags_null_enum/snake_case/postgresql/stdlib/go/query.sql.go b/internal/endtoend/testdata/json_tags_null_enum/snake_case/postgresql/stdlib/go/query.sql.go new file mode 100644 index 0000000000..47da950842 --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/snake_case/postgresql/stdlib/go/query.sql.go @@ -0,0 +1,27 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 +// source: query.sql + +package db + +import ( + "context" +) + +const getAuthor = `-- name: GetAuthor :one +SELECT id, type, name, bio 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.Type, + &i.Name, + &i.Bio, + ) + return i, err +} diff --git a/internal/endtoend/testdata/json_tags_null_enum/snake_case/postgresql/stdlib/query.sql b/internal/endtoend/testdata/json_tags_null_enum/snake_case/postgresql/stdlib/query.sql new file mode 100644 index 0000000000..b6e9878359 --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/snake_case/postgresql/stdlib/query.sql @@ -0,0 +1,12 @@ +CREATE TYPE job_post_location_type AS ENUM('remote', 'in_office', 'hybrid'); + +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + type job_post_location_type, + name text NOT NULL, + bio text +); + +-- name: GetAuthor :one +SELECT * FROM authors +WHERE id = $1 LIMIT 1; \ No newline at end of file diff --git a/internal/endtoend/testdata/json_tags_null_enum/snake_case/postgresql/stdlib/sqlc.json b/internal/endtoend/testdata/json_tags_null_enum/snake_case/postgresql/stdlib/sqlc.json new file mode 100644 index 0000000000..b078eefffa --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/snake_case/postgresql/stdlib/sqlc.json @@ -0,0 +1,14 @@ +{ + "version": "1", + "packages": [ + { + "path": "go", + "engine": "postgresql", + "name": "db", + "schema": "query.sql", + "queries": "query.sql", + "emit_json_tags": true, + "json_tags_case_style": "snake" + } + ] +} diff --git a/internal/endtoend/testdata/json_tags_null_enum/v2_config/postgresql/stdlib/go/db.go b/internal/endtoend/testdata/json_tags_null_enum/v2_config/postgresql/stdlib/go/db.go new file mode 100644 index 0000000000..e0b5347fe3 --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/v2_config/postgresql/stdlib/go/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 + +package db + +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/json_tags_null_enum/v2_config/postgresql/stdlib/go/models.go b/internal/endtoend/testdata/json_tags_null_enum/v2_config/postgresql/stdlib/go/models.go new file mode 100644 index 0000000000..ec72ed0d95 --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/v2_config/postgresql/stdlib/go/models.go @@ -0,0 +1,61 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 + +package db + +import ( + "database/sql" + "database/sql/driver" + "fmt" +) + +type JobPostLocationType string + +const ( + JobPostLocationTypeRemote JobPostLocationType = "remote" + JobPostLocationTypeInOffice JobPostLocationType = "in_office" + JobPostLocationTypeHybrid JobPostLocationType = "hybrid" +) + +func (e *JobPostLocationType) Scan(src interface{}) error { + switch s := src.(type) { + case []byte: + *e = JobPostLocationType(s) + case string: + *e = JobPostLocationType(s) + default: + return fmt.Errorf("unsupported scan type for JobPostLocationType: %T", src) + } + return nil +} + +type NullJobPostLocationType struct { + JobPostLocationType JobPostLocationType `json:"job_post_location_type"` + Valid bool `json:"valid"` // Valid is true if JobPostLocationType is not NULL +} + +// Scan implements the Scanner interface. +func (ns *NullJobPostLocationType) Scan(value interface{}) error { + if value == nil { + ns.JobPostLocationType, ns.Valid = "", false + return nil + } + ns.Valid = true + return ns.JobPostLocationType.Scan(value) +} + +// Value implements the driver Valuer interface. +func (ns NullJobPostLocationType) Value() (driver.Value, error) { + if !ns.Valid { + return nil, nil + } + return string(ns.JobPostLocationType), nil +} + +type Author struct { + ID int64 `json:"id"` + Type NullJobPostLocationType `json:"type"` + Name string `json:"name"` + Bio sql.NullString `json:"bio"` +} diff --git a/internal/endtoend/testdata/json_tags_null_enum/v2_config/postgresql/stdlib/go/query.sql.go b/internal/endtoend/testdata/json_tags_null_enum/v2_config/postgresql/stdlib/go/query.sql.go new file mode 100644 index 0000000000..47da950842 --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/v2_config/postgresql/stdlib/go/query.sql.go @@ -0,0 +1,27 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.18.0 +// source: query.sql + +package db + +import ( + "context" +) + +const getAuthor = `-- name: GetAuthor :one +SELECT id, type, name, bio 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.Type, + &i.Name, + &i.Bio, + ) + return i, err +} diff --git a/internal/endtoend/testdata/json_tags_null_enum/v2_config/postgresql/stdlib/query.sql b/internal/endtoend/testdata/json_tags_null_enum/v2_config/postgresql/stdlib/query.sql new file mode 100644 index 0000000000..b6e9878359 --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/v2_config/postgresql/stdlib/query.sql @@ -0,0 +1,12 @@ +CREATE TYPE job_post_location_type AS ENUM('remote', 'in_office', 'hybrid'); + +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + type job_post_location_type, + name text NOT NULL, + bio text +); + +-- name: GetAuthor :one +SELECT * FROM authors +WHERE id = $1 LIMIT 1; \ No newline at end of file diff --git a/internal/endtoend/testdata/json_tags_null_enum/v2_config/postgresql/stdlib/sqlc.json b/internal/endtoend/testdata/json_tags_null_enum/v2_config/postgresql/stdlib/sqlc.json new file mode 100644 index 0000000000..07cb7b9f0c --- /dev/null +++ b/internal/endtoend/testdata/json_tags_null_enum/v2_config/postgresql/stdlib/sqlc.json @@ -0,0 +1,17 @@ +{ + "version": "2", + "sql": [ + { + "schema": "query.sql", + "queries": "query.sql", + "engine": "postgresql", + "gen": { + "go": { + "out": "go", + "package": "db", + "emit_json_tags": true + } + } + } + ] +}