Skip to content

Commit 9d9026b

Browse files
authored
Emit pointers for nullable enum columns when emit_pointers_for_null_types is set (#4388)
1 parent 64d18fc commit 9d9026b

File tree

31 files changed

+784
-110
lines changed

31 files changed

+784
-110
lines changed

docs/reference/config.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,9 @@ The `gen` mapping supports the following keys:
158158
- `emit_methods_with_db_argument`:
159159
- If true, generated methods will accept a DBTX argument instead of storing a DBTX on the `*Queries` struct. Defaults to `false`.
160160
- `emit_pointers_for_null_types`:
161-
- If true, generated types for nullable columns are emitted as pointers (ie. `*string`) instead of `database/sql` null types (ie. `NullString`). Currently only supported for PostgreSQL if `sql_package` is `pgx/v4` or `pgx/v5`, and for SQLite. Defaults to `false`.
161+
- If true, generated types for nullable columns are emitted as pointers (ie. `*string`) instead of `database/sql` null types (ie. `NullString`). Currently only supported for PostgreSQL if `sql_package` is `pgx/v4` or `pgx/v5`, and for SQLite. Defaults to `false`. Nullable enum columns also follow this setting unless `emit_pointers_for_null_enum_types` is set.
162+
- `emit_pointers_for_null_enum_types`:
163+
- Overrides `emit_pointers_for_null_types` for nullable enum columns only. When `true`, nullable enum columns are emitted as pointers (ie. `*UserRole`). When `false`, nullable enum columns use the generated `NullUserRole` wrapper struct even if `emit_pointers_for_null_types` is true. Set this to `false` to keep the pre-v1.31 behavior when upgrading. Only applies to PostgreSQL with `sql_package` `pgx/v4` or `pgx/v5`.
162164
- `emit_enum_valid_method`:
163165
- If true, generate a Valid method on enum types,
164166
indicating whether a string is a valid enum value.
@@ -441,7 +443,9 @@ Each mapping in the `packages` collection has the following keys:
441443
- `emit_methods_with_db_argument`:
442444
- If true, generated methods will accept a DBTX argument instead of storing a DBTX on the `*Queries` struct. Defaults to `false`.
443445
- `emit_pointers_for_null_types`:
444-
- If true and `sql_package` is set to `pgx/v4` or `pgx/v5`, generated types for nullable columns are emitted as pointers (ie. `*string`) instead of `database/sql` null types (ie. `NullString`). Defaults to `false`.
446+
- If true and `sql_package` is set to `pgx/v4` or `pgx/v5`, generated types for nullable columns are emitted as pointers (ie. `*string`) instead of `database/sql` null types (ie. `NullString`). Defaults to `false`. Nullable enum columns also follow this setting unless `emit_pointers_for_null_enum_types` is set.
447+
- `emit_pointers_for_null_enum_types`:
448+
- Overrides `emit_pointers_for_null_types` for nullable enum columns only. When `true`, nullable enum columns are emitted as pointers (ie. `*UserRole`). When `false`, nullable enum columns use the generated `NullUserRole` wrapper struct even if `emit_pointers_for_null_types` is true. Set this to `false` to keep the pre-v1.31 behavior when upgrading. Only applies to PostgreSQL with `sql_package` `pgx/v4` or `pgx/v5`.
445449
- `emit_enum_valid_method`:
446450
- If true, generate a Valid method on enum types,
447451
indicating whether a string is a valid enum value.

internal/codegen/golang/gen.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,8 @@ func filterUnusedStructs(enums []Enum, structs []Struct, queries []Query) ([]Enu
396396
for _, enum := range enums {
397397
_, keep := keepTypes[enum.Name]
398398
_, keepNull := keepTypes["Null"+enum.Name]
399-
if keep || keepNull {
399+
_, keepPointer := keepTypes["*"+enum.Name]
400+
if keep || keepNull || keepPointer {
400401
keepEnums = append(keepEnums, enum)
401402
}
402403
}

internal/codegen/golang/opts/options.go

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -10,41 +10,43 @@ import (
1010
)
1111

1212
type Options struct {
13-
EmitInterface bool `json:"emit_interface" yaml:"emit_interface"`
14-
EmitJsonTags bool `json:"emit_json_tags" yaml:"emit_json_tags"`
15-
JsonTagsIdUppercase bool `json:"json_tags_id_uppercase" yaml:"json_tags_id_uppercase"`
16-
EmitDbTags bool `json:"emit_db_tags" yaml:"emit_db_tags"`
17-
EmitPreparedQueries bool `json:"emit_prepared_queries" yaml:"emit_prepared_queries"`
18-
EmitExactTableNames bool `json:"emit_exact_table_names,omitempty" yaml:"emit_exact_table_names"`
19-
EmitEmptySlices bool `json:"emit_empty_slices,omitempty" yaml:"emit_empty_slices"`
20-
EmitExportedQueries bool `json:"emit_exported_queries" yaml:"emit_exported_queries"`
21-
EmitResultStructPointers bool `json:"emit_result_struct_pointers" yaml:"emit_result_struct_pointers"`
22-
EmitParamsStructPointers bool `json:"emit_params_struct_pointers" yaml:"emit_params_struct_pointers"`
23-
EmitMethodsWithDbArgument bool `json:"emit_methods_with_db_argument,omitempty" yaml:"emit_methods_with_db_argument"`
24-
EmitPointersForNullTypes bool `json:"emit_pointers_for_null_types" yaml:"emit_pointers_for_null_types"`
25-
EmitEnumValidMethod bool `json:"emit_enum_valid_method,omitempty" yaml:"emit_enum_valid_method"`
26-
EmitAllEnumValues bool `json:"emit_all_enum_values,omitempty" yaml:"emit_all_enum_values"`
27-
EmitSqlAsComment bool `json:"emit_sql_as_comment,omitempty" yaml:"emit_sql_as_comment"`
28-
JsonTagsCaseStyle string `json:"json_tags_case_style,omitempty" yaml:"json_tags_case_style"`
29-
Package string `json:"package" yaml:"package"`
30-
Out string `json:"out" yaml:"out"`
31-
Overrides []Override `json:"overrides,omitempty" yaml:"overrides"`
32-
Rename map[string]string `json:"rename,omitempty" yaml:"rename"`
33-
SqlPackage string `json:"sql_package" yaml:"sql_package"`
34-
SqlDriver string `json:"sql_driver" yaml:"sql_driver"`
35-
OutputBatchFileName string `json:"output_batch_file_name,omitempty" yaml:"output_batch_file_name"`
36-
OutputDbFileName string `json:"output_db_file_name,omitempty" yaml:"output_db_file_name"`
37-
OutputModelsFileName string `json:"output_models_file_name,omitempty" yaml:"output_models_file_name"`
38-
OutputQuerierFileName string `json:"output_querier_file_name,omitempty" yaml:"output_querier_file_name"`
39-
OutputCopyfromFileName string `json:"output_copyfrom_file_name,omitempty" yaml:"output_copyfrom_file_name"`
40-
OutputFilesSuffix string `json:"output_files_suffix,omitempty" yaml:"output_files_suffix"`
41-
InflectionExcludeTableNames []string `json:"inflection_exclude_table_names,omitempty" yaml:"inflection_exclude_table_names"`
42-
WrapErrors bool `json:"wrap_errors,omitempty" yaml:"wrap_errors"`
43-
QueryParameterLimit *int32 `json:"query_parameter_limit,omitempty" yaml:"query_parameter_limit"`
44-
OmitSqlcVersion bool `json:"omit_sqlc_version,omitempty" yaml:"omit_sqlc_version"`
45-
OmitUnusedStructs bool `json:"omit_unused_structs,omitempty" yaml:"omit_unused_structs"`
46-
BuildTags string `json:"build_tags,omitempty" yaml:"build_tags"`
47-
Initialisms *[]string `json:"initialisms,omitempty" yaml:"initialisms"`
13+
EmitInterface bool `json:"emit_interface" yaml:"emit_interface"`
14+
EmitJsonTags bool `json:"emit_json_tags" yaml:"emit_json_tags"`
15+
JsonTagsIdUppercase bool `json:"json_tags_id_uppercase" yaml:"json_tags_id_uppercase"`
16+
EmitDbTags bool `json:"emit_db_tags" yaml:"emit_db_tags"`
17+
EmitPreparedQueries bool `json:"emit_prepared_queries" yaml:"emit_prepared_queries"`
18+
EmitExactTableNames bool `json:"emit_exact_table_names,omitempty" yaml:"emit_exact_table_names"`
19+
EmitEmptySlices bool `json:"emit_empty_slices,omitempty" yaml:"emit_empty_slices"`
20+
EmitExportedQueries bool `json:"emit_exported_queries" yaml:"emit_exported_queries"`
21+
EmitResultStructPointers bool `json:"emit_result_struct_pointers" yaml:"emit_result_struct_pointers"`
22+
EmitParamsStructPointers bool `json:"emit_params_struct_pointers" yaml:"emit_params_struct_pointers"`
23+
EmitMethodsWithDbArgument bool `json:"emit_methods_with_db_argument,omitempty" yaml:"emit_methods_with_db_argument"`
24+
EmitPointersForNullTypes bool `json:"emit_pointers_for_null_types" yaml:"emit_pointers_for_null_types"`
25+
// nil inherits EmitPointersForNullTypes; non-nil overrides for enums only.
26+
EmitPointersForNullEnumTypes *bool `json:"emit_pointers_for_null_enum_types,omitempty" yaml:"emit_pointers_for_null_enum_types"`
27+
EmitEnumValidMethod bool `json:"emit_enum_valid_method,omitempty" yaml:"emit_enum_valid_method"`
28+
EmitAllEnumValues bool `json:"emit_all_enum_values,omitempty" yaml:"emit_all_enum_values"`
29+
EmitSqlAsComment bool `json:"emit_sql_as_comment,omitempty" yaml:"emit_sql_as_comment"`
30+
JsonTagsCaseStyle string `json:"json_tags_case_style,omitempty" yaml:"json_tags_case_style"`
31+
Package string `json:"package" yaml:"package"`
32+
Out string `json:"out" yaml:"out"`
33+
Overrides []Override `json:"overrides,omitempty" yaml:"overrides"`
34+
Rename map[string]string `json:"rename,omitempty" yaml:"rename"`
35+
SqlPackage string `json:"sql_package" yaml:"sql_package"`
36+
SqlDriver string `json:"sql_driver" yaml:"sql_driver"`
37+
OutputBatchFileName string `json:"output_batch_file_name,omitempty" yaml:"output_batch_file_name"`
38+
OutputDbFileName string `json:"output_db_file_name,omitempty" yaml:"output_db_file_name"`
39+
OutputModelsFileName string `json:"output_models_file_name,omitempty" yaml:"output_models_file_name"`
40+
OutputQuerierFileName string `json:"output_querier_file_name,omitempty" yaml:"output_querier_file_name"`
41+
OutputCopyfromFileName string `json:"output_copyfrom_file_name,omitempty" yaml:"output_copyfrom_file_name"`
42+
OutputFilesSuffix string `json:"output_files_suffix,omitempty" yaml:"output_files_suffix"`
43+
InflectionExcludeTableNames []string `json:"inflection_exclude_table_names,omitempty" yaml:"inflection_exclude_table_names"`
44+
WrapErrors bool `json:"wrap_errors,omitempty" yaml:"wrap_errors"`
45+
QueryParameterLimit *int32 `json:"query_parameter_limit,omitempty" yaml:"query_parameter_limit"`
46+
OmitSqlcVersion bool `json:"omit_sqlc_version,omitempty" yaml:"omit_sqlc_version"`
47+
OmitUnusedStructs bool `json:"omit_unused_structs,omitempty" yaml:"omit_unused_structs"`
48+
BuildTags string `json:"build_tags,omitempty" yaml:"build_tags"`
49+
Initialisms *[]string `json:"initialisms,omitempty" yaml:"initialisms"`
4850

4951
InitialismsMap map[string]struct{} `json:"-" yaml:"-"`
5052
}

internal/codegen/golang/postgresql_type.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ func postgresType(req *plugin.GenerateRequest, options *opts.Options, col *plugi
3939
notNull := col.NotNull || col.IsArray
4040
driver := parseDriver(options.SqlPackage)
4141
emitPointersForNull := driver.IsPGX() && options.EmitPointersForNullTypes
42+
emitPointersForNullEnums := emitPointersForNull
43+
if options.EmitPointersForNullEnumTypes != nil {
44+
emitPointersForNullEnums = driver.IsPGX() && *options.EmitPointersForNullEnumTypes
45+
}
4246

4347
switch columnType {
4448
case "serial", "serial4", "pg_catalog.serial4":
@@ -582,10 +586,14 @@ func postgresType(req *plugin.GenerateRequest, options *opts.Options, col *plugi
582586
}
583587
return StructName(schema.Name+"_"+enum.Name, options)
584588
} else {
589+
nullPrefix := "Null"
590+
if emitPointersForNullEnums {
591+
nullPrefix = "*"
592+
}
585593
if schema.Name == req.Catalog.DefaultSchema {
586-
return "Null" + StructName(enum.Name, options)
594+
return nullPrefix + StructName(enum.Name, options)
587595
}
588-
return "Null" + StructName(schema.Name+"_"+enum.Name, options)
596+
return nullPrefix + StructName(schema.Name+"_"+enum.Name, options)
589597
}
590598
}
591599
}

0 commit comments

Comments
 (0)