Skip to content

Commit 753f045

Browse files
Merge pull request #3 from MerlinVeritas/fix/support-enum
support enum and control whether to produce schema prefix for types
2 parents 25e4578 + b6b2eee commit 753f045

File tree

4 files changed

+59
-33
lines changed

4 files changed

+59
-33
lines changed

README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,29 @@ sql:
2020
emit_async_querier: true
2121
```
2222
23+
### Configuration Options
24+
25+
These are the supported `options` for the `py` plugin. Add them under the `codegen[].options` section of your `sqlc.yaml`.
26+
27+
- package: Module path used for imports in generated query files (e.g., `from <package> import models`).
28+
- emit_sync_querier: Emit a synchronous `Querier` class using `sqlalchemy.engine.Connection`.
29+
- emit_async_querier: Emit an asynchronous `AsyncQuerier` class using `sqlalchemy.ext.asyncio.AsyncConnection`.
30+
- emit_pydantic_models: Emit Pydantic models instead of `dataclasses` for models.py. See the section below.
31+
- emit_str_enum: Emit enums as `enum.StrEnum` (Python >=3.11). When false, emit `(str, enum.Enum)`. See the section below.
32+
- emit_schema_name_prefix: When true, prefix non-default schema to generated types to avoid name collisions. Examples:
33+
- false (default): `Book`, `BookStatus`
34+
- true: `MySchemaBook`, `MySchemaBookStatus` when the objects live in schema `my_schema`.
35+
- emit_exact_table_names: When true, do not singularize table names for model class names.
36+
- query_parameter_limit: Integer controlling when query params are grouped into a single struct argument.
37+
- If the number of parameters exceeds this value, a single `Params` struct is emitted.
38+
- Set to 0 to always emit a struct; omit or set to a large value to keep separate parameters.
39+
- inflection_exclude_table_names: A list of table names to exclude from singularization when `emit_exact_table_names` is false.
40+
- overrides: Column type overrides; see the section below.
41+
42+
Notes
43+
- out: Controlled by `codegen[].out` at the sqlc level. The plugin’s `out` option is not used; prefer the top-level `out` value.
44+
45+
2346
### Emit Pydantic Models instead of `dataclasses`
2447

2548
Option: `emit_pydantic_models`

internal/config.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package python
22

33
type OverrideColumn struct {
4-
Column string `json:"column"`
5-
PyType string `json:"py_type"`
6-
PyImport string `json:"py_import"`
4+
Column string `json:"column"`
5+
PyType string `json:"py_type"`
6+
PyImport string `json:"py_import"`
77
}
88

99
type Config struct {
@@ -14,6 +14,7 @@ type Config struct {
1414
Out string `json:"out"`
1515
EmitPydanticModels bool `json:"emit_pydantic_models"`
1616
EmitStrEnum bool `json:"emit_str_enum"`
17+
EmitSchemaNamePrefix bool `json:"emit_schema_name_prefix"`
1718
QueryParameterLimit *int32 `json:"query_parameter_limit"`
1819
InflectionExcludeTableNames []string `json:"inflection_exclude_table_names"`
1920
Overrides []OverrideColumn `json:"overrides"`

internal/gen.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -215,18 +215,18 @@ func makePyType(req *plugin.GenerateRequest, col *plugin.Column) pyType {
215215
}
216216

217217
// No override found, use the standard type mapping
218-
typ := pyInnerType(req, col)
218+
typ := pyInnerType(conf, req, col)
219219
return pyType{
220220
InnerType: typ,
221221
IsArray: col.IsArray,
222222
IsNull: !col.NotNull,
223223
}
224224
}
225225

226-
func pyInnerType(req *plugin.GenerateRequest, col *plugin.Column) string {
226+
func pyInnerType(conf Config, req *plugin.GenerateRequest, col *plugin.Column) string {
227227
switch req.Settings.Engine {
228228
case "postgresql":
229-
return postgresType(req, col)
229+
return postgresType(conf, req, col)
230230
default:
231231
log.Println("unsupported engine type")
232232
return "Any"
@@ -260,18 +260,18 @@ func pyEnumValueName(value string) string {
260260
return strings.ToUpper(id)
261261
}
262262

263-
func buildEnums(req *plugin.GenerateRequest) []Enum {
263+
func buildEnums(conf Config, req *plugin.GenerateRequest) []Enum {
264264
var enums []Enum
265265
for _, schema := range req.Catalog.Schemas {
266266
if schema.Name == "pg_catalog" || schema.Name == "information_schema" {
267267
continue
268268
}
269269
for _, enum := range schema.Enums {
270270
var enumName string
271-
if schema.Name == req.Catalog.DefaultSchema {
272-
enumName = enum.Name
273-
} else {
271+
if conf.EmitSchemaNamePrefix && schema.Name != req.Catalog.DefaultSchema {
274272
enumName = schema.Name + "_" + enum.Name
273+
} else {
274+
enumName = enum.Name
275275
}
276276
e := Enum{
277277
Name: modelName(enumName, req.Settings),
@@ -301,10 +301,10 @@ func buildModels(conf Config, req *plugin.GenerateRequest) []Struct {
301301
}
302302
for _, table := range schema.Tables {
303303
var tableName string
304-
if schema.Name == req.Catalog.DefaultSchema {
305-
tableName = table.Rel.Name
306-
} else {
304+
if conf.EmitSchemaNamePrefix && schema.Name != req.Catalog.DefaultSchema {
307305
tableName = schema.Name + "_" + table.Rel.Name
306+
} else {
307+
tableName = table.Rel.Name
308308
}
309309
structName := tableName
310310
if !conf.EmitExactTableNames {
@@ -1219,7 +1219,7 @@ func Generate(_ context.Context, req *plugin.GenerateRequest) (*plugin.GenerateR
12191219
}
12201220
}
12211221

1222-
enums := buildEnums(req)
1222+
enums := buildEnums(conf, req)
12231223
models := buildModels(conf, req)
12241224
queries, err := buildQueries(conf, req, models)
12251225
if err != nil {

internal/postgresql_type.go

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import (
77
"github.com/sqlc-dev/plugin-sdk-go/sdk"
88
)
99

10-
func postgresType(req *plugin.GenerateRequest, col *plugin.Column) string {
11-
columnType := sdk.DataType(col.Type)
10+
func postgresType(conf Config, req *plugin.GenerateRequest, col *plugin.Column) string {
11+
columnType := sdk.DataType(col.Type)
1212

1313
switch columnType {
1414
case "serial", "serial4", "pg_catalog.serial4", "bigserial", "serial8", "pg_catalog.serial8", "smallserial", "serial2", "pg_catalog.serial2", "integer", "int", "int4", "pg_catalog.int4", "bigint", "int8", "pg_catalog.int8", "smallint", "int2", "pg_catalog.int2":
@@ -42,21 +42,23 @@ func postgresType(req *plugin.GenerateRequest, col *plugin.Column) string {
4242
return "str"
4343
case "ltree", "lquery", "ltxtquery":
4444
return "str"
45-
default:
46-
for _, schema := range req.Catalog.Schemas {
47-
if schema.Name == "pg_catalog" || schema.Name == "information_schema" {
48-
continue
49-
}
50-
for _, enum := range schema.Enums {
51-
if columnType == enum.Name {
52-
if schema.Name == req.Catalog.DefaultSchema {
53-
return "models." + modelName(enum.Name, req.Settings)
54-
}
55-
return "models." + modelName(schema.Name+"_"+enum.Name, req.Settings)
56-
}
57-
}
58-
}
59-
log.Printf("unknown PostgreSQL type: %s\n", columnType)
60-
return "Any"
61-
}
45+
default:
46+
for _, schema := range req.Catalog.Schemas {
47+
if schema.Name == "pg_catalog" || schema.Name == "information_schema" {
48+
continue
49+
}
50+
for _, enum := range schema.Enums {
51+
// Match both unqualified and schema-qualified enum type names
52+
if columnType == enum.Name || columnType == schema.Name+"."+enum.Name {
53+
name := enum.Name
54+
if conf.EmitSchemaNamePrefix && schema.Name != req.Catalog.DefaultSchema {
55+
name = schema.Name + "_" + enum.Name
56+
}
57+
return "models." + modelName(name, req.Settings)
58+
}
59+
}
60+
}
61+
log.Printf("unknown PostgreSQL type: %s\n", columnType)
62+
return "Any"
63+
}
6264
}

0 commit comments

Comments
 (0)