Skip to content

Commit

Permalink
Merge pull request #10 from go-jet/develop
Browse files Browse the repository at this point in the history
Release 2.0.0: MySQL and MariaDB support.
  • Loading branch information
go-jet authored Aug 20, 2019
2 parents 3857715 + b7363a5 commit 361e360
Show file tree
Hide file tree
Showing 209 changed files with 12,505 additions and 467,893 deletions.
126 changes: 118 additions & 8 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,25 @@
# Check https://circleci.com/docs/2.0/language-go/ for more details
version: 2
jobs:
build:
build-postgres-and-mysql:
docker:
# specify the version
- image: circleci/golang:1.11

- image: circleci/postgres:10.6-alpine
- image: circleci/postgres:10.8-alpine
environment: # environment variables for primary container
POSTGRES_USER: jet
POSTGRES_PASSWORD: jet
POSTGRES_DB: jetdb

- image: circleci/mysql:8.0
command: [--default-authentication-plugin=mysql_native_password]
environment:
MYSQL_ROOT_PASSWORD: jet
MYSQL_DATABASE: dvds
MYSQL_USER: jet
MYSQL_PASSWORD: jet

working_directory: /go/src/github.com/go-jet/jet

environment: # environment variables for the build itself
Expand All @@ -22,12 +30,20 @@ jobs:
steps:
- checkout

# specify any bash command here prefixed with `run: `
- run:
name: Submodule init
command: |
git submodule init
git submodule update
cd ./tests/testdata && git fetch && git checkout master
- run:
name: Install dependencies
command: |
go get github.com/google/uuid
go get github.com/lib/pq
go get github.com/go-sql-driver/mysql
go get github.com/pkg/profile
go get gotest.tools/assert
Expand All @@ -48,14 +64,37 @@ jobs:
echo Failed waiting for Postgres && exit 1
- run:
name: Init Postgres database
name: Waiting for MySQL to be ready
command: |
cd tests
go run ./init/init.go
cd ..
for i in `seq 1 10`;
do
nc -z 127.0.0.1 3306 && echo Success && exit 0
echo -n .
sleep 1
done
echo Failed waiting for MySQL && exit 1
- run:
name: Install MySQL CLI;
command: |
sudo apt-get install default-mysql-client
- run:
name: Create MySQL user and databases
command: |
mysql -h 127.0.0.1 -u root -pjet -e "grant all privileges on *.* to 'jet'@'%';"
mysql -h 127.0.0.1 -u root -pjet -e "set global sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';"
mysql -h 127.0.0.1 -u jet -pjet -e "create database test_sample"
- run:
name: Init Postgres database
command: |
cd tests
go run ./init/init.go -testsuite all
cd ..
- run: mkdir -p $TEST_RESULTS
- run: go test -v . ./tests -coverpkg=github.com/go-jet/jet,github.com/go-jet/jet/execution/...,github.com/go-jet/jet/generator/...,github.com/go-jet/jet/internal/... -coverprofile=cover.out 2>&1 | go-junit-report > $TEST_RESULTS/results.xml
- run: go test -v ./... -coverpkg=github.com/go-jet/jet/postgres/...,github.com/go-jet/jet/mysql/...,github.com/go-jet/jet/execution/...,github.com/go-jet/jet/generator/...,github.com/go-jet/jet/internal/... -coverprofile=cover.out 2>&1 | go-junit-report > $TEST_RESULTS/results.xml

- run:
name: Upload code coverage
Expand All @@ -67,4 +106,75 @@ jobs:

- store_test_results: # Upload test results for display in Test Summary: https://circleci.com/docs/2.0/collect-test-data/
path: /tmp/test-results
build-mariadb:
docker:
# specify the version
- image: circleci/golang:1.11

- image: circleci/mariadb:10.3
command: [--default-authentication-plugin=mysql_native_password]
environment:
MYSQL_ROOT_PASSWORD: jet
MYSQL_DATABASE: dvds
MYSQL_USER: jet
MYSQL_PASSWORD: jet

working_directory: /go/src/github.com/go-jet/jet

environment: # environment variables for the build itself
TEST_RESULTS: /tmp/test-results # path to where test results will be saved

steps:
- checkout

- run:
name: Submodule init
command: |
git submodule init
git submodule update
cd ./tests/testdata && git fetch && git checkout master
- run:
name: Install dependencies
command: |
go get github.com/google/uuid
go get github.com/lib/pq
go get github.com/go-sql-driver/mysql
go get github.com/pkg/profile
go get gotest.tools/assert
go get github.com/davecgh/go-spew/spew
go get github.com/jstemmer/go-junit-report
go install github.com/go-jet/jet/cmd/jet
- run:
name: Install MySQL CLI;
command: |
sudo apt-get install default-mysql-client
- run:
name: Init MariaDB database
command: |
mysql -h 127.0.0.1 -u root -pjet -e "grant all privileges on *.* to 'jet'@'%';"
mysql -h 127.0.0.1 -u root -pjet -e "set global sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';"
mysql -h 127.0.0.1 -u jet -pjet -e "create database test_sample"
- run:
name: Init MariaDB database
command: |
cd tests
go run ./init/init.go -testsuite MariaDB
cd ..
- run:
name: Run MariaDB tests
command: |
go test -v ./tests/mysql/ -source=MariaDB
workflows:
version: 2
build_and_test:
jobs:
- build-postgres-and-mysql
- build-mariadb
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@

# Test files
gen
.gentestdata
.gentestdata
.tests/testdata/
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "tests/testdata"]
path = tests/testdata
url = https://github.com/go-jet/jet-test-data
81 changes: 46 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
# Jet

[![CircleCI](https://circleci.com/gh/go-jet/jet/tree/develop.svg?style=svg&circle-token=97f255c6a4a3ab6590ea2e9195eb3ebf9f97b4a7)](https://circleci.com/gh/go-jet/jet/tree/develop)
[![codecov](https://codecov.io/gh/go-jet/jet/branch/develop/graph/badge.svg)](https://codecov.io/gh/go-jet/jet)
[![CircleCI](https://circleci.com/gh/go-jet/jet/tree/master.svg?style=svg&circle-token=97f255c6a4a3ab6590ea2e9195eb3ebf9f97b4a7)](https://circleci.com/gh/go-jet/jet/tree/develop)
[![codecov](https://codecov.io/gh/go-jet/jet/branch/master/graph/badge.svg)](https://codecov.io/gh/go-jet/jet)
[![Go Report Card](https://goreportcard.com/badge/github.com/go-jet/jet)](https://goreportcard.com/report/github.com/go-jet/jet)
[![Documentation](https://godoc.org/github.com/go-jet/jet?status.svg)](http://godoc.org/github.com/go-jet/jet)
[![GitHub release](https://img.shields.io/github/release/go-jet/jet.svg)](https://github.com/go-jet/jet/releases)


Jet is a framework for writing type-safe SQL queries for PostgreSQL in Go, with ability to easily
convert database query result to desired arbitrary structure.
_*Support for additional databases will be added in future jet releases._
Jet is a framework for writing type-safe SQL queries in Go, with ability to easily
convert database query result into desired arbitrary object structure.
Jet currently supports `PostgreSQL`, `MySQL` and `MariaDB`. Future releases will add support for additional databases.

![jet](https://github.com/go-jet/jet/wiki/image/jet.png)
Jet is the easiest and fastest way to write complex SQL queries and map database query result
into complex object composition. __It is not an ORM.__

## Contents
- [Features](#features)
Expand All @@ -27,15 +30,19 @@ _*Support for additional databases will be added in future jet releases._
- [License](#license)

## Features
1) Auto-generated type-safe SQL Builder
- Types - boolean, integers(smallint, integer, bigint), floats(real, numeric, decimal, double precision),
strings(text, character, character varying), date, time(z), timestamp(z) and enums.
- Statements:
* SELECT (DISTINCT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, OFFSET, FOR, UNION, INTERSECT, EXCEPT, sub-queries)
* INSERT (VALUES, query, RETURNING),
* UPDATE (SET, WHERE, RETURNING),
* DELETE (WHERE, RETURNING),
* LOCK (IN, NOWAIT)
1) Auto-generated type-safe SQL Builder
- PostgreSQL:
* SELECT `(DISTINCT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, OFFSET, FOR, UNION, INTERSECT, EXCEPT, sub-queries)`
* INSERT `(VALUES, query, RETURNING)`,
* UPDATE `(SET, WHERE, RETURNING)`,
* DELETE `(WHERE, RETURNING)`,
* LOCK `(IN, NOWAIT)`
- MySQL and MariaDB:
* SELECT `(DISTINCT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, OFFSET, FOR, UNION, LOCK_IN_SHARE_MODE, sub-queries)`
* INSERT `(VALUES, query)`,
* UPDATE `(SET, WHERE)`,
* DELETE `(WHERE, ORDER_BY, LIMIT)`,
* LOCK `(READ, WRITE)`
2) Auto-generated Data Model types - Go types mapped to database type (table 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.
Expand Down Expand Up @@ -64,16 +71,16 @@ go install github.com/go-jet/jet/cmd/jet
Make sure GOPATH bin folder is added to the PATH environment variable.

### Quick Start
For this quick start example we will use sample _dvd rental_ database. Full database dump can be found in [./tests/init/data/dvds.sql](./tests/init/data/dvds.sql).
For this quick start example we will use PostgreSQL sample _'dvd rental'_ database. Full database dump can be found in [./tests/testdata/init/postgres/dvds.sql](./tests/testdata/init/postgres/dvds.sql).
Schema diagram of interest for example can be found [here](./examples/quick-start/diagram.png).

#### Generate SQL Builder and Model files
To generate jet SQL Builder and Data Model files from postgres database we need to call `jet` generator with postgres
To generate jet SQL Builder and Data Model files from postgres database, we need to call `jet` generator with postgres
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 -host=localhost -port=5432 -user=jetuser -password=jetpass -dbname=jetdb -schema=dvds -path=./gen
jet -source=PostgreSQL -host=localhost -port=5432 -user=jetuser -password=jetpass -dbname=jetdb -schema=dvds -path=./gen
```
```sh
Connecting to postgres database: host=localhost port=5432 user=jetuser password=jetpass dbname=jetdb sslmode=disable
Expand All @@ -87,7 +94,9 @@ Generating enum sql builder files...
Generating enum model files...
Done
```
_*User has to have a permission to read information schema tables_
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).
_*User has to have a permission to read information schema tables._

As command output suggest, Jet will:
- connect to postgres database and retrieve information about the _tables_ and _enums_ of `dvds` schema
Expand Down Expand Up @@ -116,15 +125,17 @@ Generated files folder structure will look like this:
Types from `table` and `enum` are used to write type safe SQL in Go, and `model` types can be combined to store
results of the SQL queries.



#### Lets write some SQL queries in Go

First we need to import jet and generated files from previous step:
```go
import (
// dot import so that Go code would resemble as much as native SQL
// dot import so go code would resemble as much as native SQL
// dot import is not mandatory
. "github.com/go-jet/jet"
. "github.com/go-jet/jet/examples/quick-start/gen/jetdb/dvds/table"
. "github.com/go-jet/jet/examples/quick-start/.gen/jetdb/dvds/table"
. "github.com/go-jet/jet/postgres"

"github.com/go-jet/jet/examples/quick-start/gen/jetdb/dvds/model"
)
Expand Down Expand Up @@ -153,13 +164,13 @@ stmt := SELECT(
Film.FilmID.ASC(),
)
```
With package(dot) import above statements looks almost the same 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
and can be compared only with integer columns and expressions.

__How to get parametrized SQL query from statement?__
```go
query, args, err := stmt.Sql()
query, args := stmt.Sql()
```
query - parametrized query\
args - parameters for the query
Expand Down Expand Up @@ -209,9 +220,9 @@ ORDER BY actor.actor_id ASC, film.film_id ASC;

__How to get debug SQL from statement?__
```go
debugSql, err := stmt.DebugSql()
debugSql := stmt.DebugSql()
```
debugSql - query string that can be copy pasted to sql editor and executed. It's not intended to be used in production.
debugSql - query string that can be copy pasted to sql editor and executed. __It's not intended to be used in production!!!__

<details>
<summary>Click to see debug sql</summary>
Expand Down Expand Up @@ -275,9 +286,9 @@ var dest []struct {
```
Because one actor can act in multiple films, `Films` field is a slice, and because each film belongs to one language
`Langauge` field is just a single model struct.
_*There is no limitation of how big or nested destination structure can be._
_*There is no limitation of how big or nested destination can be._

Now lets execute a above statement on open database connection db and store result into `dest`.
Now lets execute a above statement on open database connection (or transaction) db and store result into `dest`.

```go
err := stmt.Query(db, &dest)
Expand Down Expand Up @@ -485,12 +496,12 @@ 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:
What are the benefits of writing SQL in Go using Jet?
The biggest benefit is speed. Speed is improved in 3 major areas:

##### Speed of development

Writing SQL queries is much easier directly from Go, because programmer has the help of SQL code completion and SQL type safety directly in Go.
Writing SQL queries is much easier, because programmer has the help of SQL code completion and SQL type safety directly in Go.
Writing code is much faster and code is more robust. Automatic scan to arbitrary structure removes a lot of headache and
boilerplate code needed to structure database query result.

Expand All @@ -508,7 +519,7 @@ return result in one database call. Handler execution will be only proportional
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.
This is exactly what is being done in one of the tests: [TestJoinEverything](/tests/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.

##### How quickly bugs are found
Expand All @@ -529,14 +540,14 @@ Without Jet these bugs will have to be either caught by some test or by manual t

## Dependencies
At the moment Jet dependence only of:
- `github.com/google/uuid` _(Used for debug purposes and in data model files)_
- `github.com/lib/pq` _(Used by Jet to read information about database schema types)_

- `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/google/uuid` _(Used in data model files and for debug purposes)_

To run the tests, additional dependencies are required:
- `github.com/pkg/profile`
- `gotest.tools/assert`


## Versioning

[SemVer](http://semver.org/) is used for versioning. For the versions available, see the [releases](https://github.com/go-jet/jet/releases).
Expand Down
Loading

0 comments on commit 361e360

Please sign in to comment.