From 77985f3cb7ca96b2b27bbc36563d9b3e02623ffa Mon Sep 17 00:00:00 2001 From: Stephen Afam-Osemene Date: Tue, 24 Sep 2024 23:27:45 +0100 Subject: [PATCH] Fix linting errors --- .golangci.yml | 2 ++ CHANGELOG.md | 8 ++++++-- dialect/mysql/table.go | 14 ++++++------- dialect/psql/table.go | 20 +++++++++---------- dialect/sqlite/table.go | 16 +++++++-------- .../models/singleton/bob_mysql_blocks.go.tpl | 4 ++-- .../models/singleton/bob_psql_blocks.go.tpl | 4 ++-- gen/bobgen-sql/driver/sql.go | 8 ++++++-- gen/bobgen-sql/main.go | 2 ++ .../models/singleton/bob_sqlite_blocks.go.tpl | 4 ++-- .../query-builder/mysql/examples/delete.md | 2 +- .../query-builder/mysql/examples/select.md | 18 +++++++++++++++++ .../query-builder/psql/examples/select.md | 18 +++++++++++++++++ .../query-builder/sqlite/examples/select.md | 18 +++++++++++++++++ website/examples_gen.go | 7 +++++-- 15 files changed, 107 insertions(+), 38 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index edef84fd..b5af5fe8 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -53,6 +53,8 @@ linters-settings: disabled: true issues: + exclude: + - G115 exclude-rules: - path: . linters: diff --git a/CHANGELOG.md b/CHANGELOG.md index 53a03ff4..e7b928f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,13 +43,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Added error constants for matching against both specific and generic unique constraint errors raised by the underlying database driver. +- Added error constants for matching against both specific and generic unique constraint errors raised by the underlying database driver. (thanks @mbezhanov) + +### Removed + +- Remove MS SQL artifacts. (thanks @mbezhanov) ### Fixed - Removed unnecessary import of `strings` in `bobfactory_random.go`. - Fixed data races in unit tests. -- Fixed invalid SQL statements generated by `sm.OrderBy().Collate()`. +- Fixed invalid SQL statements generated by `sm.OrderBy().Collate()`. (thanks @mbezhanov) ## [v0.28.1] - 2024-06-28 diff --git a/dialect/mysql/table.go b/dialect/mysql/table.go index f44ddfa7..9f5a0212 100644 --- a/dialect/mysql/table.go +++ b/dialect/mysql/table.go @@ -31,8 +31,8 @@ func NewTablex[T orm.Table, Tslice ~[]T, Tset setter[T]](tableName string, uniqu view, mappings := newView[T, Tslice](tableName) t := &Table[T, Tslice, Tset]{ - View: view, - setMapping: setMapping, + View: view, + setterMapping: setMapping, } pkCols := internal.FilterNonZero(mappings.PKs) @@ -65,8 +65,8 @@ func NewTablex[T orm.Table, Tslice ~[]T, Tset setter[T]](tableName string, uniqu // caches ??? type Table[T orm.Table, Tslice ~[]T, Tset setter[T]] struct { *View[T, Tslice] - pkExpr dialect.Expression - setMapping mappings.Mapping + pkExpr dialect.Expression + setterMapping mappings.Mapping BeforeInsertHooks orm.Hooks[[]Tset, orm.SkipModelHooksKey] AfterInsertHooks orm.Hooks[Tslice, orm.SkipModelHooksKey] @@ -159,7 +159,7 @@ func (t *Table[T, Tslice, Tset]) InsertMany(ctx context.Context, exec bob.Execut } q := Insert( - im.Into(t.Name(ctx), internal.FilterNonZero(t.setMapping.NonGenerated)...), + im.Into(t.Name(ctx), internal.FilterNonZero(t.setterMapping.NonGenerated)...), ) // To prevent unnecessary work, we will do this before we add the rows @@ -417,7 +417,7 @@ func (t *Table[T, Tslice, Tset]) uniqueSet(row Tset) ([]string, []any) { break } - colNames = append(colNames, t.setMapping.All[col]) + colNames = append(colNames, t.setterMapping.All[col]) args = append(args, field.Interface()) } @@ -432,7 +432,7 @@ func (t *Table[T, Tslice, Tset]) uniqueSet(row Tset) ([]string, []any) { // Starts an insert query for this table func (t *Table[T, Tslice, Tset]) InsertQ(ctx context.Context, exec bob.Executor, queryMods ...bob.Mod[*dialect.InsertQuery]) *TQuery[*dialect.InsertQuery, T, Tslice] { q := &TQuery[*dialect.InsertQuery, T, Tslice]{ - BaseQuery: Insert(im.Into(t.NameAs(ctx), internal.FilterNonZero(t.setMapping.NonGenerated)...)), + BaseQuery: Insert(im.Into(t.NameAs(ctx), internal.FilterNonZero(t.setterMapping.NonGenerated)...)), ctx: ctx, exec: exec, view: t.View, diff --git a/dialect/psql/table.go b/dialect/psql/table.go index aa2b8695..61a282da 100644 --- a/dialect/psql/table.go +++ b/dialect/psql/table.go @@ -30,9 +30,9 @@ func NewTablex[T orm.Table, Tslice ~[]T, Tset setter[T]](schema, tableName strin setMapping := mappings.GetMappings(reflect.TypeOf(zeroSet)) view, mappings := newView[T, Tslice](schema, tableName) t := &Table[T, Tslice, Tset]{ - View: view, - pkCols: internal.FilterNonZero(mappings.PKs), - setMapping: setMapping, + View: view, + pkCols: internal.FilterNonZero(mappings.PKs), + setterMapping: setMapping, } if len(t.pkCols) == 1 { @@ -52,9 +52,9 @@ func NewTablex[T orm.Table, Tslice ~[]T, Tset setter[T]](schema, tableName strin // caches ??? type Table[T orm.Table, Tslice ~[]T, Tset setter[T]] struct { *View[T, Tslice] - pkCols []string - pkExpr dialect.Expression - setMapping mappings.Mapping + pkCols []string + pkExpr dialect.Expression + setterMapping mappings.Mapping BeforeInsertHooks orm.Hooks[[]Tset, orm.SkipModelHooksKey] AfterInsertHooks orm.Hooks[Tslice, orm.SkipModelHooksKey] @@ -101,7 +101,7 @@ func (t *Table[T, Tslice, Tset]) InsertMany(ctx context.Context, exec bob.Execut } q := Insert( - im.Into(t.NameAs(ctx), internal.FilterNonZero(t.setMapping.NonGenerated)...), + im.Into(t.NameAs(ctx), internal.FilterNonZero(t.setterMapping.NonGenerated)...), im.Returning(t.Columns()), ) @@ -218,14 +218,14 @@ func (t *Table[T, Tslice, Tset]) UpsertMany(ctx context.Context, exec bob.Execut } // if still empty, use non-PKs if len(excludeSetCols) == 0 { - excludeSetCols = t.setMapping.NonPKs + excludeSetCols = t.setterMapping.NonPKs } conflictQM = im.OnConflict(internal.ToAnySlice(conflictCols)...). DoUpdate(im.SetExcluded(excludeSetCols...)) } q := Insert( - im.Into(t.NameAs(ctx), internal.FilterNonZero(t.setMapping.NonGenerated)...), + im.Into(t.NameAs(ctx), internal.FilterNonZero(t.setterMapping.NonGenerated)...), im.Returning(t.Columns()), conflictQM, ) @@ -289,7 +289,7 @@ func (t *Table[T, Tslice, Tset]) Delete(ctx context.Context, exec bob.Executor, // Starts an insert query for this table func (t *Table[T, Tslice, Tset]) InsertQ(ctx context.Context, exec bob.Executor, queryMods ...bob.Mod[*dialect.InsertQuery]) *TableQuery[*dialect.InsertQuery, T, Tslice] { q := &TableQuery[*dialect.InsertQuery, T, Tslice]{ - BaseQuery: Insert(im.Into(t.NameAs(ctx), internal.FilterNonZero(t.setMapping.NonGenerated)...)), + BaseQuery: Insert(im.Into(t.NameAs(ctx), internal.FilterNonZero(t.setterMapping.NonGenerated)...)), ctx: ctx, exec: exec, view: t.View, diff --git a/dialect/sqlite/table.go b/dialect/sqlite/table.go index ca7aff46..dd303855 100644 --- a/dialect/sqlite/table.go +++ b/dialect/sqlite/table.go @@ -30,9 +30,9 @@ func NewTablex[T orm.Table, Tslice ~[]T, Tset setter[T]](schema, tableName strin setMapping := mappings.GetMappings(reflect.TypeOf(zeroSet)) view, mappings := newView[T, Tslice](schema, tableName) t := &Table[T, Tslice, Tset]{ - View: view, - pkCols: internal.FilterNonZero(mappings.PKs), - setMapping: setMapping, + View: view, + pkCols: internal.FilterNonZero(mappings.PKs), + setterMapping: setMapping, } if len(t.pkCols) == 1 { @@ -52,9 +52,9 @@ func NewTablex[T orm.Table, Tslice ~[]T, Tset setter[T]](schema, tableName strin // caches ??? type Table[T orm.Table, Tslice ~[]T, Tset setter[T]] struct { *View[T, Tslice] - pkCols []string - pkExpr dialect.Expression - setMapping mappings.Mapping + pkCols []string + pkExpr dialect.Expression + setterMapping mappings.Mapping BeforeInsertHooks orm.Hooks[[]Tset, orm.SkipModelHooksKey] AfterInsertHooks orm.Hooks[Tslice, orm.SkipModelHooksKey] @@ -217,7 +217,7 @@ func (t *Table[T, Tslice, Tset]) UpsertMany(ctx context.Context, exec bob.Execut } // if still empty, use non-PKs if len(excludeSetCols) == 0 { - excludeSetCols = t.setMapping.NonPKs + excludeSetCols = t.setterMapping.NonPKs } conflictQM = im.OnConflict(internal.ToAnySlice(conflictCols)...). DoUpdate(im.SetExcluded(excludeSetCols...)) @@ -289,7 +289,7 @@ func (t *Table[T, Tslice, Tset]) Delete(ctx context.Context, exec bob.Executor, // Starts an insert query for this table func (t *Table[T, Tslice, Tset]) InsertQ(ctx context.Context, exec bob.Executor, queryMods ...bob.Mod[*dialect.InsertQuery]) *TQuery[*dialect.InsertQuery, T, Tslice] { q := &TQuery[*dialect.InsertQuery, T, Tslice]{ - BaseQuery: Insert(im.Into(t.NameAs(ctx), internal.FilterNonZero(t.setMapping.NonGenerated)...)), + BaseQuery: Insert(im.Into(t.NameAs(ctx), internal.FilterNonZero(t.setterMapping.NonGenerated)...)), ctx: ctx, exec: exec, view: t.View, diff --git a/gen/bobgen-mysql/templates/models/singleton/bob_mysql_blocks.go.tpl b/gen/bobgen-mysql/templates/models/singleton/bob_mysql_blocks.go.tpl index 908df4f7..6b3faa87 100644 --- a/gen/bobgen-mysql/templates/models/singleton/bob_mysql_blocks.go.tpl +++ b/gen/bobgen-mysql/templates/models/singleton/bob_mysql_blocks.go.tpl @@ -7,7 +7,7 @@ var ( ) {{- end -}} -{{define "unique_constraint_error_detection_method"}} +{{define "unique_constraint_error_detection_method" -}} {{$.Importer.Import "strings"}} {{$.Importer.Import "mysqlDriver" "github.com/go-sql-driver/mysql"}} func (e *errUniqueConstraint) Is(target error) bool { @@ -17,4 +17,4 @@ func (e *errUniqueConstraint) Is(target error) bool { } return err.Number == 1062 && strings.Contains(err.Message, e.s) } -{{end}} +{{- end}} diff --git a/gen/bobgen-psql/templates/models/singleton/bob_psql_blocks.go.tpl b/gen/bobgen-psql/templates/models/singleton/bob_psql_blocks.go.tpl index 29a92102..2c9ac6f6 100644 --- a/gen/bobgen-psql/templates/models/singleton/bob_psql_blocks.go.tpl +++ b/gen/bobgen-psql/templates/models/singleton/bob_psql_blocks.go.tpl @@ -1,4 +1,4 @@ -{{define "unique_constraint_error_detection_method"}} +{{define "unique_constraint_error_detection_method" -}} func (e *errUniqueConstraint) Is(target error) bool { {{$supportedDrivers := list "github.com/lib/pq" "github.com/jackc/pgx" "github.com/jackc/pgx/v4" "github.com/jackc/pgx/v5"}} {{if not (has $.DriverName $supportedDrivers)}} @@ -28,4 +28,4 @@ func (e *errUniqueConstraint) Is(target error) bool { return err.Code == "23505" && (e.s == "" || err.{{$constraintNameField}} == e.s) {{end}} } -{{end}} +{{- end}} diff --git a/gen/bobgen-sql/driver/sql.go b/gen/bobgen-sql/driver/sql.go index 0b54964d..d5699954 100644 --- a/gen/bobgen-sql/driver/sql.go +++ b/gen/bobgen-sql/driver/sql.go @@ -37,6 +37,8 @@ type Config struct { Concurrency int // Which UUID package to use (gofrs or google) UUIDPkg string `yaml:"uuid_pkg"` + // Which `database/sql` driver to use (the full module name) + DriverName string `yaml:"driver_name"` Output string Pkgname string @@ -98,6 +100,7 @@ func getPsqlDriver(ctx context.Context, config Config) (psqlDriver.Interface, er Except: config.Except, Concurrency: config.Concurrency, UUIDPkg: config.UUIDPkg, + DriverName: config.DriverName, Output: config.Output, Pkgname: config.Pkgname, NoFactory: config.NoFactory, @@ -153,8 +156,9 @@ func getSQLiteDriver(ctx context.Context, config Config) (sqliteDriver.Interface db.Close() // close early d := sqliteDriver.New(sqliteDriver.Config{ - DSN: tmp.Name(), - Attach: attach, + DSN: tmp.Name(), + Attach: attach, + DriverName: config.DriverName, SharedSchema: config.SharedSchema, Only: config.Only, diff --git a/gen/bobgen-sql/main.go b/gen/bobgen-sql/main.go index 8fd93ad9..97cca364 100644 --- a/gen/bobgen-sql/main.go +++ b/gen/bobgen-sql/main.go @@ -52,6 +52,8 @@ func run(c *cli.Context) error { var modelTemplates []fs.FS switch driverConfig.Dialect { + case "psql", "postgres": + modelTemplates = append(modelTemplates, gen.PSQLModelTemplates) case "mysql": modelTemplates = append(modelTemplates, gen.MySQLModelTemplates) case "sqlite": diff --git a/gen/bobgen-sqlite/templates/models/singleton/bob_sqlite_blocks.go.tpl b/gen/bobgen-sqlite/templates/models/singleton/bob_sqlite_blocks.go.tpl index f2d15a0d..ffb60ca4 100644 --- a/gen/bobgen-sqlite/templates/models/singleton/bob_sqlite_blocks.go.tpl +++ b/gen/bobgen-sqlite/templates/models/singleton/bob_sqlite_blocks.go.tpl @@ -23,7 +23,7 @@ func (s {{$tAlias.UpSingular}}Setter) InsertMod() bob.Mod[*dialect.InsertQuery] } {{- end}} -{{define "unique_constraint_error_detection_method"}} +{{define "unique_constraint_error_detection_method" -}} func (e *errUniqueConstraint) Is(target error) bool { {{if not (eq $.DriverName "modernc.org/sqlite" "github.com/mattn/go-sqlite3")}} return false @@ -47,4 +47,4 @@ func (e *errUniqueConstraint) Is(target error) bool { return err.{{$codeGetter}} == 2067 && strings.Contains(err.Error(), e.s) {{end}} } -{{end}} +{{- end}} diff --git a/website/docs/query-builder/mysql/examples/delete.md b/website/docs/query-builder/mysql/examples/delete.md index 762d038c..09899907 100644 --- a/website/docs/query-builder/mysql/examples/delete.md +++ b/website/docs/query-builder/mysql/examples/delete.md @@ -48,7 +48,7 @@ mysql.Delete( ) ``` -## With Limit And Offset +## With Limit And Offest SQL: diff --git a/website/docs/query-builder/mysql/examples/select.md b/website/docs/query-builder/mysql/examples/select.md index 3b884f2d..26967d6b 100644 --- a/website/docs/query-builder/mysql/examples/select.md +++ b/website/docs/query-builder/mysql/examples/select.md @@ -109,3 +109,21 @@ mysql.Select( sm.Where(mysql.Group(mysql.Quote("id"), mysql.Quote("employee_id")).In(mysql.ArgGroup(100, 200), mysql.ArgGroup(300, 400))), ) ``` + +## Select With Order By And Collate + +SQL: + +```sql +SELECT id, name FROM users ORDER BY name COLLATE utf8mb4_bg_0900_as_cs ASC +``` + +Code: + +```go +mysql.Select( + sm.Columns("id", "name"), + sm.From("users"), + sm.OrderBy("name").Collate("utf8mb4_bg_0900_as_cs").Asc(), +) +``` diff --git a/website/docs/query-builder/psql/examples/select.md b/website/docs/query-builder/psql/examples/select.md index 449d48a4..a36faedc 100644 --- a/website/docs/query-builder/psql/examples/select.md +++ b/website/docs/query-builder/psql/examples/select.md @@ -292,3 +292,21 @@ psql.Select( sm.Window("w").PartitionBy("depname").OrderBy("salary"), ) ``` + +## Select With Order By And Collate + +SQL: + +```sql +SELECT id, name FROM users ORDER BY name COLLATE "bg-BG-x-icu" ASC +``` + +Code: + +```go +psql.Select( + sm.Columns("id", "name"), + sm.From("users"), + sm.OrderBy("name").Collate("bg-BG-x-icu").Asc(), +) +``` diff --git a/website/docs/query-builder/sqlite/examples/select.md b/website/docs/query-builder/sqlite/examples/select.md index 906d9ef3..c3512de7 100644 --- a/website/docs/query-builder/sqlite/examples/select.md +++ b/website/docs/query-builder/sqlite/examples/select.md @@ -125,3 +125,21 @@ sqlite.Select( sm.Where(sqlite.Group(sqlite.Quote("id"), sqlite.Quote("employee_id")).In(sqlite.ArgGroup(100, 200), sqlite.ArgGroup(300, 400))), ) ``` + +## Select With Order By And Collate + +SQL: + +```sql +SELECT id, name FROM users ORDER BY name COLLATE NOCASE ASC +``` + +Code: + +```go +sqlite.Select( + sm.Columns("id", "name"), + sm.From("users"), + sm.OrderBy("name").Collate("NOCASE").Asc(), +) +``` diff --git a/website/examples_gen.go b/website/examples_gen.go index 06570355..b7c8f50a 100644 --- a/website/examples_gen.go +++ b/website/examples_gen.go @@ -16,6 +16,8 @@ import ( "strings" testutils "github.com/stephenafamo/bob/test/utils" + "golang.org/x/text/cases" + "golang.org/x/text/language" ) var ( @@ -24,6 +26,7 @@ var ( rgxLeadingSpaces = regexp.MustCompile(`^\s+`) // Switch from backticks to double quotes and back rgxQuoteSwitch = regexp.MustCompile(`(\x60 \+ "|" \+ \x60)`) + caser = cases.Title(language.English, cases.NoLower) //nolint:gochecknoglobals ) func main() { @@ -348,7 +351,7 @@ func toMarkdown(destination string, cases []testcase) { } if c.doc == "" { - c.doc = strings.Title(c.name) + c.doc = caser.String(c.name) } // write the sql query fmt.Fprintf(buf, "## %s\n\nSQL:\n\n```sql\n%s\n```\n\n", c.doc, c.query) @@ -380,7 +383,7 @@ func toMarkdown(destination string, cases []testcase) { func markdownTitle(s string) string { base := filepath.Base(s) heading := strings.TrimSuffix(base, filepath.Ext(base)) - return fmt.Sprintf("# %s\n\n", strings.Title(heading)) + return fmt.Sprintf("# %s\n\n", caser.String(heading)) } func reindent(s string) string {