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 support for
LISTENandNOTIFYstatements in PostgreSQL, includingbobgen-psqlparser support. Note:LISTENrequires a persistent connection and only registers the channel — receiving notifications must be implemented using your specific database driver. (thanks @manhrev) - Added
bobgen-psqlandbobgen-sqliteparser support for top-levelVALUESqueries. MySQL support is partial. (thanks @manhrev) - Generated
dberrorspackages now include generic and per-table check-constraint errors for PostgreSQL, matched by constraint name forpqandpgxdrivers. (thanks @keithbro-imx)
- PostgreSQL single-column slice relationship loaders (
<Parent>Slice.<Rel>) and batch counts (<Parent>Slice.LoadCount<Rel>) now de-duplicate the key array bound to= ANY($1)when the key column can contain duplicates (a non-unique foreign key). The array is only a semi-join filter, so query results are unchanged — a slice of 10,000 parents sharing 50 related rows now binds 50 keys instead of 10,000. Keys that are unique by construction (the parent's own primary key or a uniquely-constrained column) and key types not comparable with==keep the previous plain loop, decided at codegen time (#740). (thanks @sandonemaki) - Generated through-relationship loaders (
Load<Rel>) no longer apply every query mod twice (once against a throwaway query to detect whether the user set columns, then again for real). The default columns are now added by a deferredbob.ModFuncduring the single real application — the same patternView.Queryuses — and the join-key slice is pre-allocated to the parent slice length. Generated SQL is unchanged (#740). (thanks @sandonemaki)
- Fixed the PostgreSQL code generator's query parser renumbering each reference to a repeated query parameter (
$N) as a distinct argument (e.g.id = $1 OR parent_id = $1generating$1/$2), which changed the meaning of the generated query mods. Repeated$Nreferences now map to a single generated parameter (#745). (thanks @dmakushin)
- Added
bob.NextUniqueInt()for generating unique SQL alias suffixes (#719). (thanks @atzedus) - Code generation now emits a reflection-free
scan.Mapperper table (<table>ScanMapper) that scans each result column directly into the struct field by index. The mapper is passed to the model constructor, so every query built from a model —Query(), relationship loaders, andInsert/Update/DeletewithRETURNING— scans without the per-row reflection ofscan.StructMapper. (thanks @sandonemaki) - Generated
Wherestructs now include relationship filters under anRfield (e.g.SelectWhere.Pilots.R.HasJets(filters ...bob.Mod[*dialect.SelectQuery])) that filter rows by the existence of related rows, using a correlatedEXISTSsubquery (semi-join) built from the schema's relationship definitions. TheRnamespace mirrors the model struct and keeps the filters from colliding with column names. Unlike filtering throughSelectJoins, this does not multiply parent rows, soDISTINCTis not needed andCount()/LIMIT-based pagination stay correct (#722). (thanks @sandonemaki)
NewViewxandNewTablexin thepsql,mysqlandsqlitedialects now take ascan.Mapper[T]argument used for all queries built from the view/table. Passnilto keep the previous reflection-basedscan.StructMapperbehaviour.NewView/NewTableare unchanged. (thanks @sandonemaki)- JOIN a DISTINCT unnest(...) for composite-key relationship loaders & counts on PostgreSQL. (thanks @sandonemaki)
Preloadnow shares a single related-struct instance between all parent rows with the same join key, instead of building an identical instance per parent row — the same semantics asThenLoad. The emitted SQL is unchanged; construction, nested loader collection and mapping now run once per distinct related row, which significantly reduces time, allocations and retained memory on high-duplication workloads. Preloaded structs should be treated as read-only: code that mutates a preloaded struct and relies on each parent having its own copy must copy the struct first. (thanks @sandonemaki)
- Fixed an unused type import (e.g.
github.com/google/uuid) in generated models when the type is only referenced through optional wrapper expressions, such as m2m relationship helpers for a join table with auuidcolumn (#730). - Fixed the counts plugin's generated
Cfield reusing therelation_tagstruct tag, which collided with the relationsRfield and causedencoding/jsonto drop both fields when a real tag name was configured. TheCfield now uses a dedicatedrelation_tag_countconfig option (default"-"). (thanks @jacobmolby) - Fixed generated join alias suffixes using
randInt(), which could produce negative values whenmaphash.Hash.Sum64()overflowedint64(#719). Generated join mods now usebob.NextUniqueInt()instead. (thanks @atzedus) - Fixed
orm.Query.Clone()dropping theScanner, which madeAll/One/Cursor/Eachon a cloned query panic with a nil pointer dereference. (thanks @sandonemaki) - Fixed column_order on
*selectors in sql queries in postgres
- PostgreSQL single-column relationship loaders — both the slice relationship query (
<Parent>Slice.<Rel>) and the batch count method (<Parent>Slice.LoadCount<Rel>) — now filter related rows withcol = ANY($1)instead ofcol IN (SELECT unnest($1)), so the query planner can use an index scan on the foreign key instead of aSeq Scan + Hash Semi Join. Composite-key relationships keep the existingIN (SELECT unnest(...))form. (thanks @sandonemaki)
- Fixed PostgreSQL generated query parsing for CTEs that use table functions in
FROM(for exampleunnest(...) AS alias), which could incorrectly widen CTE spans and generate malformed query mods such as duplicated outerSELECTprojections.
- Added
column_orderconfig option (shared across all drivers). Set to"name"to sort generated model columns alphabetically, producing deterministic output regardless of the order migrations were applied to the database. Defaults to"ordinal"(previous behaviour: database physical column order). (thanks @cbarber)
- Change the closure in
RunInTxto passbob.Transactioninstead ofbob.Executor
With()on generated queries as a more ergonomic method to add mods on top of generated queries (thanks @daddz)- Added
Asc()/Desc()/...helpers tosm.OrderCombinedfor PostgreSQL/MySQL (thanks @daddz) - Added SQLite
um.SetCols(columns...)andim.SetCols(columns...)for tuple assignment inUPDATE ... SETandON CONFLICT DO UPDATE SET(.ToExprs(...),.ToRow(...),.ToQuery(...)). SQLite renders(cols) = (exprs...); PostgreSQLToRowstill emitsROW (...). MySQL does not support tuple assignment — use multipleSetColcalls. (thanks @atzedus)
- Fixed generated
Setter.Applywrapping all insert values in a singleExpressionFunc, which preventedBeforeInsertHooksand query mods from modifying individual column values viaq.Values.Vals[row][columnIndex]. Base and SQLite codegen templates now emit one expression per column (MySQL already did). Generated SQL is unchanged. (thanks @atzedus) - Fixed generated query mods for combined
UNION/INTERSECT/EXCEPTqueries dropping or misrouting the first operand'sORDER BY/LIMIT/OFFSETinto the combined-result clauses. (thanks @daddz) - Fixed PostgreSQL
um/dmstandalone join mods (InnerJoin,LeftJoin, etc.) applied beforeum.From(...)/dm.Using(...): the join is now preserved and attached to the nextFROM/USINGfrom_item instead of being dropped. (thanks @atzedus) - Fixed/extended PostgreSQL
sm.From(...): it now accepts variadic join chains (sm.From(table, joins...)), and inline joins are merged with already attached standalone joins when replacing the primaryFROMsource. (thanks @atzedus)
- Moved PostgreSQL
SetColstuple-assignment builder fromdialect/psql/dialect/setcols.goto sharedclause/setcols.go(clause.NewSetCols,clause.SetColsOptions). Dialect wrappers configureToRowviaSetColsOptions.RowPrefix(e.g."ROW"on PostgreSQL). (thanks @atzedus) EQcomparisons passed toSET/ON CONFLICT DO UPDATE SET/MERGE ... UPDATE SET/ MySQLON DUPLICATE KEY UPDATErender without the extra parentheses used inWHERE/ON(e.g.SET "users"."name" = $1vsWHERE ("users"."name" = $1)). (thanks @atzedus)NameAsExpr()on dialectView/Tabletypes (PostgreSQL, SQLite, MySQL) omits a redundantASwhen the alias matches the table name (for exampleFROM "users"instead ofFROM "users" AS "users"). An explicit alias is still emitted when a schema is set at construction (AS "schema.table"). (thanks @atzedus)- Generated slice relationship loaders (
<Parent>Slice.Load<Relationship>) now stitch loaded parents and children in O(N+M) using a map keyed by the join column, instead of the previous O(N×M) nested loop. This greatly speeds up eager-loading and then-loading relationships with many rows on both sides. The map is only used for single-column joins whose key type is comparable with==; composite keys and types with a customcompare_expr(e.g.[]byte) fall back to the original nested loop, so generated behaviour is unchanged. (thanks @sandonemaki)
- Added
Schema()method to dialectViewtypes (PostgreSQL, SQLite). (thanks @atzedus) - Added
ColumnsExpr()method onpsql.Viewfor parity with MySQL and SQLite views. (thanks @atzedus) - Added
um.SetExpr/im.SetExpr/mm.SetExprfor SET (and PostgreSQL/SQLiteim.SetExprforON CONFLICT DO UPDATE SET) when the assignment LHS is a qualified or arbitrary expression — passdialect.Quote(...)or anotherbob.Expression.SetCol/UpdateColremain for a single column name (quoted automatically). (thanks @atzedus)
- BREAKING:
psql.F/mysql.F/sqlite.Fanddialect.NewFunctionnow takename any(wasstring). The name is rendered withbob.Express; use a string for a literal function name ordialect.Quote("schema", "fn")for qualified names. (thanks @atzedus) - BREAKING:
mods.Setis now a struct with aCol anyfield instead of a[]stringalias.um.SetCol/im.SetCol/mm.SetCol(and MySQLim.UpdateCol) take astringcolumn name and quote it automatically; useSetExprfor qualified or arbitrary LHS expressions.SetCol(...).To(...)/SetExpr(...).To(...)implementbob.Expressionand can be passed toum.Set/im.Set/mm.Setto group several assignments in one mod (they still work as standalone query mods). (thanks @atzedus) - Godoc on
sm.With,sm.Window,wm.BasedOn(PostgreSQL, MySQL, SQLite) notes that CTE/window names are quoted as SQL identifiers. (thanks @atzedus) - BREAKING: PostgreSQL
sm.ForUpdate,sm.ForNoKeyUpdate,sm.ForShare, andsm.ForKeySharenow taketables ...anyinstead oftables ...string. Passpsql.Quote(...)(or anotherExpression) for each locked relation (#693). (thanks @atzedus) - BREAKING: MySQL
sm.ForUpdateandsm.ForSharenow taketables ...anywith the same semantics as PostgreSQL (mysql.Quote(...)when needed). (thanks @atzedus) - BREAKING:
clause.Lock.Tablesis now[]anyinstead of[]string(used byFOR UPDATE/FOR SHARErendering). (thanks @atzedus) - BREAKING:
View/TableName()now returns the bare table (or view) name asstring. In v0.44.0,Name()returned a dialectExpression(qualified table reference for SQL). That role moved to new methods:NameExpr()— whatName()did in v0.44.0 (on PostgreSQL and SQLite, respectsUseSchemawhen schema was generated empty)NameAsExpr()— whatNameAs()did in v0.44.0 (name plus table alias) Update manual call sites, codegen templates, and generated models:Users.Name()in SQL builders →Users.NameExpr(),Users.NameAs()→Users.NameAsExpr(); useUsers.Name()when you need the unqualified name string. On PostgreSQL and SQLite,Schema()still returns the schema when set.
- Codegen templates and
orm.Preloadnow useNameExpr()/NameAsExpr()instead ofName()/NameAs(). (thanks @atzedus)
- Fixed SQL identifier quoting in shared clause builders (CTE names/columns, window names,
ON CONFLICT ON CONSTRAINT,WHERE CURRENT OF, partition/index lists, SQLiteINDEXED BY) and PostgreSQLMERGE/SetColscolumn lists, table-function column definitions, and MySQL optimizer-hint table lists. Simple identifier parameters are quoted automatically; passdialect.Quote(...)for qualified names inanyslots (From,OnConflict,FOR UPDATE OF, etc.). (thanks @atzedus) - Fixed PostgreSQL
sm.Fromclearing joins already on theFROMfrom_item (e.g.sm.CrossJoinbeforesm.From) becauseSelectQuery.AppendTableRefreplaced the entire embeddedFROMtable ref. Existing joins are merged into the new primary table ref. (thanks @atzedus) - Fixed
FOR UPDATE/FOR SHAREOFtable lists: passpsql.Quote(...)/mysql.Quote(...)so names with spaces or qualification render correctly (#693). (thanks @atzedus) - Fixed MySQL
sm.From(...).UseIndex/ForceIndex/IgnoreIndex(and*ForJoin/*ForOrderBy/*ForGroupByvariants) not appearing in generated SQL becauseFromChain.Applydid not copyIndexHintsonto the query. (thanks @atzedus) - Fixed generated models using the wrong column qualifier when a table was constructed with a non-empty schema. Codegen previously passed
table.Keyintobuild*ColumnsandpkEQ/pkIN, but dialectView/Tabletypes useschema.tableasAlias()wheneverschemais set at construction. That mismatch produced SQL such as`users`.`id`inWHEREwhileFROMused`myapp`.`users` AS `myapp.users`(columns and primary-key expressions did not match the table alias fromNameAsExpr()). Templates now use atableColumnAliashelper:schema.namewhenschemais set, otherwisetable.Key. (thanks @atzedus) - Fix issue with overwriting unique constraints for tables beloging to other schemas. (thanks @eaglehuntt and @MD-Mushfiqur123)
- Added PostgreSQL
MERGEstatement SQL parser used for sql-to-code generation (thanks @atzedus) - Added
R.Loadedto generated models, a nested struct with oneboolper relationship that records whether each relationship has been loaded. This disambiguates "not loaded yet" from "loaded, but no related rows" for both to-one and to-many relations. Maintained automatically byLoad*,Preload,ThenLoad, factory builds, and to-oneAttach/Insertops. TheLoadedalias can be changed in the bob config. (thanks @jacobmolby) - Added
As(alias)method tobob.BaseQuery, allowing queries (e.g.mysql.Select(...)) to be aliased directly when used as subqueries in a column list. (thanks @jacobmolby) - Added columns API: generated column structures now provide
Name() stringmethod. (thanks @atzedus) - Added
expr.ColumnsExpraccessor methods:Parent() []string,AggFunc() [2]string,AliasPrefix() string, andAliasDisabled() bool.WithParent(...)now filters empty parts, and default rendering for plain unqualified columns no longer emits redundant self-aliases (e.g."name"instead of"name" AS "name"). (thanks @atzedus) - Added
bob.ParensOmitterinterface withShouldOmitParens() boolto let expressions opt out of automatic parenthesis wrapping in expression builders. (thanks @atzedus) - Added PostgreSQL
RETURNING WITH (OLD AS ..., NEW AS ...)support forINSERT,UPDATE,DELETE, andMERGEquery builders, including fluent modifiers:im/um/dm/mm.Returning(...).WithOldAs(...).WithNewAs(...). (thanks @atzedus)- Note:
bobgen-psqlsql-to-code parsing for this syntax is currently blocked by upstream PostgreSQL parser dependency support.
- Note:
- Added PostgreSQL
TABLESAMPLE ... REPEATABLE ...support via fluent modifiers onsm.From(...)and join chains. (thanks @atzedus) - Added PostgreSQL
JOIN ... USING (...) AS aliassupport viaUsingAs(alias, cols...)on psql join chains. (thanks @atzedus) - Added PostgreSQL GROUP BY grouping-element helpers:
sm.Grouping(...),sm.Rollup(...),sm.Cube(...), andsm.GroupingSets(...). (thanks @atzedus) - Added PostgreSQL
im.ConflictTarget(...)helper for composingON CONFLICTtarget items with optional.Collate(...)and.OpClass(...)modifiers. (thanks @atzedus) - Added PostgreSQL UPDATE/MERGE tuple-assignment helper
um.SetCols(columns...)with.ToExprs(...),.ToRow(...), and.ToQuery(...)support. (thanks @atzedus) - Added PostgreSQL UPDATE/DELETE
um.WhereCurrentOf(cursor)modifier to renderWHERE CURRENT OF <cursor>. (thanks @atzedus) - Added
expr.NoSepsentinel to join expressions without any separator. The existingexpr.Joindefault (space) is unchanged. (thanks @atzedus) - Added
im.Excluded(column)helper (PostgreSQL and SQLite) forON CONFLICT DO UPDATEassignments — renders asEXCLUDED."col"with no extra space, reused internally byim.SetExcluded(...)and available for direct use inim.SetCol(...).To(...). (thanks @atzedus) - Added PostgreSQL
psql.TableFunctions(funcs)andsm.FromFunction/um.FromFunction/dm.UsingFunctionhelpers that returnbob.Expressionfor table-functionfrom_itemsources (ROWS FROM (...)when multiple functions are given). (thanks @atzedus) - Added PostgreSQL
um.From(table, joins...)anddm.Using(table, joins...)variadic join arguments so each appendedfrom_itemcan include inlineINNER JOIN,LEFT JOIN,CROSS JOIN, etc. (JoinChainbuilders). (thanks @atzedus) - Added
bobgen-psqlsupport for multipleUPDATE ... FROM/DELETE ... USINGsources: sql-to-code emitsAppendTableRef(...)per parsedfrom_itemand resolves column sources from every item. (thanks @atzedus)
- BREAKING: Renamed the generated
ThenLoadCountvariable toSelectThenLoadCountfor naming consistency withSelectThenLoad/InsertThenLoad/UpdateThenLoad. Update call sites frommodels.ThenLoadCount.X.Ytomodels.SelectThenLoadCount.X.Y. (thanks @jacobmolby) - BREAKING:
mm.SetCol()now returnsmods.Set[*mm.UpdateAction]instead of a customSetChaintype..ToExpr(val)is replaced by.To(val), and.ToDefault()is replaced by.To(psql.Raw("DEFAULT"))..To()and.ToArg()work as before. (thanks @atzedus) - BREAKING:
mm.Recursive()has been removed. PostgreSQL does not supportWITH RECURSIVEin MERGE statements. (thanks @atzedus) - BREAKING: Generated
*Columnsaccessor fields now return a dialect-specific wrapper type (e.g.,userColumn) instead of plaindialect.Expression. The wrapper still implementsdialect.Expressionand avoids extra auto-parentheses in expression builders. Use.Expressiononly when you explicitly need the embedded expression value. (thanks @atzedus) - BREAKING: PostgreSQL
UPDATE ... FROMandDELETE ... USINGadditional sources now live inUpdateQuery.FromItems/DeleteQuery.UsingItemsinstead of the embeddedclause.TableRefon the query struct. Eachum.From(...)ordm.Using(...)appends one comma-separatedfrom_item(last call no longer wins). Useum.Table(...)/dm.From(...)for the update/delete target table. (thanks @atzedus) - BREAKING: PostgreSQL
sm.FromFunctionandum.FromFunctionno longer returnFromChainor applyFROM/USINGby themselves. They returnbob.Expressionand must be passed tosm.From(...)/um.From(...)/dm.Using(...)— e.g.sm.From(sm.FromFunction(psql.F("generate_series", 1, 3)()))instead ofsm.FromFunction(...). Aliasing and other table modifiers belong onsm.From(...)/um.From(...). (thanks @atzedus) - BREAKING: PostgreSQL
sm.From/FromChainforSelectQuerynow set theFROMsource viaAppendTableRef(replace semantics) instead ofSetTable/SetTableAliason afromableinterface. (thanks @atzedus) - BREAKING: PostgreSQL
um/dmjoin helpers (InnerJoin,LeftJoin,CrossJoin, etc.) returnJoinChain[*UpdateQuery]/JoinChain[*DeleteQuery]. Use them inum.From(table, joins...)/dm.Using(table, joins...), or as standalone mods afterum.From/dm.Using—AppendJointhen attaches to the lastFromItems/UsingItemsentry. (thanks @atzedus) - BREAKING: PostgreSQL psql join chain modifiers
.Natural(),.On(),.OnEQ(),.Using(), and.UsingAs()now returnJoinChainfor fluent chaining instead ofbob.Mod. (thanks @atzedus)
- Fix PostgreSQL
sm.Fromreplacing a previousFROMwithout clearing a stale table alias when the new source has no alias. (thanks @atzedus) - Fix PostgreSQL
sm.With(...).SearchBreadth(...)renderingSEARCH DEPTHinstead ofSEARCH BREADTHin CTE queries. (thanks @atzedus) - Avoid unnecessary imports in generated random factory code when a type has no random expression. (thanks @jay-babu)
- Fix missing base type imports (e.g.
github.com/google/uuid) in generated models when usingtype_system: "database/sql"anduuid_pkg: google, which could cause compile errors in generated many-to-many relation helpers. (thanks @atzedus) - Reuse parents when creating children in factory (thanks @abdusco)
- Added PostgreSQL
MERGEstatement support with full syntax including:MERGE INTO ... USING ... ON ...with table aliases andONLYmodifierWHEN MATCHED,WHEN NOT MATCHED,WHEN NOT MATCHED BY SOURCEclausesUPDATE,INSERT,DELETE,DO NOTHINGactions- Support for
AND conditionin WHEN clauses OVERRIDING SYSTEM VALUEandOVERRIDING USER VALUEfor INSERT actionsRETURNINGclause support (PostgreSQL 17+) (thanks @atzedus)- Note: the SQL parser used for sql-to-code generation does not yet support
MERGEstatements
- Added
psql.SetVersion,psql.GetVersion, andpsql.VersionAtLeastfunctions for context-based PostgreSQL version management (thanks @atzedus) - Added
Table.Merge()method for ORM-style MERGE operations with automaticRETURNING *for PostgreSQL 17+ (thanks @atzedus) - Added
mmpackage with modifiers for building MERGE queries (mm.Into,mm.Using,mm.WhenMatched,mm.WhenNotMatched,mm.WhenNotMatchedBySource, etc.) (thanks @atzedus) - 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) - Added a customizable MySQL and PostgreSQL driver image setting for
bobgen-sql. (thanks @manhrev) - Added support for Materialized Views in PostgreSQL code generation. (thanks @PudottaPommin)
- Fix
pgxdriverCommit()returningnilinstead ofpgx.ErrTxClosedwhen the transaction is already closed (e.g., rolled back by context expiry). This prevented silent data loss by correctly propagating the error to the caller. (thanks @wucm667) - Fix factory
FromExistingmethods causing stack overflow when models have bidirectional relationships populated (thanks @wucm667) - Fix self-referencing relationship back-references so generated preload/load helpers no longer create cyclic parent links. (thanks @atzedus)
- 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.qkg1.top/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.qkg1.top/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.qkg1.top/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.qkg1.top/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