diff --git a/README.md b/README.md index e79e86c..6a64753 100644 --- a/README.md +++ b/README.md @@ -9,17 +9,17 @@ Jet is a complete solution for efficient and high performance database access, consisting of type-safe SQL builder with code generation and automatic query result data mapping. -Jet currently supports `PostgreSQL`, `MySQL` and `MariaDB`. Future releases will add support for additional databases. +Jet currently supports `PostgreSQL`, `MySQL`, `MariaDB` and `SQLite`. Future releases will add support for additional databases. ![jet](https://github.com/go-jet/jet/wiki/image/jet.png) -Jet is the easiest and the fastest way to write complex type-safe SQL queries as a Go code and map database query result +Jet is the easiest, and the fastest way to write complex type-safe SQL queries as a Go code and map database query result into complex object composition. __It is not an ORM.__ ## Motivation https://medium.com/@go.jet/jet-5f3667efa0cc ## Contents - - [Features](#features) +- [Features](#features) - [Getting Started](#getting-started) - [Prerequisites](#prerequisites) - [Installation](#installation) @@ -33,24 +33,17 @@ https://medium.com/@go.jet/jet-5f3667efa0cc - [License](#license) ## Features - 1) Auto-generated type-safe SQL Builder - - PostgreSQL: - * [SELECT](https://github.com/go-jet/jet/wiki/SELECT) `(DISTINCT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, OFFSET, FOR, UNION, INTERSECT, EXCEPT, WINDOW, sub-queries)` - * [INSERT](https://github.com/go-jet/jet/wiki/INSERT) `(VALUES, MODEL, MODELS, QUERY, ON_CONFLICT, RETURNING)`, + 1) Auto-generated type-safe SQL Builder. Statements supported: + * [SELECT](https://github.com/go-jet/jet/wiki/SELECT) `(DISTINCT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, OFFSET, FOR, LOCK_IN_SHARE_MODE, UNION, INTERSECT, EXCEPT, WINDOW, sub-queries)` + * [INSERT](https://github.com/go-jet/jet/wiki/INSERT) `(VALUES, MODEL, MODELS, QUERY, ON_CONFLICT/ON_DUPLICATE_KEY_UPDATE, RETURNING)`, * [UPDATE](https://github.com/go-jet/jet/wiki/UPDATE) `(SET, MODEL, WHERE, RETURNING)`, - * [DELETE](https://github.com/go-jet/jet/wiki/DELETE) `(WHERE, RETURNING)`, - * [LOCK](https://github.com/go-jet/jet/wiki/LOCK) `(IN, NOWAIT)` - * [WITH](https://github.com/go-jet/jet/wiki/WITH) - - MySQL and MariaDB: - * [SELECT](https://github.com/go-jet/jet/wiki/SELECT) `(DISTINCT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, OFFSET, FOR, UNION, LOCK_IN_SHARE_MODE, WINDOW, sub-queries)` - * [INSERT](https://github.com/go-jet/jet/wiki/INSERT) `(VALUES, MODEL, MODELS, ON_DUPLICATE_KEY_UPDATE, query)`, - * [UPDATE](https://github.com/go-jet/jet/wiki/UPDATE) `(SET, MODEL, WHERE)`, - * [DELETE](https://github.com/go-jet/jet/wiki/DELETE) `(WHERE, ORDER_BY, LIMIT)`, - * [LOCK](https://github.com/go-jet/jet/wiki/LOCK) `(READ, WRITE)` + * [DELETE](https://github.com/go-jet/jet/wiki/DELETE) `(WHERE, ORDER_BY, LIMIT, RETURNING)`, + * [LOCK](https://github.com/go-jet/jet/wiki/LOCK) `(IN, NOWAIT)`, `(READ, WRITE)` * [WITH](https://github.com/go-jet/jet/wiki/WITH) + 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. - 3) Query execution with result mapping to arbitrary destination structure. + 3) Query execution with result mapping to arbitrary destination. ## Getting Started @@ -100,7 +93,7 @@ connection parameters and root destination folder path for generated files.\ Assuming we are running local postgres database, with user `jetuser`, user password `jetpass`, database `jetdb` and schema `dvds` we will use this command: ```sh -jet -source=PostgreSQL -host=localhost -port=5432 -user=jetuser -password=jetpass -dbname=jetdb -schema=dvds -path=./.gen +jet -dsn=postgresql://jetuser:jetpass@localhost:5432/jetdb -schema=dvds -path=./.gen ``` ```sh Connecting to postgres database: host=localhost port=5432 user=jetuser password=jetpass dbname=jetdb sslmode=disable @@ -115,8 +108,13 @@ Generating view model files... Generating enum model files... Done ``` -Procedure is similar for MySQL or MariaDB, except source should be replaced with `MySql` or `MariaDB` and schema name should -be omitted (both databases doesn't have schema support). +Procedure is similar for MySQL, MariaDB and SQLite. For instance: +```sh +jet -source=mysql -dsn="jet:jet@tcp(localhost:3306)/dvds" -path=./gen +jet -dsn="mariadb://jet:jet@tcp(localhost:3306)/dvds" -path=./gen # source flag can be omitted if data source is the same as database +jet -source=sqlite -dsn="/path/to/sqlite/database/file" -schema=dvds -path=./gen +jet -dsn="file:///path/to/sqlite/database/file" -schema=dvds -path=./gen # sqlite database assumed for 'file' data sources +``` _*User has to have a permission to read information schema tables._ As command output suggest, Jet will: @@ -189,7 +187,7 @@ stmt := SELECT( Film.FilmID.ASC(), ) ``` -_Package(dot) import is used so that statement would resemble as much as possible as native SQL._ +_Package(dot) import is used, so the statements 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 and can be compared only with integer columns and expressions. @@ -291,14 +289,14 @@ ORDER BY actor.actor_id ASC, film.film_id ASC; #### Execute query and store result -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. Let's 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. 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/Query-Result-Mapping-(QRM)) for more information). +by combining custom model files(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 made of autogenerated types: ```go var dest []struct { model.Actor @@ -315,7 +313,7 @@ var dest []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._ -Now lets execute a above statement on open database connection (or transaction) db and store result into `dest`. +Now lets execute above statement on open database connection (or transaction) db and store result into `dest`. ```go err := stmt.Query(db, &dest) @@ -524,7 +522,7 @@ found at project [Wiki](https://github.com/go-jet/jet/wiki) page. ## Benefits What are the benefits of writing SQL in Go using Jet? -The biggest benefit is speed. Speed is improved in 3 major areas: +The biggest benefit is speed. Speed is being improved in 3 major areas: ##### Speed of development @@ -538,32 +536,34 @@ Jet will always perform better as developers can write complex query and retriev Thus handler time lost on latency between server and database can be constant. Handler execution will be proportional only to the query complexity and the number of rows returned from database. -With Jet it is even possible to join the whole database and store the whole structured result in one database call. +With Jet, it is even possible to 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). 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 -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 discovered 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. Lets return to quick start example, and take closer look at a line: ```go AND(Film.Length.GT(Int(180))), ``` -Lets say someone changes column `length` to `duration` from `film` table. The next go build will fail at that line and +Let's say someone changes column `length` to `duration` from `film` table. The next go build will fail at that line, and the bug will be caught at compile time. -Lets say someone changes the type of `length` column to some non integer type. Build will also fail at the same line -because integer columns and expressions can be only compered to other integer columns and expressions. +Let's say someone changes the type of `length` column to some non integer type. Build will also fail at the same line +because integer columns and expressions can be only compared to other integer columns and expressions. -Build will also fail if someone removes `length` column from `film` table, because `Film` field will be omitted from SQL Builder and Model types, next time `jet` generator is run. +Build will also fail if someone removes `length` column from `film` table. `Film` field will be omitted from SQL Builder and Model types, +next time `jet` generator is run. Without Jet these bugs will have to be either caught by some test or by manual testing. ## Dependencies At the moment Jet dependence only of: -- `github.com/lib/pq` _(Used by jet generator to read information about database schema from `PostgreSQL`)_ -- `github.com/go-sql-driver/mysql` _(Used by jet generator to read information about database from `MySQL` and `MariaDB`)_ +- `github.com/lib/pq` _(Used by jet generator to read `PostgreSQL` database information)_ +- `github.com/go-sql-driver/mysql` _(Used by jet generator to read `MySQL` and `MariaDB` database information)_ +- `github.com/mattn/go-sqlite3` _(Used by jet generator to read `SQLite` database information)_ - `github.com/google/uuid` _(Used in data model files and for debug purposes)_ To run the tests, additional dependencies are required: