Releases: stephenafamo/bob
v0.29.0
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
andexcept
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 usingq.MustBuild()
would not add the columns whilebob.MustBuild(q)
will add them correctly. modelSlice.UpdateMod()
andmodelSlice.DeleteMod()
are new methods that returns a mod for update and delete queries on a slice of models.
It addsWHERE pk IN (pk1, pk2, pk3, ...)
to the query, and also schedule running the hooks.- Added
bob.ToMods
which a slice of structs that implementbob.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 methodRunHooks(ctx, exec)
will be called before the query is executed. - Added
bob.HookableType
interface. If a type implements this interface, the methodAfterQueryHook(ctx, exec, bob.QueryType)
will be called after the query is executed.
This is howAfterSeleect/Insert/Update/DeleteHooks
hooks are now implemented. - Added
Type() QueryType
method tobob.Query
to get the type of query it is. Available constants areUnknown, 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 buildCASE
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 tobob.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 toQuery.WriteQuery()
andExpression.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()
andNameAs()
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()
andGetLoadContext()
have removed. - The
ToExpr
field inorm.RelSide
which was used for preloading is no longer needed and has been removed.
- The
-
Moved
orm.Hooks
tobob.Hooks
since it should not be limited to only ORM queries. -
Moved
mods.QueryModFunc
tobob.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 totable.Insert
. The old implementation ofInsert
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 totable.Update
. The old implementation ofUpdate
has been removed.
The same functionality can be achieved by usingmodel.Update()
ormodelSlice.UpdateAll()
. -
table.DeleteQ
has been renamed totable.Delete
. The old implementation ofDelete
has been removed.
The same functionality can be achieved by usingmodelSlice.DeleteAll()
or creating anDelete
query usingtable.Delete()
. -
BeforeInsertHooks
now only takes a singleModelSetter
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 anExecutor
. 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 fromorm.Table
since they are not needed.
It is possible to do the same thing, with similar effor using the theInsertQ
method (which is now renamed toInsert
). - Remove
Update
andDelete
methods fromorm.Table
since they are not needed.
It is possible to do the same thing, with similar effor using the theUpdateQ
andDeleteQ
methods (which are now renamed toUpdate
andDelete
). context.Context
andbob.Executor
are no longer passed when creating a Table/ViewQuery. It is now passed at the point of execution withExec/One/All/Cursor
.- Remove
Prepare
methods from table and view qureries. Sincebob.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 theColumns
field with anIsExpression
field to indicate if the column is an expression.
Fixed
- Removed unnecessary import of
strings
inbobfactory_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
orto_where
. - Fixed
ModelSlice.ReloadAll()
method for models with multiple primary keys.
New Contributors
- @tjmtmmnk made their first contribution in #247
- @adel-hadadi made their first contribution in #249
- @Hasaber8 made their first contribution in #265
- @mrtztg made their first contribution in #272
- @k4n4ry made their first contribution in #294
Full Changelog: v0.28.1...v0.29.0
v0.28.1
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
Added
- Added the
pgtypes.Inet
forinet
type in PostgreSQL. (thanks @gstarikov) - Added the
pgtypes.Macaddr
formacaddr
andmacaddr8
types in PostgreSQL. - Added the
pgtypes.LSN
type for thepg_lsn
type in PostgreSQL. - Added the
pgtypes.TxIDSnapshot
type for thetxid_snapshot
type in PostgreSQL. - Added the
pgtypes.TSVector
type for thetsvector
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 buildCAST(expr AS type)
expressions. - Load index information for MySQL, PostgreSQL, and SQLite tables. (thanks @mbezhanov)
Changed
- Changed the
parray
package topgtypes
. - Moved
HStore
to thepgtypes
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 thierValue()
method if they implement thedriver.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 toSELECT
queries that are used as subqueries. - Enum values are now checked for validity after scanning.
New Contributors
- @gstarikov made their first contribution in #234
- @mbezhanov made their first contribution in #236
Full Changelog: v0.27.1...v0.28.0
v0.27.1
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
Added
-
Add PreloadAs PreloadOption to override the join alias when preloading a relationship with a left join. (thanks @daddz)
-
Add
AliasedAs()
method totableColumns
andtableWhere
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
andCreateManyOrFail
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 onViews
to clone the query instead of changing the existing one. This makes queries reusable and theCount()
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 ofnetip.Prefix
for Postgrescidr
type. -
Use
decimal.Decimal
instead ofstring
for Postgresmoney
type. -
Use
net.HardwareAddr
for Postgresmacaddr8
type, in addition to themacaddr
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 anExpression
and is not needed since theExpression
has anAs
method which can be used directly.
Fixed
- Fix a bug with
types.Stringer[T]
where the wrong value was returned in theValue()
method.
New Contributors
- @daddz made their first contribution in #220
- @singhsays made their first contribution in #225
Full Changelog: v0.26.1...v0.27.0
v0.26.1
Fixed
- Use
netip.Prefix
instead ofnetip.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
Added
- Add
bobgen-sql
a code generation driver for SQL schema files. Supports PostgreSQL and SQLite. - Add new properties
compare_expr
andcompare_expr_imports
to thetypes
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
andencoding.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
toNULL
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
- @relvacode made their first contribution in #186
- @mmrath made their first contribution in #191
- @AaronCTech made their first contribution in #193
Full Changelog: v0.25.0...v0.26.0
v0.25.0
v0.24.0
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 thetypes
configuration.
Removed
- Remove
Imports
from column definition.
Fixed
INTEGER
columns are now correctly generated asint32
notint
Full Changelog: v0.23.2...v0.24.0
v0.23.2
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