From 6f0803515532f31ba635a810deb3926273a34c61 Mon Sep 17 00:00:00 2001 From: Marin Bezhanov Date: Mon, 24 Jun 2024 16:39:13 +0300 Subject: [PATCH] Respect character_maximum_length when generating random values for string columns --- gen/bobgen-mysql/driver/mysql.go | 18 +++++++++++------- gen/bobgen-psql/driver/psql.go | 19 ++++++++++++------- gen/drivers/column.go | 3 +++ gen/templates/factory/03_create.go.tpl | 18 ++++++++++++------ gen/templates/factory/11_column_mods.go.tpl | 11 +++++++++-- .../singleton/bobfactory_random.go.tpl | 11 +++++++++++ 6 files changed, 58 insertions(+), 22 deletions(-) diff --git a/gen/bobgen-mysql/driver/mysql.go b/gen/bobgen-mysql/driver/mysql.go index 13fb65a0..6fd0b04f 100644 --- a/gen/bobgen-mysql/driver/mysql.go +++ b/gen/bobgen-mysql/driver/mysql.go @@ -9,6 +9,7 @@ import ( "strings" "sync" + "github.com/aarondl/opt/null" "github.com/go-sql-driver/mysql" helpers "github.com/stephenafamo/bob/gen/bobgen-helpers" "github.com/stephenafamo/bob/gen/drivers" @@ -157,6 +158,7 @@ func (d *driver) TableDetails(ctx context.Context, info drivers.TableInfo, colFi c.data_type, c.column_default, c.extra = 'auto_increment' AS autoincr, + c.character_maximum_length, c.is_nullable = 'YES' AS nullable, (c.extra = 'STORED GENERATED' OR c.extra = 'VIRTUAL GENERATED') is_generated from information_schema.columns as c @@ -188,7 +190,8 @@ func (d *driver) TableDetails(ctx context.Context, info drivers.TableInfo, colFi var colName, colFullType, colComment, colType string var autoIncr, nullable, generated bool var defaultValue *string - if err := rows.Scan(&colName, &colFullType, &colComment, &colType, &defaultValue, &autoIncr, &nullable, &generated); err != nil { + var charMaxLen null.Val[int] + if err := rows.Scan(&colName, &colFullType, &colComment, &colType, &defaultValue, &autoIncr, &charMaxLen, &nullable, &generated); err != nil { return "", "", nil, fmt.Errorf("unable to scan for table %s: %w", tableName, err) } @@ -197,12 +200,13 @@ func (d *driver) TableDetails(ctx context.Context, info drivers.TableInfo, colFi } column := drivers.Column{ - Name: colName, - Comment: colComment, - DBType: colType, - Nullable: nullable, - Generated: generated, - AutoIncr: autoIncr, + Name: colName, + Comment: colComment, + DBType: colType, + Nullable: nullable, + Generated: generated, + AutoIncr: autoIncr, + CharMaxLen: charMaxLen, } if defaultValue != nil { diff --git a/gen/bobgen-psql/driver/psql.go b/gen/bobgen-psql/driver/psql.go index 0f922506..b9184a4d 100644 --- a/gen/bobgen-psql/driver/psql.go +++ b/gen/bobgen-psql/driver/psql.go @@ -6,6 +6,7 @@ import ( "fmt" "sort" + "github.com/aarondl/opt/null" "github.com/lib/pq" helpers "github.com/stephenafamo/bob/gen/bobgen-helpers" "github.com/stephenafamo/bob/gen/drivers" @@ -230,6 +231,7 @@ func (d *driver) TableDetails(ctx context.Context, info drivers.TableInfo, colFi ) AS array_type, c.domain_name, c.column_default, + c.character_maximum_length, coalesce(col_description(('"' || c.table_schema || '"."' || c.table_name || '"')::regclass::oid, ordinal_position), '') AS column_comment, c.is_nullable = 'YES' AS is_nullable, ( @@ -288,7 +290,8 @@ func (d *driver) TableDetails(ctx context.Context, info drivers.TableInfo, colFi column_comment, is_nullable, is_generated, - is_identity + is_identity, + character_maximum_length FROM ( %s ) AS c`, tableQuery) // matviewQuery, tableQuery) @@ -325,16 +328,18 @@ func (d *driver) TableDetails(ctx context.Context, info drivers.TableInfo, colFi var colName, colType, udtSchema, udtName, comment string var defaultValue, arrayType, domainName *string var nullable, generated, identity bool - if err := rows.Scan(&colName, &colType, &udtSchema, &udtName, &arrayType, &domainName, &defaultValue, &comment, &nullable, &generated, &identity); err != nil { + var charMaxLen null.Val[int] + if err := rows.Scan(&colName, &colType, &udtSchema, &udtName, &arrayType, &domainName, &defaultValue, &comment, &nullable, &generated, &identity, &charMaxLen); err != nil { return "", "", nil, fmt.Errorf("unable to scan for table %s: %w", info.Key, err) } column := drivers.Column{ - Name: colName, - DBType: colType, - Comment: comment, - Nullable: nullable, - Generated: generated, + Name: colName, + DBType: colType, + Comment: comment, + Nullable: nullable, + Generated: generated, + CharMaxLen: charMaxLen, } info := colInfo{ UDTSchema: udtSchema, diff --git a/gen/drivers/column.go b/gen/drivers/column.go index c3e9eaf4..bf15d1b3 100644 --- a/gen/drivers/column.go +++ b/gen/drivers/column.go @@ -3,6 +3,7 @@ package drivers import ( "strings" + "github.com/aarondl/opt/null" "github.com/volatiletech/strmangle" ) @@ -21,6 +22,8 @@ type Column struct { // https://www.postgresql.org/docs/16/extend-type-system.html DomainName string `json:"domain_name" yaml:"domain_name" toml:"domain_name"` + CharMaxLen null.Val[int] `json:"char_max_len" yaml:"char_max_len" toml:"char_max_len"` + Type string `json:"type" yaml:"type" toml:"type"` } diff --git a/gen/templates/factory/03_create.go.tpl b/gen/templates/factory/03_create.go.tpl index f89435c6..15af00bc 100644 --- a/gen/templates/factory/03_create.go.tpl +++ b/gen/templates/factory/03_create.go.tpl @@ -8,14 +8,20 @@ func ensureCreatable{{$tAlias.UpSingular}}(m *models.{{$tAlias.UpSingular}}Setter) { {{range $column := $table.Columns -}} - {{- if $column.Default}}{{continue}}{{end -}} - {{- if $column.Nullable}}{{continue}}{{end -}} + {{- if $column.Default}}{{continue}}{{end -}} + {{- if $column.Nullable}}{{continue}}{{end -}} {{- if $column.Generated}}{{continue}}{{end -}} {{- $colAlias := $tAlias.Column $column.Name -}} - {{- $typDef := index $.Types $column.Type -}} - {{- $colTyp := or $typDef.AliasOf $column.Type -}} - if m.{{$colAlias}}.IsUnset() { - m.{{$colAlias}} = omit.From(random_{{normalizeType $column.Type}}(nil)) + {{- $typDef := index $.Types $column.Type -}} + {{- $colTyp := or $typDef.AliasOf $column.Type -}} + {{- $wrapStart := "" -}} + {{- $wrapEnd := "" -}} + {{- if $column.CharMaxLen.IsSet -}} + {{- $wrapStart = "truncateString(" -}} + {{- $wrapEnd = printf `,%d )` $column.CharMaxLen.GetOrZero -}} + {{- end -}} + if m.{{$colAlias}}.IsUnset() { + m.{{$colAlias}} = omit.From({{$wrapStart}}random_{{normalizeType $column.Type}}(nil){{$wrapEnd}}) } {{end -}} } diff --git a/gen/templates/factory/11_column_mods.go.tpl b/gen/templates/factory/11_column_mods.go.tpl index ab36cef6..e2d10c43 100644 --- a/gen/templates/factory/11_column_mods.go.tpl +++ b/gen/templates/factory/11_column_mods.go.tpl @@ -24,6 +24,13 @@ func (m {{$tAlias.DownSingular}}Mods) RandomizeAllColumns(f *faker.Faker) {{$tAl {{- $colTyp = printf "null.Val[%s]" $colTyp -}} {{- end -}} +{{- $wrapStart := "" -}} +{{- $wrapEnd := "" -}} +{{- if $column.CharMaxLen.IsSet -}} + {{- $wrapStart = "truncateString(" -}} + {{- $wrapEnd = printf `,%d )` $column.CharMaxLen.GetOrZero -}} +{{- end -}} + // Set the model columns to this value func (m {{$tAlias.DownSingular}}Mods) {{$colAlias}}(val {{$colTyp}}) {{$tAlias.UpSingular}}Mod { return {{$tAlias.UpSingular}}ModFunc(func(o *{{$tAlias.UpSingular}}Template) { @@ -59,9 +66,9 @@ func (m {{$tAlias.DownSingular}}Mods) Random{{$colAlias}}(f *faker.Faker) {{$tAl return null.FromPtr[{{or $typDef.AliasOf $column.Type}}](nil) } - return null.From(random_{{normalizeType $column.Type}}(f)) + return null.From({{$wrapStart}}random_{{normalizeType $column.Type}}(f){{$wrapEnd}}) {{- else -}} - return random_{{normalizeType $column.Type}}(f) + return {{$wrapStart}}random_{{normalizeType $column.Type}}(f){{$wrapEnd}} {{- end}} } }) diff --git a/gen/templates/factory/singleton/bobfactory_random.go.tpl b/gen/templates/factory/singleton/bobfactory_random.go.tpl index 723e32ff..cd2e4313 100644 --- a/gen/templates/factory/singleton/bobfactory_random.go.tpl +++ b/gen/templates/factory/singleton/bobfactory_random.go.tpl @@ -3,10 +3,12 @@ var defaultFaker = faker.New() +{{$hasCharMaxLen := false}} {{$doneTypes := dict }} {{- range $table := .Tables}} {{- $tAlias := $.Aliases.Table $table.Key}} {{range $column := $table.Columns -}} + {{- if $column.CharMaxLen -}}{{- $hasCharMaxLen = true -}}{{- end -}} {{- $colTyp := $column.Type -}} {{- if hasKey $doneTypes $column.Type}}{{continue}}{{end -}} {{- $_ := set $doneTypes $column.Type nil -}} @@ -34,3 +36,12 @@ var defaultFaker = faker.New() {{$typDef.RandomExpr}} } {{end -}} + +{{- if $hasCharMaxLen -}} +func truncateString(s string, maxLen int) string { + if len(s) > maxLen { + return s[:maxLen] + } + return s +} +{{- end -}}