All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Added
enum_formatconfiguration option to control enum value identifier formatting. Options:"title_case"(default, e.g.,InProgress) or"screaming_snake_case"(e.g.,IN_PROGRESS). - Added
Unqualified()method to generated column structures that returns columns without table alias/prefix. (thanks @atzedus) - Added
PreloadCountandThenLoadCountto generate code for preloading and then loading counts for relationships. (thanks @jacobmolby) - MySQL support for insert queries executing loaders (e.g.,
InsertThenLoad,InsertThenLoadCount). (thanks @jacobmolby) - Added overwritable hooks that are run before the exec or scanning test of generated queries. This allows seeding data before the test runs.
- Added
bob.Eachfunction to iterate over query results (range-over-func). (thanks @toqueteos) - Added support for the
VALUESstatement in MySQL, PostgreSQL, and SQLite. (thanks @manhrev) - Added MariaDB compatibility check in gen/bobgen-mysql (thanks @dumdev25)
- Added
ALL,SOME,ANYexpressions for MySQL and PostgreSQL dialects. AddedEXISTSexpression for all dialects. (thanks @manhrev)
- Fix collisions for preloader alias generation. Replaced
RandIntwithNextUniqueInt(thanks @atzedus) - Fix an issue where the random function of aliased custom types were not being used in generated query tests.
- Properly recognize placeholders in LIMIT and OFFSET when generating queries for PostgreSQL.
- Throw an error on an empty SET clause during SQL generation rather than sending invalid syntax to database. (thanks @Xaeroxe)
- Fix MySQL
Insert().One()/All()/Cursor()usingSELECT *instead of explicit model columns when re-fetching inserted rows, consistent with PostgreSQL/SQLiteRETURNING. (thanks @tak848)
- Fixed a bug where the generated loaders for many-to-many relationships were skipping related rows. (thanks @TylerJGabb)
- Include
shell.nixfor developers using Nix to create development environments. (thanks @EliRibble) - Additional README content on how developers can use linting and unit testing to contribute. (thanks @EliRibble)
- Added
Plusexpression chain method (thanks @atzedus).
- Export
orm.NullTypeConverter. (thanks @Serjlee) - Uses
io.StringWriterinstead ofio.Writerfor efficiency since we are always writing strings.
- Properly handle code generation tests for compound queries in MySQL.
drivers/pgx.Poolnow includes the methodsAcquireandAcquireFuncwhich mirror the methods inpgx/v5/pgxpoolto acquire a connection from the pool (thanks @Eyal-Shalev).- Added the
drivers/pgx.PoolConntype which is a wrapper aroundpgx/v5/pgxpool.Conn.
- Use the full column type and not just the datatype as the
DBTypein bobgen-mysql. bob.Transactoris now a generic interface so that implementations can use a concrete transaction type.- The data types generated for SQLite now follow SQLite's type affinity rules more closely (excluding some common names). As a result, all integer types are now mapped to
int64and all floating point types are mapped tofloat64.
- Fixed an issue where
bobgen-mysqlcould not detect unsigned integer columns in queries. - Properly close
pgxtransactions if the context used inBeginTxis cancelled. - Fix issues with generating code for relationships defined with
WhereExpr. - Support
uint64type when scanning columns astypes.Uint64. This fixes scanningBIGINT UNSIGNEDMySQL columns astypes.Uint64wheninterpolateParamsis enabled. (thanks @luiscleto) - Properly handle code generation tests for compound queries in MySQL.
- Fix an issue where some ids are uppercased by the MySQL query code generator.
- Fixed Scanner/Valuer test gen for types defined in the models package.
- Fix issue with randomization test when enum is only used in an array.
- Fix issue with using
CompareExprwith values that are null. - Fix issue with imports in query tests.
- Fix issue with detecting the columns in a CTE in
bobgen-psql. - Properly detect the end of a function call in postgres qury parser.
- Fixed bug in preloading
- Made code generation modular by relying on built-in plugins that can be enabled or disabled in the configuration.
dbinfo: Generates code for information about each database. Schemas, tables, columns, indexes, primary keys, foreign keys, unique constraints, and check constraints.enums: Generates code for enums in a separate package, if there are any present.models: Generates code for models. Depends onenums.factory: Generates code for factories. Depends onmodels.dberrors: Generates code for unique constraint errors. Depends onmodels.where: Generates type-safe code forWHEREclauses in queries. Depends onmodels.loaders: Adds templates to themodelspackage to generate code for loaders e.gmodels.SelectThenLoad.Table.Rel().joins: Adds templates to themodelspackage to generate code for joins e.gmodels.SelectJoin.Table.LeftJoin.Rel.queries: Generates code for queries.
- Added new
types.Uint64type that sends values to the database as strings. This is necessary because usinguint64directly can cause an overflow if the value exceeds the maximum value of anint64. This is a limitation imposed bydatabase/sql/driver.Valuerinterface. - Added support for
pgvectortypes during code generation.pgvector.Vectorpgvector.HalfVectorpgvector.SparseVector
- Enums are now imported directly from a new generated
enumspackage. This makes it easier to use enums in other packages without having to depend on themodelspackage. - Preload functions now take a custom
orm.PreloadRelstruct instead of reusingorm.Relationship. - By default, factories are now generated in
./factoryinstead of./models/factory. - Outputs are now determined by plugins which can be enabled or disabled in the configuration.
- UniqueConstraintErrors are now generated in a separate
dberrorspackage instead of being generated in themodelspackage. - Tests in the generated
modelspackage are no longer generated in a separatemodels_testpackage. There is no longer any circular dependency since tests for the unique constraint errors are generated in thedberrorspackage. orm.Columnshas been moved toexpr.ColumnsExpr.orm.NewColumnshas been moved toexpr.NewColumnsExpr.<Table>.Columns()is removed. The columns expression is now expected to be embedded in theColumnsfield of the<Table>struct.<dialect>.Viewand<dialect>.Tablenow take an additional type parameter for the columns type. This is assigned to theColumnsfield withNewView/NewTablefunctions.
- Removed the
no_factoryconfiguration option. It is now replaced with thefactoryplugin which can be enabled or disabled. See https://bob.stephenafamo.com/docs/code-generation/configuration#plugins-configuration for more details. - Removed the
OnlyandExceptexported functions inorm. They are now in the privateinternalpackage. - Removed the generated
models.<Model>Columnsglobal variable. It can now be accessed throughmodels.<Table>.Columns. - Removed the generated
models.TableNamesandmodels.ColumnNamesglobal variables. Their use can be replaced with thedbinfoplugin which generates adbinfopackage with all the information about the database.
- Fixed issue with redundant title casing column names in query templates. (thanks @luiscleto)
- Fix invalid expression with pointer-based type systems. (thanks @tak848)
- Fix panic when parsing SQLite
UPDATEqueries that do not contain aFROMclause. - Fix issue when using enums in generated queries.
- Fix randomization of floats and decimals in the factory.
- Fix JSON data being incorrectly hex-encoded as bytea when using pgx through simple protocol, causing PostgreSQL to reject it with invalid input syntax errors. (by @Maxitosh)
- Fix issue with preload queries not using a defined schema on the related tables
- Added the
Asmethod toclause.TableRef, which sets the alias and return a copy of the struct. (thanks @Nitjsefni7) - Added the
type_systemconfiguration option to determine how to generate null and optional values in the generated code. Possible options:github.com/aarondl/opt,github.com/aarondl/opt/nullordatabase/sql. The default value isgithub.com/aarondl/opt. - When generating code for queries, The
Allmethod of the generated query will return a struct with nested fields instead of a flat struct.- columns with dots (
.) are assumed to be ato-manynested field. - columns with double underscores (
__) are assumed to be ato-onenested field.
- columns with dots (
- Implement
--prefixannotation in queries forbobgen-psql. - Add FromExistingRel method to factories to create a template from an existing model. (thanks @dutow)
- Add WithExistingRel to factory mods to attach an existing model as a relationship. (thanks @dutow)
- Added support in psql for combined args (order by, limit etc.) in combined queries and use parens if they are present. (@iwyrkore)
- Added parens for combined queries. (@iwyrkore)
- Match columns using regular expressions in type replacements. This is useful for e.g. matching columns that have a common prefix or suffix. (thanks @abdusco)
Modis now a separate field inorm.ModQueryandorm.ModExecQuery.Allxnow takes aTransformertype parameter to transform the result of the query.- Updated documentation for readability, added code gen examples. (thanks @singhsays)
- Columns are now matched in a case-insensitive manner in type replacements. (thanks @abdusco)
- Columns can now be matched with as many conditions as needed in type replacements. This removes the previous requirement that boolean fields had to be specified in addition to a string field. (thanks @abdusco)
- Factories now expose a
NewXWithContextthat accepts a context in addition toNewXthat does not. This provides a cleaner API for the callers, while still allowing the use of context internally. (thanks @abdusco)
- Removed the
fallback_nullconfiguration option. It is now replaced with thetype_systemconfiguration option.
- Fixed some issues with creating relationships in the factory by avoiding trying to reuse models.
- Fix issues with generating code for queries with duplicate return column names.
- Updated gen table detail queries to use context. (thanks @singhsays)
- Properly detect
bool,timestampandtimestamptztypes inbobgen-psql. - Fix transformer for single result queries.
- Properly handle indexes where the sorting order can be null.
- Check for nullability when loading relationships.
- Handle table names quoted with backticks in mysql query parser. (thanks @luiscleto)
- Allow matching columns in type replacements by the
autoincrproperty as stated in the docs. (thanks @abdusco) - Handle dashes and spaces in generated enum values properly (thanks @abdusco)
- Check for nullability when loading relationships from Slices (thanks @felipeparaujo)
- Added the
fallback_nulltop level configuraiton option. Which can be eitherdatabase/sqlorgithub.com/aarondl/opt/null.
This is used to determine how to create null values in the generated code. If set todatabase/sql, it will usesql.Null[T]for nullable types, and if set togithub.com/aarondl/opt/null, it will useopt.null.Val[T].
The default value isdatabase/sql.
- Correctly build models with nested relationships in the factory.
- Fix a performance issue with code generation in
bobgen-psql. - Use the correct alias when generating table columns.
- Fix issue with generating factory code for tables with schema names.
- Added the
drivers/pgxpackage which contains types and functions to use apgx/v5connection as abob.Executor. - Added support for
github.com/ncruces/go-sqlite3. (thanks @ncruces) - Added support for configuring what type to generate specific null versions of a type instead of always wrapping with
sql.Null[T].
- The
bob.Transactioninterface now takes acontext.Contextargument in theCommitandRollbackmethods. - The method
BeginTxon thebob.Transactioninterface is now changed toBeginand it takes a single context argument.
This is to make it easier to implement for nondatabase/sqldrivers. - In the generated model, the
PrimaryKeyVals()method is now private. - Renamed
driver_nametodriverin code generation configuration. - In type replacements, nullability is not used in matching. Previously, nullability of matches was set to false by default, and would require an additional replacement to also match nullable columns.
- Removed the
NewandNewQueryerfunctions. Any ofbob.NewDB,bob.NewTxorbob.NewConncan be used instead. - Removed the
StdInterfaceinterface as it is unnecessary. - Remove redundant
orm.Modelinterface. - Remove dependence on
github.com/aarondl/optin generated code.- Nullable values are now wrapped
database/sql.Nullwith instead ofgithub.com/aarondl/opt/null.Val. - Optional values are now represented as pointers instead of
github.com/aarondl/opt/omit.Val[T].
- Nullable values are now wrapped
- Removed
in_generated_packagetype configuration option. This was limited and could only indicate that the type is in the models package. Instead the full import path can now be used in theimportsconfiguration option, and if it is in the same package as the generated code, the prefix will be automatically removed.
- Properly handle
nilargs when checking if default or null inmysqltable insert query. - Fix bug in querying slice relationships in MySQL and SQLite.
- Fixed issue with generating correct test code for nullable args in SQL queries.
- Fix issue where writing the "NO EDIT Disclaimer" at the top of Go generated files was skipped.
-
Loaders are now generated as singular instead of plural. This feels more natural when using them in code.
// Before models.Preload.Users.Pilots() models.SelectThenLoad.Users.Pilots() // After models.Preload.User.Pilots() models.SelectThenLoad.User.Pilot()
- Store
types.Timeas an RFC3339 string in the DB
- Added support to generate code for
SELECT,INSERT,UPDATEandDELETEqueries inbobgen-mysql. - Added support to generate code for
INSERT,UPDATEandDELETEqueries inbobgen-sqlite. - Added
LIMITandOFFSETto the SQLite Update and Delete queries. - Added
IndexedByandNotIndexedmods to the SQLite Delete queries. - Added the
TransactorandTransactioninterfaces. - Added the
SeparatePackageForTestsattribute to generation outputs to indicate if generated tests should have their own package. - Added the
RandomColumnNotNullmod to factories to generate random values for non-nullable columns without the chance of being null. - Added the
WithOneRelationsmod to factories to include every relation for a factory template. - Added
clause.TableRefwhich mergesclause.Tableandclause.Fromsince they had overlapping functionality. - Added
RunInTxmethod tobob.DB. This starts a transaction and calls the given function with this transaction. - Add support for MySQL to
bobgen-sql. - Added
Exectest for generated queries that do not return rows. - Added
OrderCombined,LimitCombined,OffsetCombinedmods to MySQLSELECTqueries. These are applied to the result of aUNION,INTERSECTorEXCEPTquery. - Added
type_limitsproperty to column definitions. - Added
limitsoption torandom_exprfunction for types. This is to pass any column limits to the randomization function (e.g.max_lengthfor strings). - Added tests to check that the generated factory can create models and save into the database.
- Added the
pgtypes.Snapshottype for thepg_snapshotandtxid_snapshottype in PostgreSQL. - Added a custom
Timetype to thetypespackage. This is motivated by the fact that thelibsqldriver does not support thetime.Timetype properly. - Added an option to disable aliasing when expressing
expr.Columns. Also addedEnableAliasandDisableAliasmethods toexpr.Columnsto control this behavior. - Added a
PrimaryKeymethod to{dialect}.Tableto get the primary key columns of the table.
-
Changed the INDEXED BY and NOT INDEXED mods for SQLite update queries from
TableIndexedByandTableNotIndexedtoIndexedByandNotIndexed. -
Use
LIBSQL_TEST_SERVERenvironment variable to run tests against a libSQL server instead of the hardcodedlocalhost:8080. -
BeginTxnow returns aTransactioninterface instead of abob.Tx. -
Generated tests that required a database connection no longer create a new connection for each test. Instead it depends on a
testDBconnection that the user has to provide. -
In the generated models, relationships for
ModelSliceare now loaded using arrays to reduce the number of parameter in the query.-- Before SELECT * FROM pilots WHERE jet_id IN ($1, $2, $3, ...); -- Parameters increase with the number of pilots -- After SELECT * FROM pilots WHERE jet_id IN (SELECT unnest(CAST($1 AS integer[])); -- Parameters are always 1
-
In the generated model code,
Preloadis now a struct instead of multiple standaalone functions.
It is now used likePreload.User.Pilots(), instead ofPreloadUserPilots(). -
In the generated model code,
ThenLoadis now a struct and has been split for each query type.
It is now used likeSelectThenLoad.User.Pilots(), instead ofThenLoadUserPilots(). -
In the generated model code, the Load interfaces no longer include the name of the source model since it is a method on the model.
It now looks like*models.User.LoadPilotsinstead of*models.User.LoadUserPilots. -
Made changes to better support generating code in multiple languages.
-
Mark queries with
ON DUPLICATE KEY UPDATEas unretrievable in MySQL. -
Unretrievable
INSERTqueries usingOne, All, Cursornow immediately returnorm.ErrCannotRetrieveRowinstead of executing the query first. -
Generated tests are now run when testing drivers.
-
MEDIUMINTandMEDIUMINT UNSIGNEDare now generated asint16anduint16respectively. This is because Go doe not support 24 bit integers. -
The randomization function for floats, strings, and decimals now respect the limits set in the column definition.
-
txid_snapshotis now generated aspgtypes.Snapshotinstead ofpgtypes.TxIDSnapshot. -
cidrpostgres type is now generated astypes.Text[netip.Prefix]instead oftypes.Text[netip.Addr]. -
moneypostgres type is now generated as a string with a custom randomization expression instead of a decimal. -
Factory template mods now take a context argument. This allows for more control when using recursive mods.
-
Removed
WithOneRelationsmod from factories, now replaced withWithParentsCascadingwhich also includes parents for any parent relationships.
- Removed
clause.Tableandclause.From, and merge intoclause.TableRefsince they had overlapping functionality. - Remove unnecessary context closure in generated join helpers.
- Remove the deprecated
wipegeneration option. - Remove
pgtypes.TxIDSnapshottype. This is now replaced withpgtypes.Snapshot.
- Use correct row name for generated queries in
bobgen-sqlite. - Properly select query comment in
bobgen-sqlite. - Fixed issue with using generated queries with
VALUESas mods. - Moved
Partitionsin MySQL delete queries to after the table alias. - Fixed issue with inserting into a table with all rows having default values in SQLite.
- Use table name and not table alias in SQLite returning clause since the alias is not available in the
RETURNINGclause. - Fixed generated unique constraint errors for SQLite.
- Correctly resuse inserted rows in factories.
- Fix bug with
bobgen-psqlparsing of string identifiers in certain cases.
- Remove unnecessary limitation to place
FETCH WITH TIESbeforeOFFSET. - Fix issue with verifying statements in
bobgen-psql.
- Added support to generate code for
UPDATE, andDELETEqueries inbobgen-psql.
- Changed to non-cgo version of postgres parser.
- Changed the
dirconfiguration forbobgen-sqltopatternand it now takes a glob pattern. This allows excluding certain files from being included (e.g..down.sqlfiles).
- When a query returns only one column, instead of returning a struct with one field, it will return the type of the column. This is to make it easier to use the generated code.
- Fix panic when scanning returned rows from generated queries.
- Added support to generate code for
INSERTqueries inbobgen-psql. clause.Confictnow takesbob.Expression, and the fields are now moved to aclause.ConflictClausestruct.
- Make grouped types in generated queries a type alias.
- Remove
models.InsertWherein generated code since it is not correct.
- Fix issue with column query annotations in
bobgen-psql. - Fix issue with parsing multiple queries in the same file in
bobgen-psql. - Fix issue with correctly detecting the comment for the query annotation in
bobgen-psql. - Use a transaction in generated query tests.
- Account for LEFT, RIGHT and FULL joins when determining the nullability of a column.
- Generate WHERE helpers for
ON CONFLICTclauses.
- Added templates for query generation.
- Added
clause.OrderBy.ClearOrderBy() - Added
expr.ToArgsandexpr.ToArgGroupfunctions to convert slices of a type to args. - Add
querieskey tobobgen-sqlandbobgen-sqliteconfiguration. This is used to specify what folder to search for queries in. - Implement the Postgres query parser for
SELECTstatements. - Implement the SQLite query parser for
SELECTstatements. - Add templates for query generation.
- Add
camelCasetemplate function. - Add types to the
ormpackage to be used in generated queries.orm.ArgWithPosition,orm.ModExpression,orm.ModExecQueryandorm.ModQuery. - Add function
orm.ArgsToExpressionfor use in the generated code. - Add
String()method tobob.QueryType
- Update
mvdan.cc/gofumptand give precedence to toolchain when calculating the Go version. (thanks @isgj) - Add custom comparison support when loading relationships.
- Fix issue with scanning Postgres inet type.
- Set
ArgandArgGrouptoNULLif there are no values. - Do not call
BeforeInsertHooksin the insert mod of a view. - Fix issue with retrieving inserted rows with the MySQL driver.
- Add custom comparison for relationship loading. (thanks @kostaspt)
clause.Withnow takesbob.Expressioninstead ofclause.CTE. This makes it easier to use in generated queries without reconstruction anCTE.clause.OrderBynow takesbob.Expressioninstead ofclause.OrderDef. This makes it easier to use in generated queries without reconstruction anOrderDef.clause.Windowsnow takesbob.Expressioninstead ofclause.NamedWindow. This makes it easier to use in generated queries without reconstruction the window.clause.Forrenemaed toclause.Locksand can now take multiple locks.clause.Fetchnow takesanyinstead of an integer.- Several changes to the
drivers.Querytype as support is added for the new query parser. - Enum types can now be matched by
db_typein bobgen-psql asschema.enum_type. (thanks @abramlab)
- Removed
clause.OrderBy.SetOrderBy()as it was only being used to clear the set order by clauses.
- Added support for libSQL. (thanks @mbezhanov)
- Added support for declaring types inside the models package. (thanks @jacobmolby)
- Generates error constants with unique indexes instead of unique constraints. (thanks @tlietz)
- Used
Equalmethod for comparing decimals. (thanks @jalaziz) - Update
golang.org/x/moddependency to enable parsing of Go 1.23 modules. (thanks @m110)
- Added a new field
QueryFolderstogen/drivers.DBInfofor drivers to be able to include information about parsed queries. - Added
gen/QueriesTemplateswhich in the future will contain base templates for generating code for parsed qureries. - Added a
QueryTemplatefield tobobgen_helpers.Templatesfor drivers to include additional templates for queries. - Added a new reserved output key
queries. This is handled specially for each query folder supplied by the driver. - Added new
wmpackage to each dialect for mods that modifyWindowclauses. - Added a new method
AliasforViewstruct, for each dialect. It returns the alias of the view. (thanks @Nitjsefni7)
- Updated error constant generation to employ specific error types for making error matching easier. (thanks @mbezhanov)
- Collation in
clause.OrderDefis now a string not an expression and is always quoted - Calling
UpdateAll,DeleteAllandReloadAllon an empty model slice now returns nil without running any queries. UNION,INTERSECTandEXCEPTmods now append to the query instead of replacing it.- Generated files now end with
.bob.goinstead of.goand are always cleaned up before generating new files. Singleton templates are now required to have a.bob.go.tplextension. - The expected structure for templates have been changed:
- Previously, singleton templates should be kept in a
singletonfolder. Now, any template not inside a folder is considered a singleton template. - Previoulsy, templates in the root folder are merged and run for each table. Now, this will happen to templates in the
table/folder. - Previoulsy, the entire file tree and every subdirectory is walked to find templates. Now only templates in the root folder and the
table/folder are considered.
- Previously, singleton templates should be kept in a
- Change
Frominclause.WindowtoBasedOnto avoid confusion withFromPrecedingandFromFollowing. Also changeSetFromtoSetBasedOn. - Embed
clause.OrderByinclause.Windowto make it possible to reuseOrderBymods in window definitions. - Change the
Definitionfield inclause.NamedWindowfromanytoclause.Windowfor extra type safety. sm.Windownow takes mods to modify the window clause.fm.Overnow takes mods to modify the window for the window function.
- Deprecated the
wipeoption to delete all files in the output folder. Files are now generated with a.bob.goextension and are always cleaned up before generating new files.
- Remove redundatnt type parameters from
orm.ExecQuery. - Remove unnecessary interface in
orm.Queryandorm.ExecQuery. - Remove the redundant
clause.IWindowinterface. - Remove
dialect.WindowModanddialect.WindowModswhich use chainable methods to modifyWindowclauses. This is now handled by thewmpackage which used mods.
- Fix random value generation for pq.Float64Array factory (thanks @felipeparaujo)
- Using the
UpdateMod()andDeleteMod()methods on an empty model slice now appendsWHERE primary_key IN NULLwhich will return no results. Instead ofWHERE primary_key IN ()which is a syntax error. - Ensure
net/netipis imported for thepgtypes.Inetrandom expression (thanks @plunkettscott) - Fix a data race when adding enum types.
- Fix missing schema in table alias in pkEQ and pkIN clauses (thanks @adatob).
- 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
onlyandexcepttable filters. (thanks @mbezhanov) - Added
ContextualModswhich 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.ToModswhich 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.HookableQueryinterface. If a query implements this interface, the methodRunHooks(ctx, exec)will be called before the query is executed. - Added
bob.HookableTypeinterface. 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/DeleteHookshooks are now implemented. - Added
Type() QueryTypemethod tobob.Queryto 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
RETURNINGclause, so it is not available in MySQL. - Added the
Case()starter to all dialects to buildCASEexpressions. (thanks @k4n4ry) - Added
bob.Named()which is used to add named arguments to the query and bind them later. - Added
bob.BindNamedwhich 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
Checksfield to DBConstraints so that drivers can also load check constraints. (not yet supported by the SQLite driver). - Added comments field to Table definitions.
-
context.Contextis 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
ToExprfield inorm.RelSidewhich was used for preloading is no longer needed and has been removed.
- The
-
Moved
orm.Hookstobob.Hookssince it should not be limited to only ORM queries. -
Moved
mods.QueryModFunctobob.ModFuncsince it should be available to all packages. -
The mod capability for
orm.Setteris 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.InsertQhas been renamed totable.Insert. The old implementation ofInserthas 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.UpdateQhas been renamed totable.Update. The old implementation ofUpdatehas been removed.
The same functionality can be achieved by usingmodel.Update()ormodelSlice.UpdateAll(). -
table.DeleteQhas been renamed totable.Delete. The old implementation ofDeletehas been removed.
The same functionality can be achieved by usingmodelSlice.DeleteAll()or creating anDeletequery usingtable.Delete(). -
BeforeInsertHooksnow only takes a singleModelSetterat 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.
-
Indexcolumns are no longer just strings, but are a struct to include more information such as the sort order.
- 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/UpsertManymethods fromorm.Tablesince they are not needed.
It is possible to do the same thing, with similar effor using the theInsertQmethod (which is now renamed toInsert). - Remove
UpdateandDeletemethods fromorm.Tablesince they are not needed.
It is possible to do the same thing, with similar effor using the theUpdateQandDeleteQmethods (which are now renamed toUpdateandDelete). context.Contextandbob.Executorare no longer passed when creating a Table/ViewQuery. It is now passed at the point of execution withExec/One/All/Cursor.- Remove
Preparemethods 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
Expressionsfrom Index definitions. It is now merged with theColumnsfield with anIsExpressionfield to indicate if the column is an expression.
- Removed unnecessary import of
stringsinbobfactory_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_whereorto_where. - Fixed
ModelSlice.ReloadAll()method for models with multiple primary keys.
- 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)
- CROSS JOINS now allow aliases
- Added the
pgtypes.Inetforinettype in PostgreSQL. (thanks @gstarikov) - Added the
pgtypes.Macaddrformacaddrandmacaddr8types in PostgreSQL. - Added the
pgtypes.LSNtype for thepg_lsntype in PostgreSQL. - Added the
pgtypes.TxIDSnapshottype for thetxid_snapshottype in PostgreSQL. - Added the
pgtypes.TSVectortype for thetsvectortype in PostgreSQL. - Added
AliasOfproperty to codegen type definitions to allow for defining types that have their own randomization logic. - Added
DependsOnproperty 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
xmltype 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 the
parraypackage topgtypes. - Moved
HStoreto thepgtypespackage. - Simplified how random expressions are written for types by using standalone functions instead of a single generic function.
- The default
DebugPrinternow prints args a bit more nicely by using thierValue()method if they implement thedriver.Valuerinterface. - Only generate 2 random values when testing random expressions.
- Removed
types.Stringer[T]. It makes assumptions for how the type should be scanned and is not reliable.
- Do not add
FROMclause toSELECTqueries that are used as subqueries. - Enum values are now checked for validity after scanning.
- Fixed bug in
Count()queries not removing the offset from the original query. (thanks @daddz)
-
Add PreloadAs PreloadOption to override the join alias when preloading a relationship with a left join. (thanks @daddz)
-
Add
AliasedAs()method totableColumnsandtableWheretypes 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
fmmods 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,CreateOrFailandCreateManyOrFailmethods 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 onViewsto 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.Addrinstead ofnetip.Prefixfor Postgrescidrtype. -
Use
decimal.Decimalinstead ofstringfor Postgresmoneytype. -
Use
net.HardwareAddrfor Postgresmacaddr8type, in addition to themacaddrtype. -
Code generation now generates struct tags for the generated model Setters as well, if configured through the
Tagsconfiguration option. Previoulsy, only the model struct fields were tagged. (thanks @singhsays)
- Remove
TableWherefunction from the generated code. It was not used by the rest of the generated code and offered no clear benefit. - Removed
Asstarter. It takes anExpressionand is not needed since theExpressionhas anAsmethod which can be used directly.
- Fix a bug with
types.Stringer[T]where the wrong value was returned in theValue()method.
- Use
netip.Prefixinstead ofnetip.Addrfor postgres inet column type. This makes it possible to contain a subnet. - Allow underscores in enum variable names.
- Fix an issue with title casing enum values
- Add
bobgen-sqla code generation driver for SQL schema files. Supports PostgreSQL and SQLite. - Add new properties
compare_exprandcompare_expr_importsto thetypesconfiguration. This is used when comparing primary keys and in testing. - Add
never_requiredto 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
typesconfiguration. - Make generated enum types implement the
fmt.Stringer,encoding.TextMarshaler,encoding.TextUnmarshaler,encoding.BinaryMarshalerandencoding.BinaryUnmarshalerinterfaces.
- 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 BYtoNULLif 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)
- Update
github.com/jaswdr/fakerdependency fromv1tov2
- 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
- Format generated files with
gofumpt - Replace key in
replacementsconfiguration is now a string referring to the type defined in thetypesconfiguration.
- Remove
Importsfrom column definition.
INTEGERcolumns are now correctly generated asint32notint
- Fix panic when inferring
modifyfor relationships with no primary key - Skip factory enum generation if there are no enums
- Return
sql.ErrNoRowswhen Insert/Upsert returns nothing
- Do not wrap
Setter.Expressions()in parenthesis
- Add
bob.Cache()which saves the built SQL and args to prevent rebuilding the same query multiple times. - Add
As()starter to alias expressions - Add
OP()builder method for using custom operators - Add
table.InsertQ(ctx, db)now includes the insert columns from the table model. - It is now possible to configure additional constraints for code generation.
- Add
um.SetCol()which maintains the old behavior ofum.Set(). - Generate additional
Expressions()method for Setters to make it easier to use them inum.Set()orim.Set().
- Aliases configuration for code generation no longer has a top level
tablekey - When configuring relationships,
from_unique,to_unique,key_nullablecan no longer be configured. They are now inferred from the database. - When configuring relationships,
to_keyhas been changed tomodifyand should be set tofrom,toor""to indicate which side of the relationship to modify. If left empty, Bob will try to guess which side to modify based on the presence of primary keys and unique columns. RelWhere.Valueis nowRelWhere.SQLValue- Change CONFLICT/DUPLICATE KEY UPDATE to use mods instead of a chainable methods.
- Change
um.Set()to take a list of expressions. - Rename Setter method from
Insert()toInsertMod()to avoid confusion.
- Prevent generating duplicate relationships for many-to-many self-join relationships
- Correctly use table alias in generated relationship join mods
- Fix an issue where CTEs were encased in double parenthesis
- Fix invalid SQL generated when doing
JOIN USING - Correctly include "AS" in function query if alias is set
- Setters are also generated for tables that have relationships, even if they have no primary key
- Column aliases in CTEs are now correctly included in the final query
- Fix several issues with generating code for multi-sided relationships
- Fix an issue where loading many-to-many relationships cause no columns to be selected unless specified
- Fix an issue where many-to-many relationships would not be able to use nested loaders
- Expand expressions when used in Raw (thanks @RangelReale)
- Add
InsertQ,UpdateQ, andDeleteQmethods to Table models to start INSERT, UPDATE and DELETE queries respectively. - Allow column comment for replacement matching (thanks @jroenf)
- Add table query hooks to modify model queries
- Include
WhereOrandWhereAndto make it easier to combine multiple generated where clauses - Print a warning if a replacement rule did not find a match (thanks @jacobmolby)
- Export generated factory.Factory struct
- Allow Limit and Offset to be used as Arguments in PostgreSQL (thanks @RangelReale)
- Make model hooks take slices not single objects
- Return rows affected from
Exec()method of view queries instead ofsql.Result - Chain comparison methods now take an
Expressioninstead ofany - Table models now require the types to implement
orm.Tableandorm.Setterinterfaces.
- Remove UpdateAll and DeleteAll methods on the Table models.
- Honor Only and Except in sqlite driver
- Always surround subqueries with parenthesis when used as an expression
- Fix mysql
TablesInfomethod and make sure we don't exclude entire table when targeting columns (thanks @jacobmolby) - Fix bug in sqlite foreign key and join table detection
- Fix
UpsertandUpsertAllmethods ofmysql.Table
- Force uniqueness of relationship names in
psqldriver
- Fix panic when attaching associated relationships
- Make getting a random integer for preloading thread-safe
- Check all members when loading relationships
- Fix panic in Insert/Attach Relationship loop
- Replace
huandu/go-clonewithqdm12/reprint
- Fix cloning bug by replacing
jinzhu/copierwithhuandu/go-clone
- Account for windows when calculating models module path
- Update the generated code to use
github.com/gofrs/uuid/v5 - Fix bug where auto-increment columns were marked as generated in the SQLite driver
- Add the
PreloadWherepreload mod to filter what relation should be preloaded. ViewQuerynow embedsbob.BaseQuerygiving it additional methods likeApplyandBuild- Add plugin support. Currently 3 plugin hooks are provided.
PlugState,PlugDBInfoandPlugTemplateData.
- Make
View.Name()return a dialect-specific expression - Improve
Debughelpers.Debugwrites query output to stdoutDebugToWriterwrites the query output to anyio.Writerwith a fallback to stdout.DebugToPrinterprints the query with a givenbob.DebugPrinter. Also falls back to stdout.
- Rename
OnlyColumnstoPreloadOnlyandExceptColumnstoPreloadExceptto be more consistent with the newly addedPreloadWhere. JoinChain.Onnow takes Expressions instead ofany.JoinChain.Usingnow takes strings instead ofany.- Export
gen.TemplateData
- Remove
ILIKEoperator from MySQL since it is not supported. - Removed
Destination()method in driver interface. - Removed
PackageName()method in driver interface.
- Account for possible clashes between column and relationship alias
- Make
Preloadmods work the same way as other query mods - Avoid overwriting manually flipped relationships.
- Account for potentially null relationship in Load methods
- Fix
Onmethod for JoinChain inmysqlandsqlite
- Add
LIKEandILIKEoperators - Print generated files
- Add
no_reverseoption for user-configured relationships
- Move common parts of loading to shared internal package
- Fix generated joins for multi-sided relationships
- Account for relationships with tables that do not have a primary key in models and factories
- Properly extract preloaders nested in
mods.QueryMods - Fix bug in preloading with multiple sides
- Fix issue with multi-sided relationships that include views
- Make self-referencing foreign keys work
- Tweak factory types to make collisions even less likely
- Comparison methods now require an expression (
bob.Expression)
- No more
Xbuilder start function - No more
Pbuilder method
- Fix bug with args in table updates
- Fix some typos in documentation (thanks @leonardtan13)
- Fix a bug when multiple multi-column foreign keys exist
- Multiple internal changes to the generator to make it easier to write a custom entrypoint
- More robust testing of code generatio