Update README.

This commit is contained in:
go-jet 2019-09-21 15:48:14 +02:00
parent cbf98298bd
commit 4309b59975

View file

@ -46,7 +46,7 @@ https://medium.com/@go.jet/jet-5f3667efa0cc
* UPDATE `(SET, WHERE)`, * UPDATE `(SET, WHERE)`,
* DELETE `(WHERE, ORDER_BY, LIMIT)`, * DELETE `(WHERE, ORDER_BY, LIMIT)`,
* LOCK `(READ, WRITE)` * LOCK `(READ, WRITE)`
2) Auto-generated Data Model types - Go types mapped to database type (table or enum), used to store 2) Auto-generated Data Model types - Go types mapped to database type (table, view or enum), used to store
result of database queries. Can be combined to create desired query result destination. result of database queries. Can be combined to create desired query result destination.
3) Query execution with result mapping to arbitrary destination structure. 3) Query execution with result mapping to arbitrary destination structure.
@ -88,12 +88,13 @@ jet -source=PostgreSQL -host=localhost -port=5432 -user=jetuser -password=jetpas
```sh ```sh
Connecting to postgres database: host=localhost port=5432 user=jetuser password=jetpass dbname=jetdb sslmode=disable Connecting to postgres database: host=localhost port=5432 user=jetuser password=jetpass dbname=jetdb sslmode=disable
Retrieving schema information... Retrieving schema information...
FOUND 15 table(s), 1 enum(s) FOUND 15 table(s), 7 view(s), 1 enum(s)
Destination directory: ./gen/jetdb/dvds Cleaning up destination directory...
Cleaning up schema destination directory...
Generating table sql builder files... Generating table sql builder files...
Generating table model files... Generating view sql builder files...
Generating enum sql builder files... Generating enum sql builder files...
Generating table model files...
Generating view model files...
Generating enum model files... Generating enum model files...
Done Done
``` ```
@ -102,9 +103,9 @@ be omitted (both databases doesn't have schema support).
_*User has to have a permission to read information schema tables._ _*User has to have a permission to read information schema tables._
As command output suggest, Jet will: As command output suggest, Jet will:
- connect to postgres database and retrieve information about the _tables_ and _enums_ of `dvds` schema - connect to postgres database and retrieve information about the _tables_, _views_ and _enums_ of `dvds` schema
- delete everything in schema destination folder - `./gen/jetdb/dvds`, - delete everything in schema destination folder - `./gen/jetdb/dvds`,
- and finally generate SQL Builder and Model files for each schema table and enum. - and finally generate SQL Builder and Model files for each schema table, view and enum.
Generated files folder structure will look like this: Generated files folder structure will look like this:
@ -112,20 +113,24 @@ Generated files folder structure will look like this:
|-- gen # -path |-- gen # -path
| `-- jetdb # database name | `-- jetdb # database name
| `-- dvds # schema name | `-- dvds # schema name
| |-- enum # sql builder folder for enums | |-- enum # sql builder package for enums
| | |-- mpaa_rating.go | | |-- mpaa_rating.go
| |-- table # sql builder folder for tables | |-- table # sql builder package for tables
| |-- actor.go | |-- actor.go
| |-- address.go | |-- address.go
| |-- category.go | |-- category.go
| ... | ...
| |-- model # model files for each table and enum | |-- view # sql builder package for views
| |-- actor_info.go
| |-- film_list.go
| ...
| |-- model # data model types for each table, view and enum
| | |-- actor.go | | |-- actor.go
| | |-- address.go | | |-- address.go
| | |-- mpaa_rating.go | | |-- mpaa_rating.go
| | ... | | ...
``` ```
Types from `table` and `enum` are used to write type safe SQL in Go, and `model` types can be combined to store Types from `table`, `view` and `enum` are used to write type safe SQL in Go, and `model` types can be combined to store
results of the SQL queries. results of the SQL queries.
@ -167,7 +172,8 @@ stmt := SELECT(
Film.FilmID.ASC(), Film.FilmID.ASC(),
) )
``` ```
Package(dot) import is used so that statement would resemble as much as possible as native SQL. Note that every column has a type. String column `Language.Name` and `Category.Name` can be compared only with _Package(dot) import is used so that statement would resemble as much as possible as native SQL._
Note that every column has a type. String column `Language.Name` and `Category.Name` can be compared only with
string columns and expressions. `Actor.ActorID`, `FilmActor.ActorID`, `Film.Length` are integer columns string columns and expressions. `Actor.ActorID`, `FilmActor.ActorID`, `Film.Length` are integer columns
and can be compared only with integer columns and expressions. and can be compared only with integer columns and expressions.
@ -271,8 +277,9 @@ ORDER BY actor.actor_id ASC, film.film_id ASC;
Well formed SQL is just a first half of the job. Lets see how can we make some sense of result set returned executing Well formed SQL is just a first half of the job. Lets see how can we make some sense of result set returned executing
above statement. Usually this is the most complex and tedious work, but with Jet it is the easiest. above statement. Usually this is the most complex and tedious work, but with Jet it is the easiest.
First we have to create desired structure to store query result set. First we have to create desired structure to store query result.
This is done be combining autogenerated model types or it can be done manually(see [wiki](https://github.com/go-jet/jet/wiki/Scan-to-arbitrary-destination) for more information). This is done be combining autogenerated model types or it can be done
manually(see [wiki](https://github.com/go-jet/jet/wiki/Query-Result-Mapping-(QRM)) for more information).
Let's say this is our desired structure: Let's say this is our desired structure:
```go ```go
@ -287,8 +294,8 @@ var dest []struct {
} }
} }
``` ```
Because one actor can act in multiple films, `Films` field is a slice, and because each film belongs to one language `Films` field is a slice because one actor can act in multiple films, and because each film belongs to one language
`Langauge` field is just a single model struct. `Langauge` field is just a single model struct. `Film` can belong to multiple categories.
_*There is no limitation of how big or nested destination can be._ _*There is no limitation of how big or nested destination can be._
Now lets execute a above statement on open database connection (or transaction) db and store result into `dest`. Now lets execute a above statement on open database connection (or transaction) db and store result into `dest`.
@ -504,12 +511,14 @@ The biggest benefit is speed. Speed is improved in 3 major areas:
##### Speed of development ##### Speed of development
Writing SQL queries is much easier, because programmer has the help of SQL code completion and SQL type safety directly in Go. Writing SQL queries is faster and easier, because the developers have help of SQL code completion and SQL type safety directly from Go.
Writing code is much faster and code is more robust. Automatic scan to arbitrary structure removes a lot of headache and Automatic scan to arbitrary structure removes a lot of headache and boilerplate code needed to structure database query result.
boilerplate code needed to structure database query result.
##### Speed of execution ##### Speed of execution
While ORM libraries can introduce significant performance penalties due too number of round-trips to the database,
Jet will always perform much better, because of the single database call.
Common web and database server usually are not on the same physical machine, and there is some latency between them. Common web and database server usually are not on the same physical machine, and there is some latency between them.
Latency can vary from 5ms to 50+ms. In majority of cases query executed on database is simple query lasting no more than 1ms. Latency can vary from 5ms to 50+ms. In majority of cases query executed on database is simple query lasting no more than 1ms.
In those cases web server handler execution time is directly proportional to latency between server and database. In those cases web server handler execution time is directly proportional to latency between server and database.
@ -521,14 +530,14 @@ With Jet, handler time lost on latency between server and database is constant.
return result in one database call. Handler execution will be only proportional to the number of rows returned from database. return result in one database call. Handler execution will be only proportional to the number of rows returned from database.
ORM example replaced with jet will take just 30ms + 'result scan time' = 31ms (rough estimate). ORM example replaced with jet will take just 30ms + 'result scan time' = 31ms (rough estimate).
With Jet you can even join the whole database and store the whole structured result in in one query call. With Jet you can even join the whole database and store the whole structured result in one database call.
This is exactly what is being done in one of the tests: [TestJoinEverything](/tests/postgres/chinook_db_test.go#L40). This is exactly what is being done in one of the tests: [TestJoinEverything](/tests/postgres/chinook_db_test.go#L40).
The whole test database is joined and query result(~10,000 rows) is stored in a structured variable in less than 0.7s. The whole test database is joined and query result(~10,000 rows) is stored in a structured variable in less than 0.7s.
##### How quickly bugs are found ##### How quickly bugs are found
The most expensive bugs are the one on the production and the least expensive are those found during development. The most expensive bugs are the one on the production and the least expensive are those found during development.
With automatically generated type safe SQL not only queries are written faster but bugs are found sooner. With automatically generated type safe SQL, not only queries are written faster but bugs are found sooner.
Lets return to quick start example, and take closer look at a line: Lets return to quick start example, and take closer look at a line:
```go ```go
AND(Film.Length.GT(Int(180))), AND(Film.Length.GT(Int(180))),