Skip to content

Commit 1a97493

Browse files
authored
Merge pull request #395 from stephenafamo/queries
Implement parsing of Postgres INSERT queries
2 parents 70f67e3 + 9aa9605 commit 1a97493

File tree

24 files changed

+1601
-1116
lines changed

24 files changed

+1601
-1116
lines changed

CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [v0.33.0] - 2025-04-26
9+
10+
### Added
11+
12+
- Added support to generate code for `INSERT` queries in `bobgen-psql`.
13+
- `clause.Confict` now takes `bob.Expression`, and the fields are now moved to a `clause.ConflictClause` struct.
14+
15+
### Changed
16+
17+
- Make grouped types in generated queries a type alias.
18+
19+
### Removed
20+
21+
- Remove `models.InsertWhere` in generated code since it is not correct.
22+
23+
### Fixed
24+
25+
- Fix issue with column query annotations in `bobgen-psql`.
26+
- Fix issue with parsing multiple queries in the same file in `bobgen-psql`.
27+
- Fix issue with correctly detecting the comment for the query annotation in `bobgen-psql`.
28+
- Use a transaction in generated query tests.
29+
- Account for LEFT, RIGHT and FULL joins when determining the nullability of a column.
30+
- Generate WHERE helpers for `ON CONFLICT` clauses.
31+
832
## [v0.32.0] - 2025-04-24
933

1034
### Added

clause/conflict.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,21 @@ import (
88
)
99

1010
type Conflict struct {
11+
Expression bob.Expression
12+
}
13+
14+
func (c *Conflict) SetConflict(conflict bob.Expression) {
15+
c.Expression = conflict
16+
}
17+
18+
type ConflictClause struct {
1119
Do string // DO NOTHING | DO UPDATE
1220
Target ConflictTarget
1321
Set
1422
Where
1523
}
1624

17-
func (c *Conflict) SetConflict(conflict Conflict) {
18-
*c = conflict
19-
}
20-
21-
func (c Conflict) WriteSQL(ctx context.Context, w io.Writer, d bob.Dialect, start int) ([]any, error) {
25+
func (c ConflictClause) WriteSQL(ctx context.Context, w io.Writer, d bob.Dialect, start int) ([]any, error) {
2226
w.Write([]byte("ON CONFLICT"))
2327

2428
args, err := bob.ExpressIf(ctx, w, d, start, c.Target, true, "", "")

dialect/psql/dialect/insert.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ func (i InsertQuery) WriteSQL(ctx context.Context, w io.Writer, d bob.Dialect, s
5656
}
5757
args = append(args, valArgs...)
5858

59-
conflictArgs, err := bob.ExpressIf(ctx, w, d, start+len(args), i.Conflict,
60-
i.Conflict.Do != "", "\n", "")
59+
conflictArgs, err := bob.ExpressIf(ctx, w, d, start+len(args), i.Conflict.Expression,
60+
i.Conflict.Expression != nil, "\n", "")
6161
if err != nil {
6262
return nil, err
6363
}

dialect/psql/im/qm.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ func Query(q bob.Query) bob.Mod[*dialect.InsertQuery] {
6565

6666
// The column to target. Will auto add brackets
6767
func OnConflict(columns ...any) mods.Conflict[*dialect.InsertQuery] {
68-
return mods.Conflict[*dialect.InsertQuery](func() clause.Conflict {
69-
return clause.Conflict{
68+
return mods.Conflict[*dialect.InsertQuery](func() clause.ConflictClause {
69+
return clause.ConflictClause{
7070
Target: clause.ConflictTarget{
7171
Columns: columns,
7272
},
@@ -75,8 +75,8 @@ func OnConflict(columns ...any) mods.Conflict[*dialect.InsertQuery] {
7575
}
7676

7777
func OnConflictOnConstraint(constraint string) mods.Conflict[*dialect.InsertQuery] {
78-
return mods.Conflict[*dialect.InsertQuery](func() clause.Conflict {
79-
return clause.Conflict{
78+
return mods.Conflict[*dialect.InsertQuery](func() clause.ConflictClause {
79+
return clause.ConflictClause{
8080
Target: clause.ConflictTarget{
8181
Constraint: constraint,
8282
},
@@ -92,17 +92,17 @@ func Returning(clauses ...any) bob.Mod[*dialect.InsertQuery] {
9292
// For use in ON CONFLICT DO UPDATE SET
9393
//========================================
9494

95-
func Set(sets ...bob.Expression) bob.Mod[*clause.Conflict] {
96-
return bob.ModFunc[*clause.Conflict](func(c *clause.Conflict) {
95+
func Set(sets ...bob.Expression) bob.Mod[*clause.ConflictClause] {
96+
return bob.ModFunc[*clause.ConflictClause](func(c *clause.ConflictClause) {
9797
c.Set.Set = append(c.Set.Set, internal.ToAnySlice(sets)...)
9898
})
9999
}
100100

101-
func SetCol(from string) mods.Set[*clause.Conflict] {
102-
return mods.Set[*clause.Conflict]{from}
101+
func SetCol(from string) mods.Set[*clause.ConflictClause] {
102+
return mods.Set[*clause.ConflictClause]{from}
103103
}
104104

105-
func SetExcluded(cols ...string) bob.Mod[*clause.Conflict] {
105+
func SetExcluded(cols ...string) bob.Mod[*clause.ConflictClause] {
106106
exprs := make([]any, 0, len(cols))
107107
for _, col := range cols {
108108
if col == "" {
@@ -115,13 +115,13 @@ func SetExcluded(cols ...string) bob.Mod[*clause.Conflict] {
115115
)
116116
}
117117

118-
return bob.ModFunc[*clause.Conflict](func(c *clause.Conflict) {
118+
return bob.ModFunc[*clause.ConflictClause](func(c *clause.ConflictClause) {
119119
c.Set.Set = append(c.Set.Set, exprs...)
120120
})
121121
}
122122

123-
func Where(e bob.Expression) bob.Mod[*clause.Conflict] {
124-
return bob.ModFunc[*clause.Conflict](func(c *clause.Conflict) {
123+
func Where(e bob.Expression) bob.Mod[*clause.ConflictClause] {
124+
return bob.ModFunc[*clause.ConflictClause](func(c *clause.ConflictClause) {
125125
c.Where.Conditions = append(c.Where.Conditions, e)
126126
})
127127
}

dialect/sqlite/dialect/insert.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ func (i InsertQuery) WriteSQL(ctx context.Context, w io.Writer, d bob.Dialect, s
5555
}
5656
args = append(args, valArgs...)
5757

58-
conflictArgs, err := bob.ExpressIf(ctx, w, d, start+len(args), i.Conflict,
59-
i.Conflict.Do != "", "\n", "")
58+
conflictArgs, err := bob.ExpressIf(ctx, w, d, start+len(args), i.Conflict.Expression,
59+
i.Conflict.Expression != nil, "\n", "")
6060
if err != nil {
6161
return nil, err
6262
}

dialect/sqlite/im/qm.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ func Query(q bob.Query) bob.Mod[*dialect.InsertQuery] {
7272
}
7373

7474
func OnConflict(columns ...any) mods.Conflict[*dialect.InsertQuery] {
75-
return mods.Conflict[*dialect.InsertQuery](func() clause.Conflict {
76-
return clause.Conflict{
75+
return mods.Conflict[*dialect.InsertQuery](func() clause.ConflictClause {
76+
return clause.ConflictClause{
7777
Target: clause.ConflictTarget{
7878
Columns: columns,
7979
},
@@ -89,17 +89,17 @@ func Returning(clauses ...any) bob.Mod[*dialect.InsertQuery] {
8989
// For use in ON CONFLICT DO UPDATE SET
9090
//========================================
9191

92-
func Set(sets ...bob.Expression) bob.Mod[*clause.Conflict] {
93-
return bob.ModFunc[*clause.Conflict](func(c *clause.Conflict) {
92+
func Set(sets ...bob.Expression) bob.Mod[*clause.ConflictClause] {
93+
return bob.ModFunc[*clause.ConflictClause](func(c *clause.ConflictClause) {
9494
c.Set.Set = append(c.Set.Set, internal.ToAnySlice(sets)...)
9595
})
9696
}
9797

98-
func SetCol(from string) mods.Set[*clause.Conflict] {
99-
return mods.Set[*clause.Conflict]{from}
98+
func SetCol(from string) mods.Set[*clause.ConflictClause] {
99+
return mods.Set[*clause.ConflictClause]{from}
100100
}
101101

102-
func SetExcluded(cols ...string) bob.Mod[*clause.Conflict] {
102+
func SetExcluded(cols ...string) bob.Mod[*clause.ConflictClause] {
103103
exprs := make([]any, 0, len(cols))
104104
for _, col := range cols {
105105
if col == "" {
@@ -112,13 +112,13 @@ func SetExcluded(cols ...string) bob.Mod[*clause.Conflict] {
112112
)
113113
}
114114

115-
return bob.ModFunc[*clause.Conflict](func(c *clause.Conflict) {
115+
return bob.ModFunc[*clause.ConflictClause](func(c *clause.ConflictClause) {
116116
c.Set.Set = append(c.Set.Set, exprs...)
117117
})
118118
}
119119

120-
func Where(e bob.Expression) bob.Mod[*clause.Conflict] {
121-
return bob.ModFunc[*clause.Conflict](func(c *clause.Conflict) {
120+
func Where(e bob.Expression) bob.Mod[*clause.ConflictClause] {
121+
return bob.ModFunc[*clause.ConflictClause](func(c *clause.ConflictClause) {
122122
c.Where.Conditions = append(c.Where.Conditions, e)
123123
})
124124
}

0 commit comments

Comments
 (0)