Skip to content

Commit

Permalink
Merge pull request #290 from stephenafamo/cross-join
Browse files Browse the repository at this point in the history
Allow aliases in CROSS JOIN
  • Loading branch information
stephenafamo authored Oct 25, 2024
2 parents 597c015 + 5ef45dd commit bad7a90
Show file tree
Hide file tree
Showing 16 changed files with 168 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- 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

## [v0.28.0] - 2024-06-25

Expand Down
4 changes: 2 additions & 2 deletions dialect/mysql/dialect/mods.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,11 @@ func RightJoin[Q Joinable](e any) JoinChain[Q] {
return Join[Q](clause.RightJoin, e)
}

func CrossJoin[Q Joinable](e any) bob.Mod[Q] {
func CrossJoin[Q Joinable](e any) JoinChain[Q] {
return Join[Q](clause.CrossJoin, e)
}

func StraightJoin[Q Joinable](e any) bob.Mod[Q] {
func StraightJoin[Q Joinable](e any) JoinChain[Q] {
return Join[Q](clause.StraightJoin, e)
}

Expand Down
4 changes: 2 additions & 2 deletions dialect/mysql/dm/qm.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,11 @@ func RightJoin(e any) dialect.JoinChain[*dialect.DeleteQuery] {
return dialect.RightJoin[*dialect.DeleteQuery](e)
}

func CrossJoin(e any) bob.Mod[*dialect.DeleteQuery] {
func CrossJoin(e any) dialect.JoinChain[*dialect.DeleteQuery] {
return dialect.CrossJoin[*dialect.DeleteQuery](e)
}

func StraightJoin(e any) bob.Mod[*dialect.DeleteQuery] {
func StraightJoin(e any) dialect.JoinChain[*dialect.DeleteQuery] {
return dialect.StraightJoin[*dialect.DeleteQuery](e)
}

Expand Down
4 changes: 2 additions & 2 deletions dialect/mysql/sm/qm.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,11 @@ func RightJoin(e any) dialect.JoinChain[*dialect.SelectQuery] {
return dialect.RightJoin[*dialect.SelectQuery](e)
}

func CrossJoin(e any) bob.Mod[*dialect.SelectQuery] {
func CrossJoin(e any) dialect.JoinChain[*dialect.SelectQuery] {
return dialect.CrossJoin[*dialect.SelectQuery](e)
}

func StraightJoin(e any) bob.Mod[*dialect.SelectQuery] {
func StraightJoin(e any) dialect.JoinChain[*dialect.SelectQuery] {
return dialect.StraightJoin[*dialect.SelectQuery](e)
}

Expand Down
4 changes: 2 additions & 2 deletions dialect/mysql/um/qm.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ func RightJoin(e any) dialect.JoinChain[*dialect.UpdateQuery] {
return dialect.RightJoin[*dialect.UpdateQuery](e)
}

func CrossJoin(e any) bob.Mod[*dialect.UpdateQuery] {
func CrossJoin(e any) dialect.JoinChain[*dialect.UpdateQuery] {
return dialect.CrossJoin[*dialect.UpdateQuery](e)
}

func StraightJoin(e any) bob.Mod[*dialect.UpdateQuery] {
func StraightJoin(e any) dialect.JoinChain[*dialect.UpdateQuery] {
return dialect.StraightJoin[*dialect.UpdateQuery](e)
}

Expand Down
25 changes: 23 additions & 2 deletions dialect/psql/dialect/mods.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,13 @@ func FullJoin[Q Joinable](e any) JoinChain[Q] {
return Join[Q](clause.FullJoin, e)
}

func CrossJoin[Q Joinable](e any) bob.Mod[Q] {
return Join[Q](clause.CrossJoin, e)
func CrossJoin[Q Joinable](e any) CrossJoinChain[Q] {
return CrossJoinChain[Q](func() clause.Join {
return clause.Join{
Type: clause.CrossJoin,
To: clause.From{Table: e},
}
})
}

type JoinChain[Q Joinable] func() clause.Join
Expand Down Expand Up @@ -198,6 +203,22 @@ func (j JoinChain[Q]) Using(using ...string) bob.Mod[Q] {
return mods.Join[Q](jo)
}

type CrossJoinChain[Q Joinable] func() clause.Join

func (j CrossJoinChain[Q]) Apply(q Q) {
q.AppendJoin(j())
}

func (j CrossJoinChain[Q]) As(alias string, columns ...string) bob.Mod[Q] {
jo := j()
jo.To.Alias = alias
jo.To.Columns = columns

return CrossJoinChain[Q](func() clause.Join {
return jo
})
}

type collation struct {
name string
}
Expand Down
2 changes: 1 addition & 1 deletion dialect/psql/dm/qm.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func FullJoin(e any) dialect.JoinChain[*dialect.DeleteQuery] {
return dialect.FullJoin[*dialect.DeleteQuery](e)
}

func CrossJoin(e any) bob.Mod[*dialect.DeleteQuery] {
func CrossJoin(e any) dialect.CrossJoinChain[*dialect.DeleteQuery] {
return dialect.CrossJoin[*dialect.DeleteQuery](e)
}

Expand Down
20 changes: 20 additions & 0 deletions dialect/psql/select_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,26 @@ WINDOW w AS (PARTITION BY depname ORDER BY salary)`,
),
ExpectedSQL: `SELECT id, name FROM users ORDER BY name COLLATE "bg-BG-x-icu" ASC`,
},
"with cross join": {
Query: psql.Select(
sm.Columns("id", "name", "type"),
sm.From("users").As("u"),
sm.CrossJoin(psql.Select(
sm.Columns("id", "type"),
sm.From("clients"),
sm.Where(psql.Quote("client_id").EQ(psql.Arg("123"))),
)).As("clients"),
sm.Where(psql.Quote("id").EQ(psql.Arg(100))),
),
ExpectedSQL: `SELECT id, name, type
FROM users AS u CROSS JOIN (
SELECT id, type
FROM clients
WHERE ("client_id" = $1)
) AS "clients"
WHERE ("id" = $2)`,
ExpectedArgs: []any{"123", 100},
},
}

testutils.RunTests(t, examples, formatter)
Expand Down
2 changes: 1 addition & 1 deletion dialect/psql/sm/qm.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func FullJoin(e any) dialect.JoinChain[*dialect.SelectQuery] {
return dialect.FullJoin[*dialect.SelectQuery](e)
}

func CrossJoin(e any) bob.Mod[*dialect.SelectQuery] {
func CrossJoin(e any) dialect.CrossJoinChain[*dialect.SelectQuery] {
return dialect.CrossJoin[*dialect.SelectQuery](e)
}

Expand Down
2 changes: 1 addition & 1 deletion dialect/psql/um/qm.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func FullJoin(e any) dialect.JoinChain[*dialect.UpdateQuery] {
return dialect.FullJoin[*dialect.UpdateQuery](e)
}

func CrossJoin(e any) bob.Mod[*dialect.UpdateQuery] {
func CrossJoin(e any) dialect.CrossJoinChain[*dialect.UpdateQuery] {
return dialect.CrossJoin[*dialect.UpdateQuery](e)
}

Expand Down
25 changes: 23 additions & 2 deletions dialect/sqlite/dialect/mods.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,22 @@ func (j JoinChain[Q]) Using(using ...string) bob.Mod[Q] {
return mods.Join[Q](jo)
}

type CrossJoinChain[Q Joinable] func() clause.Join

func (j CrossJoinChain[Q]) Apply(q Q) {
q.AppendJoin(j())
}

func (j CrossJoinChain[Q]) As(alias string, columns ...string) bob.Mod[Q] {
jo := j()
jo.To.Alias = alias
jo.To.Columns = columns

return CrossJoinChain[Q](func() clause.Join {
return jo
})
}

type Joinable interface{ AppendJoin(clause.Join) }

func Join[Q Joinable](typ string, e any) JoinChain[Q] {
Expand Down Expand Up @@ -226,8 +242,13 @@ func FullJoin[Q Joinable](e any) JoinChain[Q] {
return Join[Q](clause.FullJoin, e)
}

func CrossJoin[Q Joinable](e any) bob.Mod[Q] {
return Join[Q](clause.CrossJoin, e)
func CrossJoin[Q Joinable](e any) CrossJoinChain[Q] {
return CrossJoinChain[Q](func() clause.Join {
return clause.Join{
Type: clause.CrossJoin,
To: clause.From{Table: e},
}
})
}

type collation struct {
Expand Down
20 changes: 20 additions & 0 deletions dialect/sqlite/select_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,26 @@ func TestSelect(t *testing.T) {
),
ExpectedSQL: `SELECT id, name FROM users ORDER BY name COLLATE NOCASE ASC`,
},
"with cross join": {
Query: sqlite.Select(
sm.Columns("id", "name", "type"),
sm.From("users").As("u"),
sm.CrossJoin(sqlite.Select(
sm.Columns("id", "type"),
sm.From("clients"),
sm.Where(sqlite.Quote("client_id").EQ(sqlite.Arg("123"))),
)).As("clients"),
sm.Where(sqlite.Quote("id").EQ(sqlite.Arg(100))),
),
ExpectedSQL: `SELECT id, name, type
FROM users AS "u" CROSS JOIN (
SELECT id, type
FROM clients
WHERE ("client_id" = ?1)
) AS "clients"
WHERE ("id" = ?2)`,
ExpectedArgs: []any{"123", 100},
},
}

testutils.RunTests(t, examples, formatter)
Expand Down
2 changes: 1 addition & 1 deletion dialect/sqlite/sm/qm.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func FullJoin(e any) dialect.JoinChain[*dialect.SelectQuery] {
return dialect.FullJoin[*dialect.SelectQuery](e)
}

func CrossJoin(e any) bob.Mod[*dialect.SelectQuery] {
func CrossJoin(e any) dialect.CrossJoinChain[*dialect.SelectQuery] {
return dialect.CrossJoin[*dialect.SelectQuery](e)
}

Expand Down
2 changes: 1 addition & 1 deletion dialect/sqlite/um/qm.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func FullJoin(e any) dialect.JoinChain[*dialect.UpdateQuery] {
return dialect.FullJoin[*dialect.UpdateQuery](e)
}

func CrossJoin(e any) bob.Mod[*dialect.UpdateQuery] {
func CrossJoin(e any) dialect.CrossJoinChain[*dialect.UpdateQuery] {
return dialect.CrossJoin[*dialect.UpdateQuery](e)
}

Expand Down
34 changes: 34 additions & 0 deletions website/docs/query-builder/psql/examples/select.md
Original file line number Diff line number Diff line change
Expand Up @@ -310,3 +310,37 @@ psql.Select(
sm.OrderBy("name").Collate("bg-BG-x-icu").Asc(),
)
```

## With Cross Join

SQL:

```sql
SELECT id, name, type
FROM users AS u CROSS JOIN (
SELECT id, type
FROM clients
WHERE ("client_id" = $1)
) AS "clients"
WHERE ("id" = $2)
```

Args:

* `"123"`
* `100`

Code:

```go
psql.Select(
sm.Columns("id", "name", "type"),
sm.From("users").As("u"),
sm.CrossJoin(psql.Select(
sm.Columns("id", "type"),
sm.From("clients"),
sm.Where(psql.Quote("client_id").EQ(psql.Arg("123"))),
)).As("clients"),
sm.Where(psql.Quote("id").EQ(psql.Arg(100))),
)
```
34 changes: 34 additions & 0 deletions website/docs/query-builder/sqlite/examples/select.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,37 @@ sqlite.Select(
sm.OrderBy("name").Collate("NOCASE").Asc(),
)
```

## With Cross Join

SQL:

```sql
SELECT id, name, type
FROM users AS "u" CROSS JOIN (
SELECT id, type
FROM clients
WHERE ("client_id" = ?1)
) AS "clients"
WHERE ("id" = ?2)
```

Args:

* `"123"`
* `100`

Code:

```go
sqlite.Select(
sm.Columns("id", "name", "type"),
sm.From("users").As("u"),
sm.CrossJoin(sqlite.Select(
sm.Columns("id", "type"),
sm.From("clients"),
sm.Where(sqlite.Quote("client_id").EQ(sqlite.Arg("123"))),
)).As("clients"),
sm.Where(sqlite.Quote("id").EQ(sqlite.Arg(100))),
)
```

0 comments on commit bad7a90

Please sign in to comment.