Skip to content

Commit 3b49cef

Browse files
author
Roman A. Grigorovich
committed
feat(psql merge): changelog.md updates
1 parent 46eb21a commit 3b49cef

File tree

1 file changed

+103
-93
lines changed

1 file changed

+103
-93
lines changed

CHANGELOG.md

Lines changed: 103 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12+
- Added PostgreSQL `MERGE` statement support with full syntax including:
13+
- `MERGE INTO ... USING ... ON ...` with table aliases and `ONLY` modifier
14+
- `WHEN MATCHED`, `WHEN NOT MATCHED`, `WHEN NOT MATCHED BY SOURCE` clauses
15+
- `UPDATE`, `INSERT`, `DELETE`, `DO NOTHING` actions
16+
- Support for `AND condition` in WHEN clauses
17+
- `OVERRIDING SYSTEM VALUE` and `OVERRIDING USER VALUE` for INSERT actions
18+
- `RETURNING` clause support (PostgreSQL 17+)
19+
- Added `psql.SetVersion`, `psql.GetVersion`, and `psql.VersionAtLeast` functions for context-based PostgreSQL version management
20+
- Added `Table.Merge()` method for ORM-style MERGE operations with automatic `RETURNING *` for PostgreSQL 17+
21+
- Added `mm` package with modifiers for building MERGE queries (`mm.Into`, `mm.Using`, `mm.WhenMatched`, `mm.WhenNotMatched`, `mm.WhenNotMatchedBySource`, etc.)
1222
- Added `PreloadCount` and `ThenLoadCount` to generate code for preloading and then loading counts for relationships. (thanks @jacobmolby)
1323
- MySQL support for insert queries executing loaders (e.g., `InsertThenLoad`, `InsertThenLoadCount`). (thanks @jacobmolby)
1424
- Added overwritable hooks that are run before the exec or scanning test of generated queries. This allows seeding data before the test runs.
@@ -89,20 +99,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8999
### Added
90100

91101
- Made code generation modular by relying on built-in plugins that can be enabled or disabled in the configuration.
92-
- `dbinfo`: Generates code for information about each database. Schemas, tables, columns, indexes, primary keys, foreign keys, unique constraints, and check constraints.
93-
- `enums`: Generates code for enums in a separate package, if there are any present.
94-
- `models`: Generates code for models. Depends on `enums`.
95-
- `factory`: Generates code for factories. Depends on `models`.
96-
- `dberrors`: Generates code for unique constraint errors. Depends on `models`.
97-
- `where`: Generates type-safe code for `WHERE` clauses in queries. Depends on `models`.
98-
- `loaders`: Adds templates to the `models` package to generate code for loaders e.g `models.SelectThenLoad.Table.Rel()`.
99-
- `joins`: Adds templates to the `models` package to generate code for joins e.g `models.SelectJoin.Table.LeftJoin.Rel`.
100-
- `queries`: Generates code for queries.
102+
- `dbinfo`: Generates code for information about each database. Schemas, tables, columns, indexes, primary keys, foreign keys, unique constraints, and check constraints.
103+
- `enums`: Generates code for enums in a separate package, if there are any present.
104+
- `models`: Generates code for models. Depends on `enums`.
105+
- `factory`: Generates code for factories. Depends on `models`.
106+
- `dberrors`: Generates code for unique constraint errors. Depends on `models`.
107+
- `where`: Generates type-safe code for `WHERE` clauses in queries. Depends on `models`.
108+
- `loaders`: Adds templates to the `models` package to generate code for loaders e.g `models.SelectThenLoad.Table.Rel()`.
109+
- `joins`: Adds templates to the `models` package to generate code for joins e.g `models.SelectJoin.Table.LeftJoin.Rel`.
110+
- `queries`: Generates code for queries.
101111
- Added new `types.Uint64` type that sends values to the database as strings. This is necessary because using `uint64` directly can cause an overflow if the value exceeds the maximum value of an `int64`. This is a limitation imposed by `database/sql/driver.Valuer` interface.
102112
- Added support for `pgvector` types during code generation.
103-
- `pgvector.Vector`
104-
- `pgvector.HalfVector`
105-
- `pgvector.SparseVector`
113+
- `pgvector.Vector`
114+
- `pgvector.HalfVector`
115+
- `pgvector.SparseVector`
106116

107117
### Changed
108118

@@ -142,8 +152,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
142152
- Added the `type_system` configuration option to determine how to generate null and optional values in the generated code.
143153
Possible options: `github.com/aarondl/opt`, `github.com/aarondl/opt/null` or `database/sql`. The default value is `github.com/aarondl/opt`.
144154
- When generating code for queries, The `All` method of the generated query will return a struct with nested fields instead of a flat struct.
145-
- columns with dots (`.`) are assumed to be a `to-many` nested field.
146-
- columns with double underscores (`__`) are assumed to be a `to-one` nested field.
155+
- columns with dots (`.`) are assumed to be a `to-many` nested field.
156+
- columns with double underscores (`__`) are assumed to be a `to-one` nested field.
147157
- Implement `--prefix` annotation in queries for `bobgen-psql`.
148158
- Add FromExisting**Rel** method to factories to create a template from an existing model. (thanks @dutow)
149159
- Add WithExisting**Rel** to factory mods to attach an existing model as a relationship. (thanks @dutow)
@@ -217,8 +227,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
217227
- Removed the `StdInterface` interface as it is unnecessary.
218228
- Remove redundant `orm.Model` interface.
219229
- Remove dependence on `github.com/aarondl/opt` in generated code.
220-
- Nullable values are now wrapped `database/sql.Null` with instead of `github.com/aarondl/opt/null.Val`.
221-
- Optional values are now represented as pointers instead of `github.com/aarondl/opt/omit.Val[T]`.
230+
- Nullable values are now wrapped `database/sql.Null` with instead of `github.com/aarondl/opt/null.Val`.
231+
- Optional values are now represented as pointers instead of `github.com/aarondl/opt/omit.Val[T]`.
222232
- Removed `in_generated_package` type configuration option. This was limited and could only indicate that the type is in the models package.
223233
Instead the full import path can now be used in the `imports` configuration option, and if it is in the same package as the generated code, the prefix will be automatically removed.
224234

@@ -240,15 +250,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
240250

241251
- Loaders are now generated as singular instead of plural. This feels more natural when using them in code.
242252

243-
```go
244-
// Before
245-
models.Preload.Users.Pilots()
246-
models.SelectThenLoad.Users.Pilots()
253+
```go
254+
// Before
255+
models.Preload.Users.Pilots()
256+
models.SelectThenLoad.Users.Pilots()
247257

248-
// After
249-
models.Preload.User.Pilots()
250-
models.SelectThenLoad.User.Pilot()
251-
```
258+
// After
259+
models.Preload.User.Pilots()
260+
models.SelectThenLoad.User.Pilot()
261+
```
252262

253263
## [v0.35.1] - 2025-05-27
254264

@@ -289,13 +299,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
289299
- Generated tests that required a database connection no longer create a new connection for each test. Instead it depends on a `testDB` connection that the user has to provide.
290300
- In the generated models, relationships for `ModelSlice` are now loaded using arrays to reduce the number of parameter in the query.
291301

292-
```sql
293-
-- Before
294-
SELECT * FROM pilots WHERE jet_id IN ($1, $2, $3, ...); -- Parameters increase with the number of pilots
302+
```sql
303+
-- Before
304+
SELECT * FROM pilots WHERE jet_id IN ($1, $2, $3, ...); -- Parameters increase with the number of pilots
295305
296-
-- After
297-
SELECT * FROM pilots WHERE jet_id IN (SELECT unnest(CAST($1 AS integer[])); -- Parameters are always 1
298-
```
306+
-- After
307+
SELECT * FROM pilots WHERE jet_id IN (SELECT unnest(CAST($1 AS integer[])); -- Parameters are always 1
308+
```
299309

300310
- In the generated model code, `Preload` is now a struct instead of multiple standaalone functions.
301311
It is now used like `Preload.User.Pilots()`, instead of `PreloadUserPilots()`.
@@ -466,9 +476,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
466476
- `UNION`, `INTERSECT` and `EXCEPT` mods now append to the query instead of replacing it.
467477
- Generated files now end with `.bob.go` instead of `.go` and are always cleaned up before generating new files. Singleton templates are now required to have a `.bob.go.tpl` extension.
468478
- The expected structure for templates have been changed:
469-
- Previously, singleton templates should be kept in a `singleton` folder. Now, any template not inside a folder is considered a singleton template.
470-
- Previoulsy, templates in the root folder are merged and run for each table. Now, this will happen to templates in the `table/` folder.
471-
- 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.
479+
- Previously, singleton templates should be kept in a `singleton` folder. Now, any template not inside a folder is considered a singleton template.
480+
- Previoulsy, templates in the root folder are merged and run for each table. Now, this will happen to templates in the `table/` folder.
481+
- 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.
472482
- Change `From` in `clause.Window` to `BasedOn` to avoid confusion with `FromPreceding` and `FromFollowing`. Also change `SetFrom` to `SetBasedOn`.
473483
- Embed `clause.OrderBy` in `clause.Window` to make it possible to reuse `OrderBy` mods in window definitions.
474484
- Change the `Definition` field in `clause.NamedWindow` from `any` to `clause.Window` for extra type safety.
@@ -523,32 +533,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
523533

524534
- `context.Context` is now passed to `Query.WriteQuery()` and `Expression.WriteSQL()` methods. This allows for more control over how the query is built and executed.
525535
This change made is possible to delete some hacks and simplify the codebase.
526-
- The `Name()` and `NameAs()` methods of Views/Tables no longer need the context argument since the context will be passed when writing the expression. The API then becomes cleaner.
527-
- Preloading mods no longer need to store a context internally. `SetLoadContext()` and `GetLoadContext()` have removed.
528-
- The `ToExpr` field in `orm.RelSide` which was used for preloading is no longer needed and has been removed.
536+
- The `Name()` and `NameAs()` methods of Views/Tables no longer need the context argument since the context will be passed when writing the expression. The API then becomes cleaner.
537+
- Preloading mods no longer need to store a context internally. `SetLoadContext()` and `GetLoadContext()` have removed.
538+
- The `ToExpr` field in `orm.RelSide` which was used for preloading is no longer needed and has been removed.
529539
- Moved `orm.Hooks` to `bob.Hooks` since it should not be limited to only ORM queries.
530540
- Moved `mods.QueryModFunc` to `bob.ModFunc` since it should be available to all packages.
531541
- The mod capability for `orm.Setter` is now reversed. It should now be a mod for Insert and have a method that returns a mod for Update.
532542
This makes more sense since one would at most use one setter during updates, but can use multiple setters in a bulk insert.
533543
- `table.InsertQ` has been renamed to `table.Insert`. The old implementation of `Insert` has been removed.
534544
The same functionality can be achieved in the following way:
535545

536-
```go
537-
//----------------------------------------------
538-
// OLD WAY
539-
//----------------------------------------------
540-
user, err := models.Users.Insert(ctx, db, setter) // insert one
541-
users, err := models.Users.InsertMany(ctx, db, setters...) // insert many
542-
543-
//----------------------------------------------
544-
// NEW WAY
545-
//----------------------------------------------
546-
user, err := models.Users.Insert(setter).One(ctx, db) // insert one
547-
users, err := models.Users.Insert(setters[0], setters[1]).All(ctx, db) // insert many
548-
549-
// For cases where you already have a slice of setters and you want to pass them all, you can use `bob.ToMods`
550-
users, err := models.Users.Insert(bob.ToMods(setters)).All(ctx, db) // insert many
551-
```
546+
```go
547+
//----------------------------------------------
548+
// OLD WAY
549+
//----------------------------------------------
550+
user, err := models.Users.Insert(ctx, db, setter) // insert one
551+
users, err := models.Users.InsertMany(ctx, db, setters...) // insert many
552+
553+
//----------------------------------------------
554+
// NEW WAY
555+
//----------------------------------------------
556+
user, err := models.Users.Insert(setter).One(ctx, db) // insert one
557+
users, err := models.Users.Insert(setters[0], setters[1]).All(ctx, db) // insert many
558+
559+
// For cases where you already have a slice of setters and you want to pass them all, you can use `bob.ToMods`
560+
users, err := models.Users.Insert(bob.ToMods(setters)).All(ctx, db) // insert many
561+
```
552562

553563
- `table.UpdateQ` has been renamed to `table.Update`. The old implementation of `Update` has been removed.
554564
The same functionality can be achieved by using `model.Update()` or `modelSlice.UpdateAll()`.
@@ -558,12 +568,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
558568
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.
559569
- `bob.Cache()` now requires an `Executor`. This is used to run any query hooks.
560570
- `bob.Prepare()` now requires a type parameter to be used to bind named arguments. The type can either be:
561-
- A struct with fields that match the named arguments in the query
562-
- A map with string keys. When supplied, the values in the map will be used to bind the named arguments in the query.
563-
- When there is only a single named argument, one of the following can be used:
564-
- A primitive type (int, bool, string, etc)
565-
- `time.Time`
566-
- Any type that implements `driver.Valuer`.
571+
- A struct with fields that match the named arguments in the query
572+
- A map with string keys. When supplied, the values in the map will be used to bind the named arguments in the query.
573+
- When there is only a single named argument, one of the following can be used:
574+
- A primitive type (int, bool, string, etc)
575+
- `time.Time`
576+
- Any type that implements `driver.Valuer`.
567577
- `Index` columns are no longer just strings, but are a struct to include more information such as the sort order.
568578

569579
### Removed
@@ -642,58 +652,58 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
642652
- Add PreloadAs PreloadOption to override the join alias when preloading a relationship with a left join. (thanks @daddz)
643653
- Add `AliasedAs()` method to `tableColumns` and `tableWhere` types to use a custom alias.
644654
- Add `AliasedAs()` method to generated relationship join mods. This is avaible in two places:
645-
- one to change the alias of the table being queried
655+
- one to change the alias of the table being queried
646656

647-
```go
648-
models.SelectJoins.Jets.AliasedAs("j").InnerJoin.Pilots(ctx)
649-
```
657+
```go
658+
models.SelectJoins.Jets.AliasedAs("j").InnerJoin.Pilots(ctx)
659+
```
650660

651-
- and the other to change the alias of the relationship.
661+
- and the other to change the alias of the relationship.
652662

653-
```go
654-
models.SelectJoins.Jets.InnerJoin.Pilots(ctx).AliasedAs("p")
655-
```
663+
```go
664+
models.SelectJoins.Jets.InnerJoin.Pilots(ctx).AliasedAs("p")
665+
```
656666

657667
- Add `fm` mods to all supported dialects (psql, mysql and sqlite). These are mods for functions and are used to modify the function call. For example:
658668

659-
```go
660-
// import "github.com/stephenafamo/bob/dialect/psql/fm"
661-
psql.F( "count", "*",)(fm.Filter(psql.Quote("status").EQ(psql.S("done"))))
662-
```
669+
```go
670+
// import "github.com/stephenafamo/bob/dialect/psql/fm"
671+
psql.F( "count", "*",)(fm.Filter(psql.Quote("status").EQ(psql.S("done"))))
672+
```
663673

664674
- Add `MustCreate`, `MustCreateMany`, `CreateOrFail` and `CreateManyOrFail` methods to generated factory Templates
665675

666676
### Changed
667677

668678
- 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.
669679

670-
```go
671-
// Before
672-
models.SelectJoins(ctx).Jets.InnerJoin.Pilots
673-
// After
674-
models.SelectJoins.Jets.InnerJoin.Pilots(ctx)
675-
```
680+
```go
681+
// Before
682+
models.SelectJoins(ctx).Jets.InnerJoin.Pilots
683+
// After
684+
models.SelectJoins.Jets.InnerJoin.Pilots(ctx)
685+
```
676686

677687
- Changed the `Count()` function on `Views` to clone the query instead of changing the existing one. This makes queries reusable and the `Count()` function to behave as one would expect.
678688

679-
```go
680-
// This now works as expected
681-
query := models.Jets.Query(ctx, db, /** list of various mods **/)
682-
count, err := query.Count()
683-
items, err := query.All()
684-
```
689+
```go
690+
// This now works as expected
691+
query := models.Jets.Query(ctx, db, /** list of various mods **/)
692+
count, err := query.Count()
693+
items, err := query.All()
694+
```
685695

686696
- Changed how functions are modified. Instead of chained methods, the `F()` starter now returns a function which can be called with mods:
687697

688-
```go
689-
// Before
690-
psql.F( "count", "*",).FilterWhere(psql.Quote("status").EQ(psql.S("done"))),
691-
// After
692-
// import "github.com/stephenafamo/bob/dialect/psql/fm"
693-
psql.F( "count", "*",)(fm.Filter(psql.Quote("status").EQ(psql.S("done")))),
694-
```
698+
```go
699+
// Before
700+
psql.F( "count", "*",).FilterWhere(psql.Quote("status").EQ(psql.S("done"))),
701+
// After
702+
// import "github.com/stephenafamo/bob/dialect/psql/fm"
703+
psql.F( "count", "*",)(fm.Filter(psql.Quote("status").EQ(psql.S("done")))),
704+
```
695705

696-
This makes it possible to support more queries.
706+
This makes it possible to support more queries.
697707

698708
- Use `netip.Addr` instead of `netip.Prefix` for Postgres `cidr` type.
699709
- Use `decimal.Decimal` instead of `string` for Postgres `money` type.
@@ -913,9 +923,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
913923

914924
- Make `View.Name()` return a dialect-specific expression
915925
- Improve `Debug` helpers.
916-
- `Debug` writes query output to stdout
917-
- `DebugToWriter` writes the query output to any `io.Writer` with a fallback to stdout.
918-
- `DebugToPrinter` prints the query with a given `bob.DebugPrinter`. Also falls back to stdout.
926+
- `Debug` writes query output to stdout
927+
- `DebugToWriter` writes the query output to any `io.Writer` with a fallback to stdout.
928+
- `DebugToPrinter` prints the query with a given `bob.DebugPrinter`. Also falls back to stdout.
919929
- Rename `OnlyColumns` to `PreloadOnly` and `ExceptColumns` to `PreloadExcept` to be more consistent with the newly added `PreloadWhere`.
920930
- `JoinChain.On` now takes Expressions instead of `any`.
921931
- `JoinChain.Using` now takes strings instead of `any`.

0 commit comments

Comments
 (0)