NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
Go modules · #1031 by repository stars
Last release 1 months ago
31 Aug 2026
Ships fairly regularly
a new release about every 1 weeks
Nearly every release is documented
notes for 57 of the last 60 stable releases
1 version withdrawn
withdrawn after publishing
4 years old
332 releases · first in 2022
One column per quarter.
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Deprecated the wipe option to delete all files in the output folder. Files are now generated with a .bob.go extension and are always cleaned up before…
QueryFolders to gen/drivers.DBInfo for drivers to be able to include information about parsed queries.gen/QueriesTemplates which in the future will contain base templates for generating code for parsed qureries.QueryTemplate field to bobgen_helpers.Templates for drivers to include additional templates for queries.queries. This is handled specially for each query folder supplied by the driver.wm package to each dialect for mods that modify Window clauses.Alias for View struct, for each dialect. It returns the alias of the view. (thanks @Nitjsefni7)clause.OrderDef is now a string not an expression and is always quotedUpdateAll, DeleteAll and ReloadAll on an empty model slice now returns nil without running any queries.UNION, INTERSECT and EXCEPT mods now append to the query instead of replacing it..bob.go instead of .go and are always cleaned up before generating new files. Singleton templates are now required to have a .bob.go.tpl extension.singleton folder. Now, any template not inside a folder is considered a singleton template.table/ folder.table/ folder are considered.From in clause.Window to BasedOn to avoid confusion with FromPreceding and FromFollowing. Also change SetFrom to SetBasedOn.clause.OrderBy in clause.Window to make it possible to reuse OrderBy mods in window definitions.Definition field in clause.NamedWindow from any to clause.Window for extra type safety.sm.Window now takes mods to modify the window clause.fm.Over now takes mods to modify the window for the window function.wipe option to delete all files in the output folder. Files are now generated with a .bob.go extension and are always cleaned up before generating new files.orm.ExecQuery.orm.Query and orm.ExecQuery.clause.IWindow interface.dialect.WindowMod and dialect.WindowMods which use chainable methods to modify Window clauses. This is now handled by the wm package which used mods.UpdateMod() and DeleteMod() methods on an empty model slice now appends WHERE primary_key IN NULL which will return no results. Instead of WHERE primary_key IN () which is a syntax error.net/netip is imported for the pgtypes.Inet random expression (thanks @plunkettscott)Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Added error constants for matching against both specific and generic unique constraint errors raised by the underlying database driver. (thanks @mbezh
only and except table filters. (thanks @mbezhanov)ContextualMods which are similar to regular mods but take a context argument. They are applied whenever the query is built.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.WHERE pk IN (pk1, pk2, pk3, ...) to the query, and also schedule running the hooks.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.bob.HookableQuery interface. If a query implements this interface, the method RunHooks(ctx, exec) will be called before the query is executed.bob.HookableType interface. If a type implements this interface, the method AfterQueryHook(ctx, exec, bob.QueryType) will be called after the query is executed.AfterSeleect/Insert/Update/DeleteHooks hooks are now implemented.Type() QueryType method to bob.Query to get the type of query it is. Available constants are Unknown, Select, Insert, Update, Delete.RETURNING clause, so it is not available in MySQL.Case() starter to all dialects to build CASE expressions. (thanks @k4n4ry)bob.Named() which is used to add named arguments to the query and bind them later.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.Checks field to DBConstraints so that drivers can also load check constraints. (not yet supported by the SQLite driver).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.
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.SetLoadContext() and GetLoadContext() have removed.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:
time.Timedriver.Valuer.Index columns are no longer just strings, but are a struct to include more information such as the sort order.
bob.Load.Before/AfterUpsertMods. Upserts are really just inserts with a conflict clause and should be treated as such.Insert/InsertMany/Upsert/UpsertMany methods from orm.Table since they are not needed.InsertQ method (which is now renamed to Insert).Update and Delete methods from orm.Table since they are not needed.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.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.Expressions from Index definitions. It is now merged with the Columns field with an IsExpression field to indicate if the column is an expression.strings in bobfactory_random.go.sm.OrderBy().Collate(). (thanks @mbezhanov)from_where or to_where.ModelSlice.ReloadAll() method for models with multiple primary keys.Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
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.
Nothing published for this version
Nothing published for this version
Nothing published for this version
Added the pgtypes.Inet for inet type in PostgreSQL. (thanks @gstarikov)
pgtypes.Inet for inet type in PostgreSQL. (thanks @gstarikov)pgtypes.Macaddr for macaddr and macaddr8 types in PostgreSQL.pgtypes.LSN type for the pg_lsn type in PostgreSQL.pgtypes.TxIDSnapshot type for the txid_snapshot type in PostgreSQL.pgtypes.TSVector type for the tsvector type in PostgreSQL.AliasOf property to codegen type definitions to allow for defining types that have their own randomization logic.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.xml type definition for custom randomization logic.Cast() starter to all dialects to build CAST(expr AS type) expressions.parray package to pgtypes.HStore to the pgtypes package.DebugPrinter now prints args a bit more nicely by using thier Value() method if they implement the driver.Valuer interface.types.Stringer[T]. It makes assumptions for how the type should be scanned and is not reliable.FROM clause to SELECT queries that are used as subqueries.Nothing published for this version
Nothing published for this version
Nothing published for this version
Fixed bug in Count() queries not removing the offset from the original query. (thanks @daddz)
Count() queries not removing the offset from the original query. (thanks @daddz)Nothing published for this version
Nothing published for this version
Add PreloadAs PreloadOption to override the join alias when preloading a relationship with a left join. (thanks @daddz)
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
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)
TableWhere function from the generated code. It was not used by the rest of the generated code and offered no clear benefit.As starter. It takes an Expression and is not needed since the Expression has an As method which can be used directly.types.Stringer[T] where the wrong value was returned in the Value() method.Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Use netip.Prefix instead of netip.Addr for postgres inet column type. This makes it possible to contain a subnet.
netip.Prefix instead of netip.Addr for postgres inet column type. This makes it possible to contain a subnet.Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Add bobgen-sql a code generation driver for SQL schema files. Supports PostgreSQL and SQLite.
bobgen-sql a code generation driver for SQL schema files. Supports PostgreSQL and SQLite.compare_expr and compare_expr_imports to the types configuration. This is used when comparing primary keys and in testing.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)types configuration.fmt.Stringer, encoding.TextMarshaler, encoding.TextUnmarshaler, encoding.BinaryMarshaler and encoding.BinaryUnmarshaler interfaces.OVER () with an empty window definition in PostgreSQL. (thanks @relvacode)GROUP BY to NULL if there are no expressions to group by.Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →