diff --git a/internal/codegen/golang/mysql_type.go b/internal/codegen/golang/mysql_type.go index b8e8aa43c7..9364dfa1bf 100644 --- a/internal/codegen/golang/mysql_type.go +++ b/internal/codegen/golang/mysql_type.go @@ -13,6 +13,7 @@ func mysqlType(req *plugin.GenerateRequest, options *opts.Options, col *plugin.C columnType := sdk.DataType(col.Type) notNull := col.NotNull || col.IsArray unsigned := col.Unsigned + emitPointersForNull := options.EmitPointersForNullTypes switch columnType { @@ -20,6 +21,9 @@ func mysqlType(req *plugin.GenerateRequest, options *opts.Options, col *plugin.C if notNull { return "string" } + if emitPointersForNull { + return "*string" + } return "sql.NullString" case "tinyint": @@ -27,6 +31,9 @@ func mysqlType(req *plugin.GenerateRequest, options *opts.Options, col *plugin.C if notNull { return "bool" } + if emitPointersForNull { + return "*bool" + } return "sql.NullBool" } else { if notNull { @@ -35,6 +42,12 @@ func mysqlType(req *plugin.GenerateRequest, options *opts.Options, col *plugin.C } return "int8" } + if emitPointersForNull { + if unsigned { + return "*uint8" + } + return "*int8" + } // The database/sql package does not have a sql.NullInt8 type, so we // use the smallest type they have which is NullInt16 return "sql.NullInt16" @@ -44,6 +57,9 @@ func mysqlType(req *plugin.GenerateRequest, options *opts.Options, col *plugin.C if notNull { return "int16" } + if emitPointersForNull { + return "*int16" + } return "sql.NullInt16" case "smallint": @@ -53,6 +69,12 @@ func mysqlType(req *plugin.GenerateRequest, options *opts.Options, col *plugin.C } return "int16" } + if emitPointersForNull { + if unsigned { + return "*uint16" + } + return "*int16" + } return "sql.NullInt16" case "int", "integer", "mediumint": @@ -62,6 +84,12 @@ func mysqlType(req *plugin.GenerateRequest, options *opts.Options, col *plugin.C } return "int32" } + if emitPointersForNull { + if unsigned { + return "*uint32" + } + return "*int32" + } return "sql.NullInt32" case "bigint": @@ -71,6 +99,12 @@ func mysqlType(req *plugin.GenerateRequest, options *opts.Options, col *plugin.C } return "int64" } + if emitPointersForNull { + if unsigned { + return "*uint64" + } + return "*int64" + } return "sql.NullInt64" case "blob", "binary", "varbinary", "tinyblob", "mediumblob", "longblob": @@ -83,12 +117,18 @@ func mysqlType(req *plugin.GenerateRequest, options *opts.Options, col *plugin.C if notNull { return "float64" } + if emitPointersForNull { + return "*float64" + } return "sql.NullFloat64" case "decimal", "dec", "fixed": if notNull { return "string" } + if emitPointersForNull { + return "*string" + } return "sql.NullString" case "enum": @@ -99,12 +139,18 @@ func mysqlType(req *plugin.GenerateRequest, options *opts.Options, col *plugin.C if notNull { return "time.Time" } + if emitPointersForNull { + return "*time.Time" + } return "sql.NullTime" case "boolean", "bool": if notNull { return "bool" } + if emitPointersForNull { + return "*bool" + } return "sql.NullBool" case "json": diff --git a/internal/endtoend/testdata/emit_pointers_for_null_types/mysql/go/db.go b/internal/endtoend/testdata/emit_pointers_for_null_types/mysql/go/db.go new file mode 100644 index 0000000000..187de0bd03 --- /dev/null +++ b/internal/endtoend/testdata/emit_pointers_for_null_types/mysql/go/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 + +package datatype + +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/emit_pointers_for_null_types/mysql/go/models.go b/internal/endtoend/testdata/emit_pointers_for_null_types/mysql/go/models.go new file mode 100644 index 0000000000..3ec1d77af5 --- /dev/null +++ b/internal/endtoend/testdata/emit_pointers_for_null_types/mysql/go/models.go @@ -0,0 +1,73 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 + +package datatype + +type DtBoolean struct { + A *bool + B *bool + C *bool +} + +type DtBooleanNotNull struct { + A bool + B bool + C bool +} + +type DtInteger struct { + A *int8 + B *int16 + C *int32 + D *int32 + E *int32 + F *int64 +} + +type DtIntegerNotNull struct { + A int8 + B int16 + C int32 + D int32 + E int32 + F int64 +} + +type DtRealNumber struct { + A *float64 + B *float64 + C *float64 + D *float64 + E *string + F *string + G *string +} + +type DtRealNumberNotNull struct { + A float64 + B float64 + C float64 + D float64 + E string + F string + G string +} + +type DtUnsignedInteger struct { + A *uint8 + B *uint16 + C *uint32 + D *uint32 + E *uint32 + F *uint64 +} + +type DtUnsignedIntegerNotNull struct { + A uint8 + B uint16 + C uint32 + D uint32 + E uint32 + F uint64 +} diff --git a/internal/endtoend/testdata/emit_pointers_for_null_types/mysql/go/query.sql.go b/internal/endtoend/testdata/emit_pointers_for_null_types/mysql/go/query.sql.go new file mode 100644 index 0000000000..1190d84031 --- /dev/null +++ b/internal/endtoend/testdata/emit_pointers_for_null_types/mysql/go/query.sql.go @@ -0,0 +1,21 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 +// source: query.sql + +package datatype + +import ( + "context" +) + +const test = `-- name: Test :one +SELECT 1 +` + +func (q *Queries) Test(ctx context.Context) (int32, error) { + row := q.db.QueryRowContext(ctx, test) + var column_1 int32 + err := row.Scan(&column_1) + return column_1, err +} diff --git a/internal/endtoend/testdata/emit_pointers_for_null_types/mysql/sql/boolean.sql b/internal/endtoend/testdata/emit_pointers_for_null_types/mysql/sql/boolean.sql new file mode 100644 index 0000000000..8e7b1a65fa --- /dev/null +++ b/internal/endtoend/testdata/emit_pointers_for_null_types/mysql/sql/boolean.sql @@ -0,0 +1,11 @@ +CREATE table dt_boolean ( + a boolean, + b bool, + c tinyint(1) +); + +CREATE table dt_boolean_not_null ( + a boolean not null, + b bool not null, + c tinyint(1) not null +); diff --git a/internal/endtoend/testdata/emit_pointers_for_null_types/mysql/sql/integer.sql b/internal/endtoend/testdata/emit_pointers_for_null_types/mysql/sql/integer.sql new file mode 100644 index 0000000000..0d0582e9e1 --- /dev/null +++ b/internal/endtoend/testdata/emit_pointers_for_null_types/mysql/sql/integer.sql @@ -0,0 +1,36 @@ +CREATE TABLE dt_integer ( + a tinyint, + b smallint, + c int, + d integer, + e mediumint, + f bigint +); + +CREATE TABLE dt_integer_not_null ( + a tinyint not null, + b smallint not null, + c int not null, + d integer not null, + e mediumint not null, + f bigint not null +); + +CREATE TABLE dt_unsigned_integer ( + a tinyint unsigned, + b smallint unsigned, + c int unsigned, + d integer unsigned, + e mediumint unsigned, + f bigint unsigned +); + + +CREATE TABLE dt_unsigned_integer_not_null ( + a tinyint unsigned not null, + b smallint unsigned not null, + c int unsigned not null, + d integer unsigned not null, + e mediumint unsigned not null, + f bigint unsigned not null +); diff --git a/internal/endtoend/testdata/emit_pointers_for_null_types/mysql/sql/query.sql b/internal/endtoend/testdata/emit_pointers_for_null_types/mysql/sql/query.sql new file mode 100644 index 0000000000..9da604b57e --- /dev/null +++ b/internal/endtoend/testdata/emit_pointers_for_null_types/mysql/sql/query.sql @@ -0,0 +1,2 @@ +-- name: Test :one +SELECT 1; diff --git a/internal/endtoend/testdata/emit_pointers_for_null_types/mysql/sql/real_number.sql b/internal/endtoend/testdata/emit_pointers_for_null_types/mysql/sql/real_number.sql new file mode 100644 index 0000000000..351d51194d --- /dev/null +++ b/internal/endtoend/testdata/emit_pointers_for_null_types/mysql/sql/real_number.sql @@ -0,0 +1,19 @@ +CREATE TABLE dt_real_number ( + a double, + b double precision, + c real, + d float, + e decimal, + f dec, + g fixed +); + +CREATE TABLE dt_real_number_not_null ( + a double not null, + b double precision not null, + c real not null, + d float not null, + e decimal not null, + f dec not null, + g fixed not null +); diff --git a/internal/endtoend/testdata/emit_pointers_for_null_types/mysql/sqlc.json b/internal/endtoend/testdata/emit_pointers_for_null_types/mysql/sqlc.json new file mode 100644 index 0000000000..498b789ec2 --- /dev/null +++ b/internal/endtoend/testdata/emit_pointers_for_null_types/mysql/sqlc.json @@ -0,0 +1,13 @@ +{ + "version": "1", + "packages": [ + { + "path": "go", + "engine": "mysql", + "name": "datatype", + "schema": "sql/", + "queries": "sql/", + "emit_pointers_for_null_types": true + } + ] +}