Skip to content

Releases: stephenafamo/bob

v0.29.0

20 Nov 13:16
Compare
Choose a tag to compare

Added

  • Added error constants for matching against both specific and generic unique constraint errors raised by the underlying database driver. (thanks @mbezhanov)
  • Added support for regular expressions in the only and except table filters. (thanks @mbezhanov)
  • Added ContextualMods which are similar to regular mods but take a context argument. They are applied whenever the query is built.
    This makes it cleaner to do certain things, like populating the select columns of a model if none was explicitly added.
    The previous way this was done was unreliable since using q.MustBuild() would not add the columns while bob.MustBuild(q) will add them correctly.
  • modelSlice.UpdateMod() and modelSlice.DeleteMod() are new methods that returns a mod for update and delete queries on a slice of models.
    It adds WHERE pk IN (pk1, pk2, pk3, ...) to the query, and also schedule running the hooks.
  • Added bob.ToMods which a slice of structs that implement bob.Mod[T] to a Mod. This is useful since Go does not allow using a slice of structs as a slice of an interface the struct implements.
  • Added bob.HookableQuery interface. If a query implements this interface, the method RunHooks(ctx, exec) will be called before the query is executed.
  • Added bob.HookableType interface. If a type implements this interface, the method AfterQueryHook(ctx, exec, bob.QueryType) will be called after the query is executed.
    This is how AfterSeleect/Insert/Update/DeleteHooks hooks are now implemented.
  • Added Type() QueryType method to bob.Query to get the type of query it is. Available constants are Unknown, Select, Insert, Update, Delete.
  • Postgres and SQLite Update/Delete queries now refresh the models after the query is executed. This is enabled by the RETURNING clause, so it is not available in MySQL.
  • Added the Case() starter to all dialects to build CASE expressions. (thanks @k4n4ry)
  • Added bob.Named() which is used to add named arguments to the query and bind them later.
  • Added bob.BindNamed which takes an argument (struct, map, or a single value type) to be used to bind named arguments in a query. See changes to bob.Prepare() for details of which type can be used.
  • Indexes now include more information such as the type, unique and comment fields.
  • Constraints now include a comment field.
  • Added Checks field to DBConstraints so that drivers can also load check constraints. (not yet supported by the SQLite driver).
  • Added comments field to Table definitions.

Changed

  • context.Context is now passed to Query.WriteQuery() and Expression.WriteSQL() methods. This allows for more control over how the query is built and executed.
    This change made is possible to delete some hacks and simplify the codebase.

    • The Name() and NameAs() methods of Views/Tables no longer need the context argument since the context will be passed when writing the expression. The API then becomes cleaner.
    • Preloading mods no longer need to store a context internally. SetLoadContext() and GetLoadContext() have removed.
    • The ToExpr field in orm.RelSide which was used for preloading is no longer needed and has been removed.
  • Moved orm.Hooks to bob.Hooks since it should not be limited to only ORM queries.

  • Moved mods.QueryModFunc to bob.ModFunc since it should be available to all packages.

  • The mod capability for orm.Setter is now reversed. It should now be a mod for Insert and have a method that returns a mod for Update.
    This makes more sense since one would at most use one setter during updates, but can use multiple setters in a bulk insert.

  • table.InsertQ has been renamed to table.Insert. The old implementation of Insert has been removed.
    The same functionality can be achieved in the following way:

    //----------------------------------------------
    // OLD WAY
    //----------------------------------------------
    user, err := models.Users.Insert(ctx, db, setter) // insert one
    users, err := models.Users.InsertMany(ctx, db, setters...) // insert many
    
    //----------------------------------------------
    // NEW WAY
    //----------------------------------------------
    user, err := models.Users.Insert(setter).One(ctx, db) // insert one
    users, err := models.Users.Insert(setters[0], setters[1]).All(ctx, db) // insert many
    
    // For cases where you already have a slice of setters and you want to pass them all, you can use `bob.ToMods`
    users, err := models.Users.Insert(bob.ToMods(setters)).All(ctx, db) // insert many
  • table.UpdateQ has been renamed to table.Update. The old implementation of Update has been removed.
    The same functionality can be achieved by using model.Update() or modelSlice.UpdateAll().

  • table.DeleteQ has been renamed to table.Delete. The old implementation of Delete has been removed.
    The same functionality can be achieved by using modelSlice.DeleteAll() or creating an Delete query using table.Delete().

  • BeforeInsertHooks now only takes a single ModelSetter at a time.
    This is because it is not possible to know before executing the queries exactly how many setters are being used since additional rows can be inserted by applying another setter as a mod.

  • bob.Cache() now requires an Executor. This is used to run any query hooks.

  • bob.Prepare() now requires a type parameter to be used to bind named arguments. The type can either be:

    • A struct with fields that match the named arguments in the query
    • A map with string keys. When supplied, the values in the map will be used to bind the named arguments in the query.
    • When there is only a single named argument, one of the following can be used:
      • A primitive type (int, bool, string, etc)
      • time.Time
      • Any type that implements driver.Valuer.
  • Index columns are no longer just strings, but are a struct to include more information such as the sort order.

Removed

  • Remove MS SQL artifacts. (thanks @mbezhanov)
  • Remove redundant type parameter from bob.Load.
  • Removed Before/AfterUpsertMods. Upserts are really just inserts with a conflict clause and should be treated as such.
  • Removed Insert/InsertMany/Upsert/UpsertMany methods from orm.Table since they are not needed.
    It is possible to do the same thing, with similar effor using the the InsertQ method (which is now renamed to Insert).
  • Remove Update and Delete methods from orm.Table since they are not needed.
    It is possible to do the same thing, with similar effor using the the UpdateQ and DeleteQ methods (which are now renamed to Update and Delete).
  • context.Context and bob.Executor are no longer passed when creating a Table/ViewQuery. It is now passed at the point of execution with Exec/One/All/Cursor.
  • Remove Prepare methods from table and view qureries. Since bob.Prepare() now takes a type parameter, it is not possible to prepare from a method since Go does not allow additional type parameters in methods.
  • Removed the Prisma and Atlas code generation drivers. It is better for Bob to focus on being able to generate code from the database in the most robust and detailed way and if the user wants, they can use other tools (such as prisma and atlas) to manage migrations before the code generation.
  • Removed Expressions from Index definitions. It is now merged with the Columns field with an IsExpression field to indicate if the column is an expression.

Fixed

  • Removed unnecessary import of strings in bobfactory_random.go.
  • Fixed data races in unit tests. (thanks @mbezhanov)
  • Fixed invalid SQL statements generated by sm.OrderBy().Collate(). (thanks @mbezhanov)
  • Fixed a bug preventing specific columns from being excluded when generating models from SQLite. (thanks @mbezhanov)
  • Fixed an issue where invalid code is generated if a configured relationship has from_where or to_where.
  • Fixed ModelSlice.ReloadAll() method for models with multiple primary keys.

New Contributors

Full Changelog: v0.28.1...v0.29.0

v0.28.1

28 Jun 20:10
Compare
Choose a tag to compare

Fixed

  • Also add the enum to the type array if an array of the enum is added. This is to prvent issues if the enum is only used in an array.
  • Handle null column names in expression indexes. (thanks @mbezhanov)

Full Changelog: v0.28.0...v0.28.1

v0.28.0

25 Jun 08:26
Compare
Choose a tag to compare

Added

  • Added the pgtypes.Inet for inet type in PostgreSQL. (thanks @gstarikov)
  • Added the pgtypes.Macaddr for macaddr and macaddr8 types in PostgreSQL.
  • Added the pgtypes.LSN type for the pg_lsn type in PostgreSQL.
  • Added the pgtypes.TxIDSnapshot type for the txid_snapshot type in PostgreSQL.
  • Added the pgtypes.TSVector type for the tsvector type in PostgreSQL.
  • Added AliasOf property to codegen type definitions to allow for defining types that have their own randomization logic.
  • Added DependsOn property to codegen type definitions to allow for defining types that depend on other types. This ensures that necessary code for the dependent types is generated.
  • Add xml type definition for custom randomization logic.
  • Add the Cast() starter to all dialects to build CAST(expr AS type) expressions.
  • Load index information for MySQL, PostgreSQL, and SQLite tables. (thanks @mbezhanov)

Changed

  • Changed the parray package to pgtypes.
  • Moved HStore to the pgtypes package.
  • Simplified how random expressions are written for types by using standalone functions instead of a single generic function.
  • The default DebugPrinter now prints args a bit more nicely by using thier Value() method if they implement the driver.Valuer interface.
  • Only generate 2 random values when testing random expressions.

Removed

  • Removed types.Stringer[T]. It makes assumptions for how the type should be scanned and is not reliable.

Fixed

  • Do not add FROM clause to SELECT queries that are used as subqueries.
  • Enum values are now checked for validity after scanning.

New Contributors

Full Changelog: v0.27.1...v0.28.0

v0.27.1

05 Jun 14:20
Compare
Choose a tag to compare

Fixed

  • Fixed bug in Count() queries not removing the offset from the original query. (thanks @daddz)

Full Changelog: v0.27.0...v0.27.1

v0.27.0

05 Jun 00:28
Compare
Choose a tag to compare

Added

  • Add PreloadAs PreloadOption to override the join alias when preloading a relationship with a left join. (thanks @daddz)

  • Add AliasedAs() method to tableColumns and tableWhere types to use a custom alias.

  • Add AliasedAs() method to generated relationship join mods. This is avaible in two places:

    • one to change the alias of the table being queried

      models.SelectJoins.Jets.AliasedAs("j").InnerJoin.Pilots(ctx)
    • and the other to change the alias of the relationship.

      models.SelectJoins.Jets.InnerJoin.Pilots(ctx).AliasedAs("p")
  • Add fm mods to all supported dialects (psql, mysql and sqlite). These are mods for functions and are used to modify the function call. For example:

    // import "github.com/stephenafamo/bob/dialect/psql/fm"
    psql.F( "count", "*",)(fm.Filter(psql.Quote("status").EQ(psql.S("done"))))
  • Add MustCreate, MustCreateMany, CreateOrFail and CreateManyOrFail methods to generated factory Templates

Changed

  • Change the function call point for generated relationship join mods. This reduces the amount of allocations and only does the work for the relationship being used.

    // Before
    models.SelectJoins(ctx).Jets.InnerJoin.Pilots
    // After
    models.SelectJoins.Jets.InnerJoin.Pilots(ctx)
  • Changed the Count() function on Views to clone the query instead of changing the existing one. This makes queries reusable and the Count() function to behave as one would expect.

    // This now works as expected
    query := models.Jets.Query(ctx, db, /** list of various mods **/)
    count, err := query.Count()
    items, err := query.All()
  • Changed how functions are modified. Instead of chained methods, the F() starter now returns a function which can be called with mods:

    // Before
    psql.F( "count", "*",).FilterWhere(psql.Quote("status").EQ(psql.S("done"))),
    // After
    // import "github.com/stephenafamo/bob/dialect/psql/fm"
    psql.F( "count", "*",)(fm.Filter(psql.Quote("status").EQ(psql.S("done")))),

    This makes it possible to support more queries.

  • Use netip.Addr instead of netip.Prefix for Postgres cidr type.

  • Use decimal.Decimal instead of string for Postgres money type.

  • Use net.HardwareAddr for Postgres macaddr8 type, in addition to the macaddr type.

  • Code generation now generates struct tags for the generated model Setters as well, if configured through the Tags configuration option. Previoulsy, only the model struct fields were tagged. (thanks @singhsays)

Removed

  • Remove TableWhere function from the generated code. It was not used by the rest of the generated code and offered no clear benefit.
  • Removed As starter. It takes an Expression and is not needed since the Expression has an As method which can be used directly.

Fixed

  • Fix a bug with types.Stringer[T] where the wrong value was returned in the Value() method.

New Contributors

Full Changelog: v0.26.1...v0.27.0

v0.26.1

26 May 22:44
Compare
Choose a tag to compare

Fixed

  • Use netip.Prefix instead of netip.Addr for postgres inet column type. This makes it possible to contain a subnet. By @stephenafamo in #217
  • Allow underscores in enum variable names. By @stephenafamo in #218
  • Fix an issue with title casing enum values. By @stephenafamo in #219

Full Changelog: v0.26.0...v0.26.1

v0.26.0

21 May 01:37
Compare
Choose a tag to compare

Added

  • Add bobgen-sql a code generation driver for SQL schema files. Supports PostgreSQL and SQLite.
  • Add new properties compare_expr and compare_expr_imports to the types configuration. This is used when comparing primary keys and in testing.
  • Add never_required to relationships configuration. This makes sure the factories does not require the relationship to be set. Useful if you're not using foreign keys. (thanks @jacobmolby)
  • Add wrapper types for Stringer, TextMarshaler/Unmarshaler, and BinaryMarshaler/Unmarshaler to the types configuration.
  • Make generated enum types implement the fmt.Stringer, encoding.TextMarshaler, encoding.TextUnmarshaler, encoding.BinaryMarshaler and encoding.BinaryUnmarshaler interfaces.

Fixed

  • Properly detect reference columns for implicit foreign keys in SQLite.
  • Fix panic when generating random values for nullable columns. (thanks @jacobmolby)
  • Sort relationships and imports for deterministic generated code. (thanks @jacobmolby)
  • Correctly allow OVER () with an empty window definition in PostgreSQL. (thanks @relvacode)
  • Set GROUP BY to NULL if there are no expressions to group by.
  • Replace symbols in enum values with their unicode point to make them valid Go identifiers.
  • Properly detect implicit foreign keys in SQLite.
  • Fix issue with attaching multi-sided relationships. (thanks @jacobmolby)

New Contributors

Full Changelog: v0.25.0...v0.26.0

v0.25.0

20 Jan 20:09
Compare
Choose a tag to compare

Changed

  • Update github.com/jaswdr/faker dependency from v1 to v2

Full Changelog: v0.24.0...v0.25.0

v0.24.0

20 Jan 20:08
Compare
Choose a tag to compare

Added

  • Add randomization for all primitive types
  • Add test for factory type randomization
  • Drivers are now required to send in type definitions for generated types
  • Custom types can now be configured at a top level in the config file

Changed

  • Format generated files with gofumpt
  • Replace key in replacements configuration is now a string referring to the type defined in the types configuration.

Removed

  • Remove Imports from column definition.

Fixed

  • INTEGER columns are now correctly generated as int32 not int

Full Changelog: v0.23.2...v0.24.0

v0.23.2

04 Jan 01:02
Compare
Choose a tag to compare

Fixed

  • Fix panic when inferring modify for relationships with no primary key
  • Skip factory enum generation if there are no enums
  • Return sql.ErrNoRows when Insert/Upsert returns nothing

Full Changelog: v0.23.1...v0.23.2