Update go doc.
This commit is contained in:
parent
b92af7ca6e
commit
c0710bed29
3 changed files with 219 additions and 86 deletions
24
README.md
24
README.md
|
|
@ -60,28 +60,26 @@ Use the command bellow to add jet as a dependency into `go.mod` project:
|
||||||
$ go get -u github.com/go-jet/jet/v2
|
$ go get -u github.com/go-jet/jet/v2
|
||||||
```
|
```
|
||||||
|
|
||||||
Jet generator can be installed in the following ways:
|
Jet generator can be installed in one of the following ways:
|
||||||
|
|
||||||
1) Install jet generator to GOPATH/bin folder:
|
1) (Go1.16+) Install jet generator using go install:
|
||||||
|
```sh
|
||||||
|
go install github.com/go-jet/jet/v2/cmd/jet@latest
|
||||||
|
```
|
||||||
|
|
||||||
|
2) Install jet generator to GOPATH/bin folder:
|
||||||
```sh
|
```sh
|
||||||
cd $GOPATH/src/ && GO111MODULE=off go get -u github.com/go-jet/jet/cmd/jet
|
cd $GOPATH/src/ && GO111MODULE=off go get -u github.com/go-jet/jet/cmd/jet
|
||||||
```
|
```
|
||||||
*Make sure GOPATH/bin folder is added to the PATH environment variable.*
|
|
||||||
|
|
||||||
2) Install jet generator into specific folder:
|
3) Install jet generator into specific folder:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
git clone https://github.com/go-jet/jet.git
|
git clone https://github.com/go-jet/jet.git
|
||||||
cd jet && go build -o dir_path ./cmd/jet
|
cd jet && go build -o dir_path ./cmd/jet
|
||||||
```
|
```
|
||||||
*Make sure `dir_path` folder is added to the PATH environment variable.*
|
*Make sure that the destination folder is added to the PATH environment variable.*
|
||||||
|
|
||||||
|
|
||||||
3) (Go1.16+) Install jet generator using go install:
|
|
||||||
```sh
|
|
||||||
go install github.com/go-jet/jet/v2/cmd/jet@latest
|
|
||||||
```
|
|
||||||
*Jet generator is installed to the directory named by the GOBIN environment variable,
|
|
||||||
which defaults to $GOPATH/bin or $HOME/go/bin if the GOPATH environment variable is not set.*
|
|
||||||
|
|
||||||
### Quick Start
|
### Quick Start
|
||||||
For this quick start example we will use PostgreSQL sample _'dvd rental'_ database. Full database dump can be found in
|
For this quick start example we will use PostgreSQL sample _'dvd rental'_ database. Full database dump can be found in
|
||||||
|
|
|
||||||
151
doc.go
151
doc.go
|
|
@ -1,77 +1,156 @@
|
||||||
/*
|
/*
|
||||||
Package jet is a framework for writing type-safe SQL queries in Go, with ability to easily convert database query
|
Package jet is a complete solution for efficient and high performance database access, consisting of type-safe SQL builder
|
||||||
result into desired arbitrary object structure.
|
with code generation and automatic query result data mapping.
|
||||||
|
Jet currently supports PostgreSQL, MySQL, MariaDB and SQLite. Future releases will add support for additional databases.
|
||||||
|
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
|
|
||||||
|
|
||||||
Use the bellow command to add jet as a dependency into go.mod project:
|
Use the command bellow to add jet as a dependency into go.mod project:
|
||||||
$ go get github.com/go-jet/jet/v2
|
$ go get -u github.com/go-jet/jet/v2
|
||||||
|
|
||||||
Use the bellow command to add jet as a dependency into GOPATH project:
|
Jet generator can be installed in one of the following ways:
|
||||||
$ go get -u github.com/go-jet/jet
|
|
||||||
|
|
||||||
Install jet generator to GOPATH bin folder. This will allow generating jet files from the command line.
|
1) (Go1.16+) Install jet generator using go install:
|
||||||
cd $GOPATH/src/ && GO111MODULE=off go get -u github.com/go-jet/jet/cmd/jet
|
go install github.com/go-jet/jet/v2/cmd/jet@latest
|
||||||
|
|
||||||
|
2) Install jet generator to GOPATH/bin folder:
|
||||||
|
cd $GOPATH/src/ && GO111MODULE=off go get -u github.com/go-jet/jet/cmd/jet
|
||||||
|
|
||||||
|
3) Install jet generator into specific folder:
|
||||||
|
git clone https://github.com/go-jet/jet.git
|
||||||
|
cd jet && go build -o dir_path ./cmd/jet
|
||||||
|
|
||||||
|
Make sure that the destination folder is added to the PATH environment variable.
|
||||||
|
|
||||||
Make sure GOPATH bin folder is added to the PATH environment variable.
|
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
|
|
||||||
|
|
||||||
Jet requires already defined database schema(with tables, enums etc), so that jet generator can generate SQL Builder
|
Jet requires already defined database schema(with tables, enums etc), so that jet generator can generate SQL Builder
|
||||||
and Model files. File generation is very fast, and can be added as every pre-build step.
|
and Model files. File generation is very fast, and can be added as every pre-build step.
|
||||||
Sample command:
|
Sample command:
|
||||||
jet -source=PostgreSQL -host=localhost -port=5432 -user=jet -password=pass -dbname=jetdb -schema=dvds -path=./gen
|
jet -dsn=postgresql://user:pass@localhost:5432/jetdb -schema=dvds -path=./.gen
|
||||||
|
|
||||||
Then next step is to import generated SQL Builder and Model files and write SQL queries in Go:
|
Before we can write SQL queries in Go, we need to import generated SQL builder and model types:
|
||||||
import . "some_path/.gen/jetdb/dvds/table"
|
import . "some_path/.gen/jetdb/dvds/table"
|
||||||
import "some_path/.gen/jetdb/dvds/model"
|
import "some_path/.gen/jetdb/dvds/model"
|
||||||
|
|
||||||
To write SQL queries for PostgreSQL import:
|
To write postgres SQL queries we import:
|
||||||
. "github.com/go-jet/jet/v2/postgres"
|
. "github.com/go-jet/jet/v2/postgres" // Dot import is used so that Go code resemble as much as native SQL. It is not mandatory.
|
||||||
|
|
||||||
To write SQL queries for MySQL and MariaDB import:
|
Then we can write the SQL query:
|
||||||
. "github.com/go-jet/jet/v2/mysql"
|
|
||||||
*Dot import is used so that Go code resemble as much as native SQL. Dot import is not mandatory.
|
|
||||||
|
|
||||||
Write SQL:
|
|
||||||
// sub-query
|
// sub-query
|
||||||
rRatingFilms := SELECT(
|
rRatingFilms :=
|
||||||
Film.FilmID,
|
SELECT(
|
||||||
Film.Title,
|
Film.FilmID,
|
||||||
Film.Rating,
|
Film.Title,
|
||||||
).
|
Film.Rating,
|
||||||
FROM(Film).
|
).FROM(
|
||||||
WHERE(Film.Rating.EQ(enum.FilmRating.R)).
|
Film,
|
||||||
AsTable("rFilms")
|
).WHERE(
|
||||||
|
Film.Rating.EQ(enum.FilmRating.R),
|
||||||
|
).AsTable("rFilms")
|
||||||
|
|
||||||
// export column from sub-query
|
// export column from sub-query
|
||||||
rFilmID := Film.FilmID.From(rRatingFilms)
|
rFilmID := Film.FilmID.From(rRatingFilms)
|
||||||
|
|
||||||
// main-query
|
// main-query
|
||||||
query := SELECT(
|
stmt :=
|
||||||
|
SELECT(
|
||||||
Actor.AllColumns,
|
Actor.AllColumns,
|
||||||
FilmActor.AllColumns,
|
FilmActor.AllColumns,
|
||||||
rRatingFilms.AllColumns(),
|
rRatingFilms.AllColumns(),
|
||||||
).
|
).FROM(
|
||||||
FROM(
|
|
||||||
rRatingFilms.
|
rRatingFilms.
|
||||||
INNER_JOIN(FilmActor, FilmActor.FilmID.EQ(rFilmID)).
|
INNER_JOIN(FilmActor, FilmActor.FilmID.EQ(rFilmID)).
|
||||||
INNER_JOIN(Actor, Actor.ActorID.EQ(FilmActor.ActorID)
|
INNER_JOIN(Actor, Actor.ActorID.EQ(FilmActor.ActorID)
|
||||||
).
|
).ORDER_BY(
|
||||||
ORDER_BY(rFilmID, Actor.ActorID)
|
rFilmID,
|
||||||
|
Actor.ActorID,
|
||||||
|
)
|
||||||
|
|
||||||
Store result into desired destination:
|
Now we can run the statement and store the result into desired destination:
|
||||||
var dest []struct {
|
var dest []struct {
|
||||||
model.Film
|
model.Film
|
||||||
|
|
||||||
Actors []model.Actor
|
Actors []model.Actor
|
||||||
}
|
}
|
||||||
|
|
||||||
err := query.Query(db, &dest)
|
err := stmt.Query(db, &dest)
|
||||||
|
|
||||||
Detail info about all features and use cases can be
|
We can print a statement to see SQL query and arguments sent to postgres server:
|
||||||
|
fmt.Println(stmt.Sql())
|
||||||
|
|
||||||
|
Output:
|
||||||
|
SELECT "rFilms"."film.film_id" AS "film.film_id",
|
||||||
|
"rFilms"."film.title" AS "film.title",
|
||||||
|
"rFilms"."film.rating" AS "film.rating",
|
||||||
|
actor.actor_id AS "actor.actor_id",
|
||||||
|
actor.first_name AS "actor.first_name",
|
||||||
|
actor.last_name AS "actor.last_name",
|
||||||
|
actor.last_update AS "actor.last_update",
|
||||||
|
film_actor.actor_id AS "film_actor.actor_id",
|
||||||
|
film_actor.film_id AS "film_actor.film_id",
|
||||||
|
film_actor.last_update AS "film_actor.last_update"
|
||||||
|
FROM (
|
||||||
|
SELECT film.film_id AS "film.film_id",
|
||||||
|
film.title AS "film.title",
|
||||||
|
film.rating AS "film.rating"
|
||||||
|
FROM dvds.film
|
||||||
|
WHERE film.rating = 'R'
|
||||||
|
) AS "rFilms"
|
||||||
|
INNER JOIN dvds.film_actor ON (film_actor.film_id = "rFilms"."film.film_id")
|
||||||
|
INNER JOIN dvds.actor ON (film_actor.actor_id = actor.actor_id)
|
||||||
|
WHERE "rFilms"."film.film_id" < $1
|
||||||
|
ORDER BY "rFilms"."film.film_id" ASC, actor.actor_id ASC;
|
||||||
|
[50]
|
||||||
|
|
||||||
|
If we print destination as json, we'll get:
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"FilmID": 8,
|
||||||
|
"Title": "Airport Pollock",
|
||||||
|
"Rating": "R",
|
||||||
|
"Actors": [
|
||||||
|
{
|
||||||
|
"ActorID": 55,
|
||||||
|
"FirstName": "Fay",
|
||||||
|
"LastName": "Kilmer",
|
||||||
|
"LastUpdate": "2013-05-26T14:47:57.62Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ActorID": 96,
|
||||||
|
"FirstName": "Gene",
|
||||||
|
"LastName": "Willis",
|
||||||
|
"LastUpdate": "2013-05-26T14:47:57.62Z"
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"FilmID": 17,
|
||||||
|
"Title": "Alone Trip",
|
||||||
|
"Actors": [
|
||||||
|
{
|
||||||
|
"ActorID": 3,
|
||||||
|
"FirstName": "Ed",
|
||||||
|
"LastName": "Chase",
|
||||||
|
"LastUpdate": "2013-05-26T14:47:57.62Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ActorID": 12,
|
||||||
|
"FirstName": "Karl",
|
||||||
|
"LastName": "Berry",
|
||||||
|
"LastUpdate": "2013-05-26T14:47:57.62Z"
|
||||||
|
},
|
||||||
|
...
|
||||||
|
...
|
||||||
|
]
|
||||||
|
|
||||||
|
Detail info about all statements, features and use cases can be
|
||||||
found at project wiki page - https://github.com/go-jet/jet/wiki.
|
found at project wiki page - https://github.com/go-jet/jet/wiki.
|
||||||
*/
|
*/
|
||||||
package jet
|
package jet
|
||||||
|
|
|
||||||
|
|
@ -864,62 +864,118 @@ LIMIT 1000;
|
||||||
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
//spew.Dump(films)
|
|
||||||
|
|
||||||
require.Equal(t, len(films), 1000)
|
require.Equal(t, len(films), 1000)
|
||||||
testutils.AssertDeepEqual(t, films[0], thesameLengthFilms{"Alien Center", "Iron Moon", 46})
|
testutils.AssertDeepEqual(t, films[0], thesameLengthFilms{"Alien Center", "Iron Moon", 46})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSubQuery(t *testing.T) {
|
func TestSubQuery(t *testing.T) {
|
||||||
expectedQuery := `
|
rRatingFilms :=
|
||||||
SELECT actor.actor_id AS "actor.actor_id",
|
SELECT(
|
||||||
|
Film.FilmID,
|
||||||
|
Film.Title,
|
||||||
|
Film.Rating,
|
||||||
|
).FROM(
|
||||||
|
Film,
|
||||||
|
).WHERE(
|
||||||
|
Film.Rating.EQ(enum.MpaaRating.R),
|
||||||
|
).AsTable("rFilms")
|
||||||
|
|
||||||
|
rFilmID := Film.FilmID.From(rRatingFilms)
|
||||||
|
|
||||||
|
stmt :=
|
||||||
|
SELECT(
|
||||||
|
rRatingFilms.AllColumns(),
|
||||||
|
Actor.AllColumns,
|
||||||
|
FilmActor.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
rRatingFilms.
|
||||||
|
INNER_JOIN(FilmActor, FilmActor.FilmID.EQ(rFilmID)).
|
||||||
|
INNER_JOIN(Actor, FilmActor.ActorID.EQ(Actor.ActorID)),
|
||||||
|
).WHERE(
|
||||||
|
rFilmID.LT(Int(50)),
|
||||||
|
).ORDER_BY(
|
||||||
|
rFilmID.ASC(),
|
||||||
|
Actor.ActorID.ASC(),
|
||||||
|
)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT "rFilms"."film.film_id" AS "film.film_id",
|
||||||
|
"rFilms"."film.title" AS "film.title",
|
||||||
|
"rFilms"."film.rating" AS "film.rating",
|
||||||
|
actor.actor_id AS "actor.actor_id",
|
||||||
actor.first_name AS "actor.first_name",
|
actor.first_name AS "actor.first_name",
|
||||||
actor.last_name AS "actor.last_name",
|
actor.last_name AS "actor.last_name",
|
||||||
actor.last_update AS "actor.last_update",
|
actor.last_update AS "actor.last_update",
|
||||||
film_actor.actor_id AS "film_actor.actor_id",
|
film_actor.actor_id AS "film_actor.actor_id",
|
||||||
film_actor.film_id AS "film_actor.film_id",
|
film_actor.film_id AS "film_actor.film_id",
|
||||||
film_actor.last_update AS "film_actor.last_update",
|
film_actor.last_update AS "film_actor.last_update"
|
||||||
"rFilms"."film.film_id" AS "film.film_id",
|
FROM (
|
||||||
"rFilms"."film.title" AS "film.title",
|
|
||||||
"rFilms"."film.rating" AS "film.rating"
|
|
||||||
FROM dvds.actor
|
|
||||||
INNER JOIN dvds.film_actor ON (actor.actor_id = film_actor.film_id)
|
|
||||||
INNER JOIN (
|
|
||||||
SELECT film.film_id AS "film.film_id",
|
SELECT film.film_id AS "film.film_id",
|
||||||
film.title AS "film.title",
|
film.title AS "film.title",
|
||||||
film.rating AS "film.rating"
|
film.rating AS "film.rating"
|
||||||
FROM dvds.film
|
FROM dvds.film
|
||||||
WHERE film.rating = 'R'
|
WHERE film.rating = 'R'
|
||||||
) AS "rFilms" ON (film_actor.film_id = "rFilms"."film.film_id");
|
) AS "rFilms"
|
||||||
`
|
INNER JOIN dvds.film_actor ON (film_actor.film_id = "rFilms"."film.film_id")
|
||||||
|
INNER JOIN dvds.actor ON (film_actor.actor_id = actor.actor_id)
|
||||||
|
WHERE "rFilms"."film.film_id" < 50
|
||||||
|
ORDER BY "rFilms"."film.film_id" ASC, actor.actor_id ASC;
|
||||||
|
`)
|
||||||
|
|
||||||
rRatingFilms := Film.
|
var dest []struct {
|
||||||
SELECT(
|
model.Film
|
||||||
Film.FilmID,
|
|
||||||
Film.Title,
|
|
||||||
Film.Rating,
|
|
||||||
).
|
|
||||||
WHERE(Film.Rating.EQ(enum.MpaaRating.R)).
|
|
||||||
AsTable("rFilms")
|
|
||||||
|
|
||||||
rFilmID := Film.FilmID.From(rRatingFilms)
|
Actors []model.Actor
|
||||||
|
}
|
||||||
query := Actor.
|
|
||||||
INNER_JOIN(FilmActor, Actor.ActorID.EQ(FilmActor.FilmID)).
|
|
||||||
INNER_JOIN(rRatingFilms, FilmActor.FilmID.EQ(rFilmID)).
|
|
||||||
SELECT(
|
|
||||||
Actor.AllColumns,
|
|
||||||
FilmActor.AllColumns,
|
|
||||||
rRatingFilms.AllColumns(),
|
|
||||||
)
|
|
||||||
|
|
||||||
testutils.AssertDebugStatementSql(t, query, expectedQuery)
|
|
||||||
|
|
||||||
dest := []model.Actor{}
|
|
||||||
|
|
||||||
err := query.Query(db, &dest)
|
|
||||||
|
|
||||||
|
err := stmt.Query(db, &dest)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
require.Len(t, dest, 10)
|
||||||
|
|
||||||
|
testutils.AssertJSON(t, dest[0], `
|
||||||
|
{
|
||||||
|
"FilmID": 8,
|
||||||
|
"Title": "Airport Pollock",
|
||||||
|
"Description": null,
|
||||||
|
"ReleaseYear": null,
|
||||||
|
"LanguageID": 0,
|
||||||
|
"RentalDuration": 0,
|
||||||
|
"RentalRate": 0,
|
||||||
|
"Length": null,
|
||||||
|
"ReplacementCost": 0,
|
||||||
|
"Rating": "R",
|
||||||
|
"LastUpdate": "0001-01-01T00:00:00Z",
|
||||||
|
"SpecialFeatures": null,
|
||||||
|
"Fulltext": "",
|
||||||
|
"Actors": [
|
||||||
|
{
|
||||||
|
"ActorID": 55,
|
||||||
|
"FirstName": "Fay",
|
||||||
|
"LastName": "Kilmer",
|
||||||
|
"LastUpdate": "2013-05-26T14:47:57.62Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ActorID": 96,
|
||||||
|
"FirstName": "Gene",
|
||||||
|
"LastName": "Willis",
|
||||||
|
"LastUpdate": "2013-05-26T14:47:57.62Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ActorID": 110,
|
||||||
|
"FirstName": "Susan",
|
||||||
|
"LastName": "Davis",
|
||||||
|
"LastUpdate": "2013-05-26T14:47:57.62Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ActorID": 138,
|
||||||
|
"FirstName": "Lucille",
|
||||||
|
"LastName": "Dee",
|
||||||
|
"LastUpdate": "2013-05-26T14:47:57.62Z"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSelectFunctions(t *testing.T) {
|
func TestSelectFunctions(t *testing.T) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue