Update go doc.

This commit is contained in:
go-jet 2021-12-24 17:13:13 +01:00
parent b92af7ca6e
commit c0710bed29
3 changed files with 219 additions and 86 deletions

View file

@ -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
View file

@ -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

View file

@ -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) {