Merge pull request #78 from go-jet/develop
Merge develop to master for 2.5.0 release
This commit is contained in:
commit
f0bf2c36b3
80 changed files with 2905 additions and 461 deletions
|
|
@ -6,7 +6,7 @@ jobs:
|
|||
build-postgres-and-mysql:
|
||||
docker:
|
||||
# specify the version
|
||||
- image: circleci/golang:1.11
|
||||
- image: circleci/golang:1.13
|
||||
|
||||
- image: circleci/postgres:10.8-alpine
|
||||
environment: # environment variables for primary container
|
||||
|
|
@ -14,7 +14,7 @@ jobs:
|
|||
POSTGRES_PASSWORD: jet
|
||||
POSTGRES_DB: jetdb
|
||||
|
||||
- image: circleci/mysql:8.0
|
||||
- image: circleci/mysql:8.0.16
|
||||
command: [--default-authentication-plugin=mysql_native_password]
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: jet
|
||||
|
|
@ -41,17 +41,9 @@ jobs:
|
|||
- 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 github.com/stretchr/testify/assert
|
||||
go get github.com/google/go-cmp/cmp
|
||||
go get github.com/davecgh/go-spew/spew
|
||||
cd /go/src/github.com/go-jet/jet
|
||||
go get github.com/jstemmer/go-junit-report
|
||||
|
||||
go install github.com/go-jet/jet/cmd/jet
|
||||
go build -o /home/circleci/.local/bin/jet ./cmd/jet/
|
||||
|
||||
- run:
|
||||
name: Waiting for Postgres to be ready
|
||||
|
|
@ -85,6 +77,7 @@ jobs:
|
|||
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"
|
||||
mysql -h 127.0.0.1 -u jet -pjet -e "create database dvds2"
|
||||
|
||||
- run:
|
||||
name: Init Postgres database
|
||||
|
|
@ -95,7 +88,7 @@ jobs:
|
|||
|
||||
|
||||
- run: mkdir -p $TEST_RESULTS
|
||||
- run: go test -v ./... -coverpkg=github.com/go-jet/jet/postgres/...,github.com/go-jet/jet/mysql/...,github.com/go-jet/jet/qrm/...,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: MY_SQL_SOURCE=MySQL go test -v ./... -coverpkg=github.com/go-jet/jet/postgres/...,github.com/go-jet/jet/mysql/...,github.com/go-jet/jet/qrm/...,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
|
||||
|
|
@ -110,7 +103,7 @@ jobs:
|
|||
build-mariadb:
|
||||
docker:
|
||||
# specify the version
|
||||
- image: circleci/golang:1.11
|
||||
- image: circleci/golang:1.13
|
||||
|
||||
- image: circleci/mariadb:10.3
|
||||
command: [--default-authentication-plugin=mysql_native_password]
|
||||
|
|
@ -138,17 +131,9 @@ jobs:
|
|||
- 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 github.com/stretchr/testify/assert
|
||||
go get github.com/google/go-cmp/cmp
|
||||
go get github.com/davecgh/go-spew/spew
|
||||
cd /go/src/github.com/go-jet/jet
|
||||
go get github.com/jstemmer/go-junit-report
|
||||
|
||||
go install github.com/go-jet/jet/cmd/jet
|
||||
go build -o /home/circleci/.local/bin/jet ./cmd/jet/
|
||||
|
||||
- run:
|
||||
name: Install MySQL CLI;
|
||||
|
|
@ -161,6 +146,7 @@ jobs:
|
|||
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"
|
||||
mysql -h 127.0.0.1 -u jet -pjet -e "create database dvds2"
|
||||
|
||||
- run:
|
||||
name: Init MariaDB database
|
||||
|
|
@ -172,7 +158,7 @@ jobs:
|
|||
- run:
|
||||
name: Run MariaDB tests
|
||||
command: |
|
||||
go test -v ./tests/mysql/ -source=MariaDB
|
||||
MY_SQL_SOURCE=MariaDB go test -v ./tests/mysql/
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
|
|
|
|||
49
README.md
49
README.md
|
|
@ -62,24 +62,33 @@ To install Jet package, you need to install Go and set your Go workspace first.
|
|||
|
||||
### 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:
|
||||
```sh
|
||||
$ go get -u github.com/go-jet/jet/v2
|
||||
```
|
||||
|
||||
Use the bellow command to add jet as a dependency into `GOPATH` project:
|
||||
|
||||
```sh
|
||||
$ 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.
|
||||
Jet generator can be install in the following ways:
|
||||
|
||||
1) Install jet generator to GOPATH/bin folder:
|
||||
```sh
|
||||
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.*
|
||||
|
||||
*Make sure GOPATH bin folder is added to the PATH environment variable.*
|
||||
2) Install jet generator to specific folder:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/go-jet/jet.git
|
||||
cd jet && go build -o dir_path ./cmd/jet
|
||||
```
|
||||
*Make sure `dir_path` 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
|
||||
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).
|
||||
|
|
@ -519,26 +528,17 @@ The biggest benefit is speed. Speed is improved in 3 major areas:
|
|||
|
||||
##### Speed of development
|
||||
|
||||
Writing SQL queries is faster and easier, because the developers have help of SQL code completion and SQL type safety directly from Go.
|
||||
Writing SQL queries is faster and easier as the developers have help of SQL code completion and SQL type safety directly from Go.
|
||||
Automatic scan to arbitrary structure removes a lot of headache and boilerplate code needed to structure database query result.
|
||||
|
||||
##### Speed of execution
|
||||
|
||||
While ORM libraries can introduce significant performance penalties due to number of round-trips to the database,
|
||||
Jet will always perform much better, because of the single database call.
|
||||
Jet will always perform better as developers can write complex query and retrieve result with a single database call.
|
||||
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.
|
||||
|
||||
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.
|
||||
In those cases web server handler execution time is directly proportional to latency between server and database.
|
||||
This is not such a big problem if handler calls database couple of times, but what if web server is using ORM to retrieve data from database.
|
||||
ORM sometimes can access the database once for every object needed. Now lets say latency is 30ms and there are 100
|
||||
different objects required from the database. This handler will last 3 seconds !!!.
|
||||
|
||||
With Jet, handler time lost on latency between server and database is constant. Because we can write complex query and
|
||||
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).
|
||||
|
||||
With Jet you can even 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.
|
||||
|
||||
|
|
@ -570,6 +570,7 @@ To run the tests, additional dependencies are required:
|
|||
- `github.com/pkg/profile`
|
||||
- `github.com/stretchr/testify`
|
||||
- `github.com/google/go-cmp`
|
||||
- `github.com/jackc/pgx/v4`
|
||||
|
||||
## Versioning
|
||||
|
||||
|
|
@ -577,5 +578,5 @@ To run the tests, additional dependencies are required:
|
|||
|
||||
## License
|
||||
|
||||
Copyright 2019-2020 Goran Bjelanovic
|
||||
Copyright 2019-2021 Goran Bjelanovic
|
||||
Licensed under the Apache License, Version 2.0.
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ func main() {
|
|||
|
||||
flag.Usage = func() {
|
||||
_, _ = fmt.Fprint(os.Stdout, `
|
||||
Jet generator 2.3.0
|
||||
Jet generator 2.5.0
|
||||
|
||||
Usage:
|
||||
-source string
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import (
|
|||
"github.com/go-jet/jet/v2/postgres"
|
||||
)
|
||||
|
||||
var Actor = newActorTable()
|
||||
var Actor = newActorTable("dvds", "actor", "")
|
||||
|
||||
type actorTable struct {
|
||||
postgres.Table
|
||||
|
|
@ -33,20 +33,23 @@ type ActorTable struct {
|
|||
}
|
||||
|
||||
// AS creates new ActorTable with assigned alias
|
||||
func (a *ActorTable) AS(alias string) *ActorTable {
|
||||
aliasTable := newActorTable()
|
||||
aliasTable.Table.AS(alias)
|
||||
return aliasTable
|
||||
func (a ActorTable) AS(alias string) *ActorTable {
|
||||
return newActorTable(a.SchemaName(), a.TableName(), alias)
|
||||
}
|
||||
|
||||
func newActorTable() *ActorTable {
|
||||
// Schema creates new ActorTable with assigned schema name
|
||||
func (a ActorTable) FromSchema(schemaName string) *ActorTable {
|
||||
return newActorTable(schemaName, a.TableName(), a.Alias())
|
||||
}
|
||||
|
||||
func newActorTable(schemaName, tableName, alias string) *ActorTable {
|
||||
return &ActorTable{
|
||||
actorTable: newActorTableImpl("dvds", "actor"),
|
||||
EXCLUDED: newActorTableImpl("", "excluded"),
|
||||
actorTable: newActorTableImpl(schemaName, tableName, alias),
|
||||
EXCLUDED: newActorTableImpl("", "excluded", ""),
|
||||
}
|
||||
}
|
||||
|
||||
func newActorTableImpl(schemaName, tableName string) actorTable {
|
||||
func newActorTableImpl(schemaName, tableName, alias string) actorTable {
|
||||
var (
|
||||
ActorIDColumn = postgres.IntegerColumn("actor_id")
|
||||
FirstNameColumn = postgres.StringColumn("first_name")
|
||||
|
|
@ -57,7 +60,7 @@ func newActorTableImpl(schemaName, tableName string) actorTable {
|
|||
)
|
||||
|
||||
return actorTable{
|
||||
Table: postgres.NewTable(schemaName, tableName, allColumns...),
|
||||
Table: postgres.NewTable(schemaName, tableName, alias, allColumns...),
|
||||
|
||||
//Columns
|
||||
ActorID: ActorIDColumn,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import (
|
|||
"github.com/go-jet/jet/v2/postgres"
|
||||
)
|
||||
|
||||
var Category = newCategoryTable()
|
||||
var Category = newCategoryTable("dvds", "category", "")
|
||||
|
||||
type categoryTable struct {
|
||||
postgres.Table
|
||||
|
|
@ -32,20 +32,23 @@ type CategoryTable struct {
|
|||
}
|
||||
|
||||
// AS creates new CategoryTable with assigned alias
|
||||
func (a *CategoryTable) AS(alias string) *CategoryTable {
|
||||
aliasTable := newCategoryTable()
|
||||
aliasTable.Table.AS(alias)
|
||||
return aliasTable
|
||||
func (a CategoryTable) AS(alias string) *CategoryTable {
|
||||
return newCategoryTable(a.SchemaName(), a.TableName(), alias)
|
||||
}
|
||||
|
||||
func newCategoryTable() *CategoryTable {
|
||||
// Schema creates new CategoryTable with assigned schema name
|
||||
func (a CategoryTable) FromSchema(schemaName string) *CategoryTable {
|
||||
return newCategoryTable(schemaName, a.TableName(), a.Alias())
|
||||
}
|
||||
|
||||
func newCategoryTable(schemaName, tableName, alias string) *CategoryTable {
|
||||
return &CategoryTable{
|
||||
categoryTable: newCategoryTableImpl("dvds", "category"),
|
||||
EXCLUDED: newCategoryTableImpl("", "excluded"),
|
||||
categoryTable: newCategoryTableImpl(schemaName, tableName, alias),
|
||||
EXCLUDED: newCategoryTableImpl("", "excluded", ""),
|
||||
}
|
||||
}
|
||||
|
||||
func newCategoryTableImpl(schemaName, tableName string) categoryTable {
|
||||
func newCategoryTableImpl(schemaName, tableName, alias string) categoryTable {
|
||||
var (
|
||||
CategoryIDColumn = postgres.IntegerColumn("category_id")
|
||||
NameColumn = postgres.StringColumn("name")
|
||||
|
|
@ -55,7 +58,7 @@ func newCategoryTableImpl(schemaName, tableName string) categoryTable {
|
|||
)
|
||||
|
||||
return categoryTable{
|
||||
Table: postgres.NewTable(schemaName, tableName, allColumns...),
|
||||
Table: postgres.NewTable(schemaName, tableName, alias, allColumns...),
|
||||
|
||||
//Columns
|
||||
CategoryID: CategoryIDColumn,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import (
|
|||
"github.com/go-jet/jet/v2/postgres"
|
||||
)
|
||||
|
||||
var Film = newFilmTable()
|
||||
var Film = newFilmTable("dvds", "film", "")
|
||||
|
||||
type filmTable struct {
|
||||
postgres.Table
|
||||
|
|
@ -42,20 +42,23 @@ type FilmTable struct {
|
|||
}
|
||||
|
||||
// AS creates new FilmTable with assigned alias
|
||||
func (a *FilmTable) AS(alias string) *FilmTable {
|
||||
aliasTable := newFilmTable()
|
||||
aliasTable.Table.AS(alias)
|
||||
return aliasTable
|
||||
func (a FilmTable) AS(alias string) *FilmTable {
|
||||
return newFilmTable(a.SchemaName(), a.TableName(), alias)
|
||||
}
|
||||
|
||||
func newFilmTable() *FilmTable {
|
||||
// Schema creates new FilmTable with assigned schema name
|
||||
func (a FilmTable) FromSchema(schemaName string) *FilmTable {
|
||||
return newFilmTable(schemaName, a.TableName(), a.Alias())
|
||||
}
|
||||
|
||||
func newFilmTable(schemaName, tableName, alias string) *FilmTable {
|
||||
return &FilmTable{
|
||||
filmTable: newFilmTableImpl("dvds", "film"),
|
||||
EXCLUDED: newFilmTableImpl("", "excluded"),
|
||||
filmTable: newFilmTableImpl(schemaName, tableName, alias),
|
||||
EXCLUDED: newFilmTableImpl("", "excluded", ""),
|
||||
}
|
||||
}
|
||||
|
||||
func newFilmTableImpl(schemaName, tableName string) filmTable {
|
||||
func newFilmTableImpl(schemaName, tableName, alias string) filmTable {
|
||||
var (
|
||||
FilmIDColumn = postgres.IntegerColumn("film_id")
|
||||
TitleColumn = postgres.StringColumn("title")
|
||||
|
|
@ -75,7 +78,7 @@ func newFilmTableImpl(schemaName, tableName string) filmTable {
|
|||
)
|
||||
|
||||
return filmTable{
|
||||
Table: postgres.NewTable(schemaName, tableName, allColumns...),
|
||||
Table: postgres.NewTable(schemaName, tableName, alias, allColumns...),
|
||||
|
||||
//Columns
|
||||
FilmID: FilmIDColumn,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import (
|
|||
"github.com/go-jet/jet/v2/postgres"
|
||||
)
|
||||
|
||||
var FilmActor = newFilmActorTable()
|
||||
var FilmActor = newFilmActorTable("dvds", "film_actor", "")
|
||||
|
||||
type filmActorTable struct {
|
||||
postgres.Table
|
||||
|
|
@ -32,20 +32,23 @@ type FilmActorTable struct {
|
|||
}
|
||||
|
||||
// AS creates new FilmActorTable with assigned alias
|
||||
func (a *FilmActorTable) AS(alias string) *FilmActorTable {
|
||||
aliasTable := newFilmActorTable()
|
||||
aliasTable.Table.AS(alias)
|
||||
return aliasTable
|
||||
func (a FilmActorTable) AS(alias string) *FilmActorTable {
|
||||
return newFilmActorTable(a.SchemaName(), a.TableName(), alias)
|
||||
}
|
||||
|
||||
func newFilmActorTable() *FilmActorTable {
|
||||
// Schema creates new FilmActorTable with assigned schema name
|
||||
func (a FilmActorTable) FromSchema(schemaName string) *FilmActorTable {
|
||||
return newFilmActorTable(schemaName, a.TableName(), a.Alias())
|
||||
}
|
||||
|
||||
func newFilmActorTable(schemaName, tableName, alias string) *FilmActorTable {
|
||||
return &FilmActorTable{
|
||||
filmActorTable: newFilmActorTableImpl("dvds", "film_actor"),
|
||||
EXCLUDED: newFilmActorTableImpl("", "excluded"),
|
||||
filmActorTable: newFilmActorTableImpl(schemaName, tableName, alias),
|
||||
EXCLUDED: newFilmActorTableImpl("", "excluded", ""),
|
||||
}
|
||||
}
|
||||
|
||||
func newFilmActorTableImpl(schemaName, tableName string) filmActorTable {
|
||||
func newFilmActorTableImpl(schemaName, tableName, alias string) filmActorTable {
|
||||
var (
|
||||
ActorIDColumn = postgres.IntegerColumn("actor_id")
|
||||
FilmIDColumn = postgres.IntegerColumn("film_id")
|
||||
|
|
@ -55,7 +58,7 @@ func newFilmActorTableImpl(schemaName, tableName string) filmActorTable {
|
|||
)
|
||||
|
||||
return filmActorTable{
|
||||
Table: postgres.NewTable(schemaName, tableName, allColumns...),
|
||||
Table: postgres.NewTable(schemaName, tableName, alias, allColumns...),
|
||||
|
||||
//Columns
|
||||
ActorID: ActorIDColumn,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import (
|
|||
"github.com/go-jet/jet/v2/postgres"
|
||||
)
|
||||
|
||||
var FilmCategory = newFilmCategoryTable()
|
||||
var FilmCategory = newFilmCategoryTable("dvds", "film_category", "")
|
||||
|
||||
type filmCategoryTable struct {
|
||||
postgres.Table
|
||||
|
|
@ -32,20 +32,23 @@ type FilmCategoryTable struct {
|
|||
}
|
||||
|
||||
// AS creates new FilmCategoryTable with assigned alias
|
||||
func (a *FilmCategoryTable) AS(alias string) *FilmCategoryTable {
|
||||
aliasTable := newFilmCategoryTable()
|
||||
aliasTable.Table.AS(alias)
|
||||
return aliasTable
|
||||
func (a FilmCategoryTable) AS(alias string) *FilmCategoryTable {
|
||||
return newFilmCategoryTable(a.SchemaName(), a.TableName(), alias)
|
||||
}
|
||||
|
||||
func newFilmCategoryTable() *FilmCategoryTable {
|
||||
// Schema creates new FilmCategoryTable with assigned schema name
|
||||
func (a FilmCategoryTable) FromSchema(schemaName string) *FilmCategoryTable {
|
||||
return newFilmCategoryTable(schemaName, a.TableName(), a.Alias())
|
||||
}
|
||||
|
||||
func newFilmCategoryTable(schemaName, tableName, alias string) *FilmCategoryTable {
|
||||
return &FilmCategoryTable{
|
||||
filmCategoryTable: newFilmCategoryTableImpl("dvds", "film_category"),
|
||||
EXCLUDED: newFilmCategoryTableImpl("", "excluded"),
|
||||
filmCategoryTable: newFilmCategoryTableImpl(schemaName, tableName, alias),
|
||||
EXCLUDED: newFilmCategoryTableImpl("", "excluded", ""),
|
||||
}
|
||||
}
|
||||
|
||||
func newFilmCategoryTableImpl(schemaName, tableName string) filmCategoryTable {
|
||||
func newFilmCategoryTableImpl(schemaName, tableName, alias string) filmCategoryTable {
|
||||
var (
|
||||
FilmIDColumn = postgres.IntegerColumn("film_id")
|
||||
CategoryIDColumn = postgres.IntegerColumn("category_id")
|
||||
|
|
@ -55,7 +58,7 @@ func newFilmCategoryTableImpl(schemaName, tableName string) filmCategoryTable {
|
|||
)
|
||||
|
||||
return filmCategoryTable{
|
||||
Table: postgres.NewTable(schemaName, tableName, allColumns...),
|
||||
Table: postgres.NewTable(schemaName, tableName, alias, allColumns...),
|
||||
|
||||
//Columns
|
||||
FilmID: FilmIDColumn,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import (
|
|||
"github.com/go-jet/jet/v2/postgres"
|
||||
)
|
||||
|
||||
var Language = newLanguageTable()
|
||||
var Language = newLanguageTable("dvds", "language", "")
|
||||
|
||||
type languageTable struct {
|
||||
postgres.Table
|
||||
|
|
@ -32,20 +32,23 @@ type LanguageTable struct {
|
|||
}
|
||||
|
||||
// AS creates new LanguageTable with assigned alias
|
||||
func (a *LanguageTable) AS(alias string) *LanguageTable {
|
||||
aliasTable := newLanguageTable()
|
||||
aliasTable.Table.AS(alias)
|
||||
return aliasTable
|
||||
func (a LanguageTable) AS(alias string) *LanguageTable {
|
||||
return newLanguageTable(a.SchemaName(), a.TableName(), alias)
|
||||
}
|
||||
|
||||
func newLanguageTable() *LanguageTable {
|
||||
// Schema creates new LanguageTable with assigned schema name
|
||||
func (a LanguageTable) FromSchema(schemaName string) *LanguageTable {
|
||||
return newLanguageTable(schemaName, a.TableName(), a.Alias())
|
||||
}
|
||||
|
||||
func newLanguageTable(schemaName, tableName, alias string) *LanguageTable {
|
||||
return &LanguageTable{
|
||||
languageTable: newLanguageTableImpl("dvds", "language"),
|
||||
EXCLUDED: newLanguageTableImpl("", "excluded"),
|
||||
languageTable: newLanguageTableImpl(schemaName, tableName, alias),
|
||||
EXCLUDED: newLanguageTableImpl("", "excluded", ""),
|
||||
}
|
||||
}
|
||||
|
||||
func newLanguageTableImpl(schemaName, tableName string) languageTable {
|
||||
func newLanguageTableImpl(schemaName, tableName, alias string) languageTable {
|
||||
var (
|
||||
LanguageIDColumn = postgres.IntegerColumn("language_id")
|
||||
NameColumn = postgres.StringColumn("name")
|
||||
|
|
@ -55,7 +58,7 @@ func newLanguageTableImpl(schemaName, tableName string) languageTable {
|
|||
)
|
||||
|
||||
return languageTable{
|
||||
Table: postgres.NewTable(schemaName, tableName, allColumns...),
|
||||
Table: postgres.NewTable(schemaName, tableName, alias, allColumns...),
|
||||
|
||||
//Columns
|
||||
LanguageID: LanguageIDColumn,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import (
|
|||
"github.com/go-jet/jet/v2/postgres"
|
||||
)
|
||||
|
||||
var ActorInfo = newActorInfoTable()
|
||||
var ActorInfo = newActorInfoTable("dvds", "actor_info", "")
|
||||
|
||||
type actorInfoTable struct {
|
||||
postgres.Table
|
||||
|
|
@ -33,20 +33,23 @@ type ActorInfoTable struct {
|
|||
}
|
||||
|
||||
// AS creates new ActorInfoTable with assigned alias
|
||||
func (a *ActorInfoTable) AS(alias string) *ActorInfoTable {
|
||||
aliasTable := newActorInfoTable()
|
||||
aliasTable.Table.AS(alias)
|
||||
return aliasTable
|
||||
func (a ActorInfoTable) AS(alias string) *ActorInfoTable {
|
||||
return newActorInfoTable(a.SchemaName(), a.TableName(), alias)
|
||||
}
|
||||
|
||||
func newActorInfoTable() *ActorInfoTable {
|
||||
// Schema creates new ActorInfoTable with assigned schema name
|
||||
func (a ActorInfoTable) FromSchema(schemaName string) *ActorInfoTable {
|
||||
return newActorInfoTable(schemaName, a.TableName(), a.Alias())
|
||||
}
|
||||
|
||||
func newActorInfoTable(schemaName, tableName, alias string) *ActorInfoTable {
|
||||
return &ActorInfoTable{
|
||||
actorInfoTable: newActorInfoTableImpl("dvds", "actor_info"),
|
||||
EXCLUDED: newActorInfoTableImpl("", "excluded"),
|
||||
actorInfoTable: newActorInfoTableImpl(schemaName, tableName, alias),
|
||||
EXCLUDED: newActorInfoTableImpl("", "excluded", ""),
|
||||
}
|
||||
}
|
||||
|
||||
func newActorInfoTableImpl(schemaName, tableName string) actorInfoTable {
|
||||
func newActorInfoTableImpl(schemaName, tableName, alias string) actorInfoTable {
|
||||
var (
|
||||
ActorIDColumn = postgres.IntegerColumn("actor_id")
|
||||
FirstNameColumn = postgres.StringColumn("first_name")
|
||||
|
|
@ -57,7 +60,7 @@ func newActorInfoTableImpl(schemaName, tableName string) actorInfoTable {
|
|||
)
|
||||
|
||||
return actorInfoTable{
|
||||
Table: postgres.NewTable(schemaName, tableName, allColumns...),
|
||||
Table: postgres.NewTable(schemaName, tableName, alias, allColumns...),
|
||||
|
||||
//Columns
|
||||
ActorID: ActorIDColumn,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import (
|
|||
"github.com/go-jet/jet/v2/postgres"
|
||||
)
|
||||
|
||||
var CustomerList = newCustomerListTable()
|
||||
var CustomerList = newCustomerListTable("dvds", "customer_list", "")
|
||||
|
||||
type customerListTable struct {
|
||||
postgres.Table
|
||||
|
|
@ -38,20 +38,23 @@ type CustomerListTable struct {
|
|||
}
|
||||
|
||||
// AS creates new CustomerListTable with assigned alias
|
||||
func (a *CustomerListTable) AS(alias string) *CustomerListTable {
|
||||
aliasTable := newCustomerListTable()
|
||||
aliasTable.Table.AS(alias)
|
||||
return aliasTable
|
||||
func (a CustomerListTable) AS(alias string) *CustomerListTable {
|
||||
return newCustomerListTable(a.SchemaName(), a.TableName(), alias)
|
||||
}
|
||||
|
||||
func newCustomerListTable() *CustomerListTable {
|
||||
// Schema creates new CustomerListTable with assigned schema name
|
||||
func (a CustomerListTable) FromSchema(schemaName string) *CustomerListTable {
|
||||
return newCustomerListTable(schemaName, a.TableName(), a.Alias())
|
||||
}
|
||||
|
||||
func newCustomerListTable(schemaName, tableName, alias string) *CustomerListTable {
|
||||
return &CustomerListTable{
|
||||
customerListTable: newCustomerListTableImpl("dvds", "customer_list"),
|
||||
EXCLUDED: newCustomerListTableImpl("", "excluded"),
|
||||
customerListTable: newCustomerListTableImpl(schemaName, tableName, alias),
|
||||
EXCLUDED: newCustomerListTableImpl("", "excluded", ""),
|
||||
}
|
||||
}
|
||||
|
||||
func newCustomerListTableImpl(schemaName, tableName string) customerListTable {
|
||||
func newCustomerListTableImpl(schemaName, tableName, alias string) customerListTable {
|
||||
var (
|
||||
IDColumn = postgres.IntegerColumn("id")
|
||||
NameColumn = postgres.StringColumn("name")
|
||||
|
|
@ -67,7 +70,7 @@ func newCustomerListTableImpl(schemaName, tableName string) customerListTable {
|
|||
)
|
||||
|
||||
return customerListTable{
|
||||
Table: postgres.NewTable(schemaName, tableName, allColumns...),
|
||||
Table: postgres.NewTable(schemaName, tableName, alias, allColumns...),
|
||||
|
||||
//Columns
|
||||
ID: IDColumn,
|
||||
|
|
|
|||
|
|
@ -4,9 +4,10 @@ import (
|
|||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
_ "github.com/lib/pq"
|
||||
"io/ioutil"
|
||||
|
||||
_ "github.com/lib/pq"
|
||||
|
||||
// dot import so that jet go code would resemble as much as native SQL
|
||||
// dot import is not mandatory
|
||||
. "github.com/go-jet/jet/v2/examples/quick-start/.gen/jetdb/dvds/table"
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import (
|
|||
"github.com/go-jet/jet/v2/{{dialect.PackageName}}"
|
||||
)
|
||||
|
||||
var {{ToGoIdentifier .Name}} = new{{.GoStructName}}()
|
||||
var {{ToGoIdentifier .Name}} = new{{.GoStructName}}("{{.SchemaName}}", "{{.Name}}", "")
|
||||
|
||||
type {{.GoStructName}} struct {
|
||||
{{dialect.PackageName}}.Table
|
||||
|
|
@ -38,13 +38,16 @@ type {{.GoStructName}} struct {
|
|||
}
|
||||
|
||||
// AS creates new {{.GoStructName}} with assigned alias
|
||||
func (a *{{.GoStructName}}) AS(alias string) {{.GoStructName}} {
|
||||
aliasTable := new{{.GoStructName}}()
|
||||
aliasTable.Table.AS(alias)
|
||||
return aliasTable
|
||||
func (a {{.GoStructName}}) AS(alias string) {{.GoStructName}} {
|
||||
return new{{.GoStructName}}(a.SchemaName(), a.TableName(), alias)
|
||||
}
|
||||
|
||||
func new{{.GoStructName}}() {{.GoStructName}} {
|
||||
// Schema creates new {{.GoStructName}} with assigned schema name
|
||||
func (a {{.GoStructName}}) FromSchema(schemaName string) {{.GoStructName}} {
|
||||
return new{{.GoStructName}}(schemaName, a.TableName(), a.Alias())
|
||||
}
|
||||
|
||||
func new{{.GoStructName}}(schemaName, tableName, alias string) {{.GoStructName}} {
|
||||
var (
|
||||
{{- range .Columns}}
|
||||
{{ToGoIdentifier .Name}}Column = {{dialect.PackageName}}.{{.SqlBuilderColumnType}}Column("{{.Name}}")
|
||||
|
|
@ -54,7 +57,7 @@ func new{{.GoStructName}}() {{.GoStructName}} {
|
|||
)
|
||||
|
||||
return {{.GoStructName}}{
|
||||
Table: {{dialect.PackageName}}.NewTable("{{.SchemaName}}", "{{.Name}}", allColumns...),
|
||||
Table: {{dialect.PackageName}}.NewTable(schemaName, tableName, alias, allColumns...),
|
||||
|
||||
//Columns
|
||||
{{- range .Columns}}
|
||||
|
|
@ -80,7 +83,7 @@ import (
|
|||
"github.com/go-jet/jet/v2/{{dialect.PackageName}}"
|
||||
)
|
||||
|
||||
var {{ToGoIdentifier .Name}} = new{{.GoStructName}}()
|
||||
var {{ToGoIdentifier .Name}} = new{{.GoStructName}}("{{.SchemaName}}", "{{.Name}}", "")
|
||||
|
||||
type {{.GoStructImplName}} struct {
|
||||
{{dialect.PackageName}}.Table
|
||||
|
|
@ -101,20 +104,23 @@ type {{.GoStructName}} struct {
|
|||
}
|
||||
|
||||
// AS creates new {{.GoStructName}} with assigned alias
|
||||
func (a *{{.GoStructName}}) AS(alias string) *{{.GoStructName}} {
|
||||
aliasTable := new{{.GoStructName}}()
|
||||
aliasTable.Table.AS(alias)
|
||||
return aliasTable
|
||||
func (a {{.GoStructName}}) AS(alias string) *{{.GoStructName}} {
|
||||
return new{{.GoStructName}}(a.SchemaName(), a.TableName(), alias)
|
||||
}
|
||||
|
||||
func new{{.GoStructName}}() *{{.GoStructName}} {
|
||||
// Schema creates new {{.GoStructName}} with assigned schema name
|
||||
func (a {{.GoStructName}}) FromSchema(schemaName string) *{{.GoStructName}} {
|
||||
return new{{.GoStructName}}(schemaName, a.TableName(), a.Alias())
|
||||
}
|
||||
|
||||
func new{{.GoStructName}}(schemaName, tableName, alias string) *{{.GoStructName}} {
|
||||
return &{{.GoStructName}}{
|
||||
{{.GoStructImplName}}: new{{.GoStructName}}Impl("{{.SchemaName}}", "{{.Name}}"),
|
||||
EXCLUDED: new{{.GoStructName}}Impl("", "excluded"),
|
||||
{{.GoStructImplName}}: new{{.GoStructName}}Impl(schemaName, tableName, alias),
|
||||
EXCLUDED: new{{.GoStructName}}Impl("", "excluded", ""),
|
||||
}
|
||||
}
|
||||
|
||||
func new{{.GoStructName}}Impl(schemaName, tableName string) {{.GoStructImplName}} {
|
||||
func new{{.GoStructName}}Impl(schemaName, tableName, alias string) {{.GoStructImplName}} {
|
||||
var (
|
||||
{{- range .Columns}}
|
||||
{{ToGoIdentifier .Name}}Column = {{dialect.PackageName}}.{{.SqlBuilderColumnType}}Column("{{.Name}}")
|
||||
|
|
@ -124,7 +130,7 @@ func new{{.GoStructName}}Impl(schemaName, tableName string) {{.GoStructImplName}
|
|||
)
|
||||
|
||||
return {{.GoStructImplName}}{
|
||||
Table: {{dialect.PackageName}}.NewTable(schemaName, tableName, allColumns...),
|
||||
Table: {{dialect.PackageName}}.NewTable(schemaName, tableName, alias, allColumns...),
|
||||
|
||||
//Columns
|
||||
{{- range .Columns}}
|
||||
|
|
|
|||
8
go.mod
8
go.mod
|
|
@ -4,9 +4,11 @@ go 1.11
|
|||
|
||||
require (
|
||||
github.com/go-sql-driver/mysql v1.5.0
|
||||
github.com/google/go-cmp v0.5.0
|
||||
github.com/google/go-cmp v0.5.0 //tests
|
||||
github.com/google/uuid v1.1.1
|
||||
github.com/jackc/pgx/v4 v4.11.0 //tests
|
||||
github.com/lib/pq v1.7.0
|
||||
github.com/pkg/profile v1.5.0
|
||||
github.com/stretchr/testify v1.6.1
|
||||
github.com/pkg/profile v1.5.0 //tests
|
||||
github.com/shopspring/decimal v1.2.0 // tests
|
||||
github.com/stretchr/testify v1.6.1 // tests
|
||||
)
|
||||
|
|
|
|||
463
go.sum
463
go.sum
|
|
@ -1,23 +1,482 @@
|
|||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
|
||||
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
|
||||
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
|
||||
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
|
||||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-jet/jet v1.0.0 h1:ENxUe/6lH82qLykIGAdZIlskZrpTeNfxjHz4VHtkVmA=
|
||||
github.com/go-jet/jet v2.3.0+incompatible h1:Yg7JSERDC0f9x3dHUBMA2cxe9/qC6qlozDDO/s38USU=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
||||
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE=
|
||||
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
|
||||
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
||||
github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
|
||||
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
|
||||
github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
|
||||
github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
|
||||
github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
|
||||
github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA=
|
||||
github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE=
|
||||
github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s=
|
||||
github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk=
|
||||
github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI=
|
||||
github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI=
|
||||
github.com/jackc/pgconn v1.8.1 h1:ySBX7Q87vOMqKU2bbmKbUvtYhauDFclYbNDYIE1/h6s=
|
||||
github.com/jackc/pgconn v1.8.1/go.mod h1:JV6m6b6jhjdmzchES0drzCcYcAHS1OPD5xu3OZ/lE2g=
|
||||
github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
|
||||
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
|
||||
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2 h1:JVX6jT/XfzNqIjye4717ITLaNwV9mWbJx0dLCpcRzdA=
|
||||
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A=
|
||||
github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
|
||||
github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgproto3/v2 v2.0.6 h1:b1105ZGEMFe7aCvrT1Cca3VoVb4ZFMaFJLJcg/3zD+8=
|
||||
github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
|
||||
github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
|
||||
github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
|
||||
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
|
||||
github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0=
|
||||
github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po=
|
||||
github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ=
|
||||
github.com/jackc/pgtype v1.7.0 h1:6f4kVsW01QftE38ufBYxKciO6gyioXSC0ABIRLcZrGs=
|
||||
github.com/jackc/pgtype v1.7.0/go.mod h1:ZnHF+rMePVqDKaOfJVI4Q8IVvAQMryDlDkZnKOI75BE=
|
||||
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
|
||||
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
|
||||
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
|
||||
github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA=
|
||||
github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o=
|
||||
github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg=
|
||||
github.com/jackc/pgx/v4 v4.11.0 h1:J86tSWd3Y7nKjwT/43xZBvpi04keQWx8gNC2YkdJhZI=
|
||||
github.com/jackc/pgx/v4 v4.11.0/go.mod h1:i62xJgdrtVDsnL3U8ekyrQXEwGNTRoG7/8r+CIdYfcc=
|
||||
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.7.0 h1:h93mCPfUSkaul3Ka/VG8uZdmW1uMHDGxzu0NWHuJmHY=
|
||||
github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
||||
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
|
||||
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
|
||||
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
|
||||
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
|
||||
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
|
||||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
|
||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
|
||||
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||
github.com/pkg/profile v1.5.0 h1:042Buzk+NhDI+DeSAA62RwJL8VAuZUMQZUjCsRz1Mug=
|
||||
github.com/pkg/profile v1.5.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
|
||||
github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
|
||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
||||
|
|
|
|||
|
|
@ -45,19 +45,25 @@ func (s *ClauseSelect) Serialize(statementType StatementType, out *SQLBuilder, o
|
|||
|
||||
// ClauseFrom struct
|
||||
type ClauseFrom struct {
|
||||
Table Serializer
|
||||
Tables []Serializer
|
||||
}
|
||||
|
||||
// Serialize serializes clause into SQLBuilder
|
||||
func (f *ClauseFrom) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
if f.Table == nil {
|
||||
if len(f.Tables) == 0 { // SELECT statement does not have to have FROM clause
|
||||
return
|
||||
}
|
||||
out.NewLine()
|
||||
out.WriteString("FROM")
|
||||
|
||||
out.IncreaseIdent()
|
||||
f.Table.serialize(statementType, out, FallTrough(options)...)
|
||||
for i, table := range f.Tables {
|
||||
if i > 0 {
|
||||
out.WriteString(",")
|
||||
out.NewLine()
|
||||
}
|
||||
table.serialize(statementType, out, FallTrough(options)...)
|
||||
}
|
||||
out.DecreaseIdent()
|
||||
}
|
||||
|
||||
|
|
@ -302,7 +308,7 @@ func (s *SetClause) Serialize(statementType StatementType, out *SQLBuilder, opti
|
|||
panic("jet: nil column in columns list for SET clause")
|
||||
}
|
||||
|
||||
out.WriteString(column.Name())
|
||||
out.WriteIdentifier(column.Name())
|
||||
|
||||
out.WriteString(" = ")
|
||||
|
||||
|
|
|
|||
|
|
@ -801,3 +801,8 @@ func newTimestampzFunc(name string, expressions ...Expression) *timestampzFunc {
|
|||
|
||||
return timestampzFunc
|
||||
}
|
||||
|
||||
// Func can be used to call an custom or as of yet unsupported function in the database.
|
||||
func Func(name string, expressions ...Expression) Expression {
|
||||
return newFunc(name, expressions, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -176,3 +176,7 @@ func TestTO_ASCII(t *testing.T) {
|
|||
assertClauseSerialize(t, TO_ASCII(String("Karel")), `TO_ASCII($1)`, "Karel")
|
||||
assertClauseSerialize(t, TO_ASCII(String("Karel")), `TO_ASCII($1)`, "Karel")
|
||||
}
|
||||
|
||||
func TestFunc(t *testing.T) {
|
||||
assertClauseSerialize(t, Func("FOO", String("test"), NULL, MAX(Int(1))), "FOO($1, NULL, MAX($2))", "test", int64(1))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,8 +67,7 @@ type integerLiteralExpression struct {
|
|||
integerInterfaceImpl
|
||||
}
|
||||
|
||||
// Int creates new integer literal
|
||||
func Int(value int64) IntegerExpression {
|
||||
func intLiteral(value interface{}) IntegerExpression {
|
||||
numLiteral := &integerLiteralExpression{}
|
||||
|
||||
numLiteral.literalExpressionImpl = *literal(value)
|
||||
|
|
@ -79,6 +78,46 @@ func Int(value int64) IntegerExpression {
|
|||
return numLiteral
|
||||
}
|
||||
|
||||
// Int creates a new 64 bit signed integer literal
|
||||
func Int(value int64) IntegerExpression {
|
||||
return intLiteral(value)
|
||||
}
|
||||
|
||||
// Int8 creates a new 8 bit signed integer literal
|
||||
func Int8(value int8) IntegerExpression {
|
||||
return intLiteral(value)
|
||||
}
|
||||
|
||||
// Int16 creates a new 16 bit signed integer literal
|
||||
func Int16(value int16) IntegerExpression {
|
||||
return intLiteral(value)
|
||||
}
|
||||
|
||||
// Int32 creates a new 32 bit signed integer literal
|
||||
func Int32(value int32) IntegerExpression {
|
||||
return intLiteral(value)
|
||||
}
|
||||
|
||||
// Uint8 creates a new 8 bit unsigned integer literal
|
||||
func Uint8(value uint8) IntegerExpression {
|
||||
return intLiteral(value)
|
||||
}
|
||||
|
||||
// Uint16 creates a new 16 bit unsigned integer literal
|
||||
func Uint16(value uint16) IntegerExpression {
|
||||
return intLiteral(value)
|
||||
}
|
||||
|
||||
// Uint32 creates a new 32 bit unsigned integer literal
|
||||
func Uint32(value uint32) IntegerExpression {
|
||||
return intLiteral(value)
|
||||
}
|
||||
|
||||
// Uint64 creates a new 64 bit unsigned integer literal
|
||||
func Uint64(value uint64) IntegerExpression {
|
||||
return intLiteral(value)
|
||||
}
|
||||
|
||||
//---------------------------------------------------//
|
||||
type boolLiteralExpression struct {
|
||||
boolInterfaceImpl
|
||||
|
|
@ -101,7 +140,7 @@ type floatLiteral struct {
|
|||
literalExpressionImpl
|
||||
}
|
||||
|
||||
// Float creates new float literal
|
||||
// Float creates new float literal from float64 value
|
||||
func Float(value float64) FloatExpression {
|
||||
floatLiteral := floatLiteral{}
|
||||
floatLiteral.literalExpressionImpl = *literal(value)
|
||||
|
|
@ -111,6 +150,16 @@ func Float(value float64) FloatExpression {
|
|||
return &floatLiteral
|
||||
}
|
||||
|
||||
// Decimal creates new float literal from string value
|
||||
func Decimal(value string) FloatExpression {
|
||||
floatLiteral := floatLiteral{}
|
||||
floatLiteral.literalExpressionImpl = *literal(value)
|
||||
|
||||
floatLiteral.floatInterfaceImpl.parent = &floatLiteral
|
||||
|
||||
return &floatLiteral
|
||||
}
|
||||
|
||||
//---------------------------------------------------//
|
||||
type stringLiteral struct {
|
||||
stringInterfaceImpl
|
||||
|
|
@ -345,18 +394,94 @@ func WRAP(expression ...Expression) Expression {
|
|||
type rawExpression struct {
|
||||
ExpressionInterfaceImpl
|
||||
|
||||
Raw string
|
||||
Raw string
|
||||
NamedArgument map[string]interface{}
|
||||
noWrap bool
|
||||
}
|
||||
|
||||
func (n *rawExpression) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
out.WriteString(n.Raw)
|
||||
if !n.noWrap && !contains(options, NoWrap) {
|
||||
out.WriteByte('(')
|
||||
}
|
||||
|
||||
out.insertRawQuery(n.Raw, n.NamedArgument)
|
||||
|
||||
if !n.noWrap && !contains(options, NoWrap) {
|
||||
out.WriteByte(')')
|
||||
}
|
||||
}
|
||||
|
||||
// Raw can be used for any unsupported functions, operators or expressions.
|
||||
// For example: Raw("current_database()")
|
||||
func Raw(raw string, parent ...Expression) Expression {
|
||||
rawExp := &rawExpression{Raw: raw}
|
||||
func Raw(raw string, namedArgs ...map[string]interface{}) Expression {
|
||||
var namedArguments map[string]interface{}
|
||||
|
||||
if len(namedArgs) > 0 {
|
||||
namedArguments = namedArgs[0]
|
||||
}
|
||||
|
||||
rawExp := &rawExpression{
|
||||
Raw: raw,
|
||||
NamedArgument: namedArguments,
|
||||
}
|
||||
rawExp.ExpressionInterfaceImpl.Parent = rawExp
|
||||
|
||||
return rawExp
|
||||
}
|
||||
|
||||
// RawWithParent is a Raw constructor used for construction dialect specific expression
|
||||
func RawWithParent(raw string, parent ...Expression) Expression {
|
||||
rawExp := &rawExpression{
|
||||
Raw: raw,
|
||||
noWrap: true,
|
||||
}
|
||||
rawExp.ExpressionInterfaceImpl.Parent = OptionalOrDefaultExpression(rawExp, parent...)
|
||||
|
||||
return rawExp
|
||||
}
|
||||
|
||||
// RawInt helper that for integer expressions
|
||||
func RawInt(raw string, namedArgs ...map[string]interface{}) IntegerExpression {
|
||||
return IntExp(Raw(raw, namedArgs...))
|
||||
}
|
||||
|
||||
// RawFloat helper that for float expressions
|
||||
func RawFloat(raw string, namedArgs ...map[string]interface{}) FloatExpression {
|
||||
return FloatExp(Raw(raw, namedArgs...))
|
||||
}
|
||||
|
||||
// RawString helper that for string expressions
|
||||
func RawString(raw string, namedArgs ...map[string]interface{}) StringExpression {
|
||||
return StringExp(Raw(raw, namedArgs...))
|
||||
}
|
||||
|
||||
// RawTime helper that for time expressions
|
||||
func RawTime(raw string, namedArgs ...map[string]interface{}) TimeExpression {
|
||||
return TimeExp(Raw(raw, namedArgs...))
|
||||
}
|
||||
|
||||
// RawTimez helper that for time with time zone expressions
|
||||
func RawTimez(raw string, namedArgs ...map[string]interface{}) TimezExpression {
|
||||
return TimezExp(Raw(raw, namedArgs...))
|
||||
}
|
||||
|
||||
// RawTimestamp helper that for timestamp expressions
|
||||
func RawTimestamp(raw string, namedArgs ...map[string]interface{}) TimestampExpression {
|
||||
return TimestampExp(Raw(raw, namedArgs...))
|
||||
}
|
||||
|
||||
// RawTimestampz helper that for timestamp with time zone expressions
|
||||
func RawTimestampz(raw string, namedArgs ...map[string]interface{}) TimestampzExpression {
|
||||
return TimestampzExp(Raw(raw, namedArgs...))
|
||||
}
|
||||
|
||||
// RawDate helper that for date expressions
|
||||
func RawDate(raw string, namedArgs ...map[string]interface{}) DateExpression {
|
||||
return DateExp(Raw(raw, namedArgs...))
|
||||
}
|
||||
|
||||
// UUID is a helper function to create string literal expression from uuid object
|
||||
// value can be any uuid type with a String method
|
||||
func UUID(value fmt.Stringer) StringExpression {
|
||||
return String(value.String())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
func TestRawExpression(t *testing.T) {
|
||||
assertClauseSerialize(t, Raw("current_database()"), "current_database()")
|
||||
assertClauseSerialize(t, Raw("current_database()"), "(current_database())")
|
||||
|
||||
var timeT = time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC)
|
||||
|
||||
|
|
|
|||
47
internal/jet/raw_statement.go
Normal file
47
internal/jet/raw_statement.go
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
package jet
|
||||
|
||||
type rawStatementImpl struct {
|
||||
serializerStatementInterfaceImpl
|
||||
|
||||
RawQuery string
|
||||
NamedArguments map[string]interface{}
|
||||
}
|
||||
|
||||
// RawStatement creates new sql statements from raw query and optional map of named arguments
|
||||
func RawStatement(dialect Dialect, rawQuery string, namedArgument ...map[string]interface{}) Statement {
|
||||
newRawStatement := rawStatementImpl{
|
||||
serializerStatementInterfaceImpl: serializerStatementInterfaceImpl{
|
||||
dialect: dialect,
|
||||
statementType: "",
|
||||
parent: nil,
|
||||
},
|
||||
RawQuery: rawQuery,
|
||||
}
|
||||
|
||||
if len(namedArgument) > 0 {
|
||||
newRawStatement.NamedArguments = namedArgument[0]
|
||||
}
|
||||
|
||||
newRawStatement.parent = &newRawStatement
|
||||
|
||||
return &newRawStatement
|
||||
}
|
||||
|
||||
func (s *rawStatementImpl) projections() ProjectionList {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *rawStatementImpl) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
if !contains(options, NoWrap) {
|
||||
out.WriteString("(")
|
||||
out.IncreaseIdent()
|
||||
}
|
||||
|
||||
out.insertRawQuery(s.RawQuery, s.NamedArguments)
|
||||
|
||||
if !contains(options, NoWrap) {
|
||||
out.DecreaseIdent()
|
||||
out.NewLine()
|
||||
out.WriteString(")")
|
||||
}
|
||||
}
|
||||
|
|
@ -13,8 +13,8 @@ type selectTableImpl struct {
|
|||
}
|
||||
|
||||
// NewSelectTable func
|
||||
func NewSelectTable(selectStmt SerializerStatement, alias string) SelectTable {
|
||||
selectTable := &selectTableImpl{selectStmt: selectStmt, alias: alias}
|
||||
func NewSelectTable(selectStmt SerializerStatement, alias string) selectTableImpl {
|
||||
selectTable := selectTableImpl{selectStmt: selectStmt, alias: alias}
|
||||
return selectTable
|
||||
}
|
||||
|
||||
|
|
@ -38,3 +38,22 @@ func (s selectTableImpl) serialize(statement StatementType, out *SQLBuilder, opt
|
|||
out.WriteString("AS")
|
||||
out.WriteIdentifier(s.alias)
|
||||
}
|
||||
|
||||
// --------------------------------------
|
||||
|
||||
type lateralImpl struct {
|
||||
selectTableImpl
|
||||
}
|
||||
|
||||
// NewLateral creates new lateral expression from select statement with alias
|
||||
func NewLateral(selectStmt SerializerStatement, alias string) SelectTable {
|
||||
return lateralImpl{selectTableImpl: NewSelectTable(selectStmt, alias)}
|
||||
}
|
||||
|
||||
func (s lateralImpl) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
out.WriteString("LATERAL")
|
||||
s.selectStmt.serialize(statement, out)
|
||||
|
||||
out.WriteString("AS")
|
||||
out.WriteIdentifier(s.alias)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/go-jet/jet/v2/internal/utils"
|
||||
"github.com/google/uuid"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
|
@ -135,6 +136,73 @@ func (s *SQLBuilder) insertParametrizedArgument(arg interface{}) {
|
|||
s.WriteString(argPlaceholder)
|
||||
}
|
||||
|
||||
func (s *SQLBuilder) insertRawQuery(raw string, namedArg map[string]interface{}) {
|
||||
type namedArgumentPosition struct {
|
||||
Name string
|
||||
Value interface{}
|
||||
Position int
|
||||
}
|
||||
|
||||
var namedArgumentPositions []namedArgumentPosition
|
||||
|
||||
for namedArg, value := range namedArg {
|
||||
rawCopy := raw
|
||||
rawIndex := 0
|
||||
exists := false
|
||||
|
||||
// one named argument can occur multiple times inside raw string
|
||||
for {
|
||||
index := strings.Index(rawCopy, namedArg)
|
||||
if index == -1 {
|
||||
break
|
||||
}
|
||||
|
||||
exists = true
|
||||
namedArgumentPositions = append(namedArgumentPositions, namedArgumentPosition{
|
||||
Name: namedArg,
|
||||
Value: value,
|
||||
Position: rawIndex + index,
|
||||
})
|
||||
|
||||
rawCopy = rawCopy[index+len(namedArg):]
|
||||
rawIndex += index + len(namedArg)
|
||||
}
|
||||
|
||||
if !exists {
|
||||
panic("jet: named argument '" + namedArg + "' does not appear in raw query")
|
||||
}
|
||||
}
|
||||
|
||||
sort.Slice(namedArgumentPositions, func(i, j int) bool {
|
||||
return namedArgumentPositions[i].Position < namedArgumentPositions[j].Position
|
||||
})
|
||||
|
||||
for _, namedArgumentPos := range namedArgumentPositions {
|
||||
// if named argument does not exists in raw string do not add argument to the list of arguments
|
||||
// It can happen if the same argument occurs multiple times in postgres query.
|
||||
if !strings.Contains(raw, namedArgumentPos.Name) {
|
||||
continue
|
||||
}
|
||||
s.Args = append(s.Args, namedArgumentPos.Value)
|
||||
currentArgNum := len(s.Args)
|
||||
|
||||
placeholder := s.Dialect.ArgumentPlaceholder()(currentArgNum)
|
||||
// if placeholder is not unique identifier ($1, $2, etc..), we will replace just one occurrence of the argument
|
||||
toReplace := -1 // all occurrences
|
||||
if placeholder == "?" {
|
||||
toReplace = 1 // just one occurrence
|
||||
}
|
||||
|
||||
if s.Debug {
|
||||
placeholder = argToString(namedArgumentPos.Value)
|
||||
}
|
||||
|
||||
raw = strings.Replace(raw, namedArgumentPos.Name, placeholder, toReplace)
|
||||
}
|
||||
|
||||
s.WriteString(raw)
|
||||
}
|
||||
|
||||
func argToString(value interface{}) string {
|
||||
if utils.IsNil(value) {
|
||||
return "NULL"
|
||||
|
|
|
|||
|
|
@ -13,19 +13,30 @@ type Statement interface {
|
|||
// DebugSql returns debug query where every parametrized placeholder is replaced with its argument.
|
||||
// Do not use it in production. Use it only for debug purposes.
|
||||
DebugSql() (query string)
|
||||
// Query executes statement over database connection db and stores row result in destination.
|
||||
// Query executes statement over database connection/transaction db and stores row result in destination.
|
||||
// Destination can be either pointer to struct or pointer to a slice.
|
||||
// If destination is pointer to struct and query result set is empty, method returns qrm.ErrNoRows.
|
||||
Query(db qrm.DB, destination interface{}) error
|
||||
// QueryContext executes statement with a context over database connection db and stores row result in destination.
|
||||
// QueryContext executes statement with a context over database connection/transaction db and stores row result in destination.
|
||||
// Destination can be either pointer to struct or pointer to a slice.
|
||||
// If destination is pointer to struct and query result set is empty, method returns qrm.ErrNoRows.
|
||||
QueryContext(ctx context.Context, db qrm.DB, destination interface{}) error
|
||||
|
||||
//Exec executes statement over db connection without returning any rows.
|
||||
//Exec executes statement over db connection/transaction without returning any rows.
|
||||
Exec(db qrm.DB) (sql.Result, error)
|
||||
//Exec executes statement with context over db connection without returning any rows.
|
||||
//Exec executes statement with context over db connection/transaction without returning any rows.
|
||||
ExecContext(ctx context.Context, db qrm.DB) (sql.Result, error)
|
||||
// Rows executes statements over db connection/transaction and returns rows
|
||||
Rows(ctx context.Context, db qrm.DB) (*Rows, error)
|
||||
}
|
||||
|
||||
// Rows wraps sql.Rows type to add query result mapping for Scan method
|
||||
type Rows struct {
|
||||
*sql.Rows
|
||||
}
|
||||
|
||||
// Scan will map the Row values into struct destination
|
||||
func (r *Rows) Scan(destination interface{}) error {
|
||||
return qrm.ScanOneRowToDest(r.Rows, destination)
|
||||
}
|
||||
|
||||
// SerializerStatement interface
|
||||
|
|
@ -99,6 +110,20 @@ func (s *serializerStatementInterfaceImpl) ExecContext(ctx context.Context, db q
|
|||
return db.ExecContext(ctx, query, args...)
|
||||
}
|
||||
|
||||
func (s *serializerStatementInterfaceImpl) Rows(ctx context.Context, db qrm.DB) (*Rows, error) {
|
||||
query, args := s.Sql()
|
||||
|
||||
callLogger(ctx, s)
|
||||
|
||||
rows, err := db.QueryContext(ctx, query, args...)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Rows{rows}, nil
|
||||
}
|
||||
|
||||
func callLogger(ctx context.Context, statement Statement) {
|
||||
if logger != nil {
|
||||
logger(ctx, statement)
|
||||
|
|
|
|||
|
|
@ -15,20 +15,27 @@ type Table interface {
|
|||
columns() []Column
|
||||
SchemaName() string
|
||||
TableName() string
|
||||
AS(alias string)
|
||||
Alias() string
|
||||
}
|
||||
|
||||
// NewTable creates new table with schema Name, table Name and list of columns
|
||||
func NewTable(schemaName, name string, columns ...ColumnExpression) SerializerTable {
|
||||
func NewTable(schemaName, name, alias string, columns ...ColumnExpression) SerializerTable {
|
||||
|
||||
t := tableImpl{
|
||||
schemaName: schemaName,
|
||||
name: name,
|
||||
alias: alias,
|
||||
columnList: columns,
|
||||
}
|
||||
|
||||
columnTableName := name
|
||||
|
||||
if alias != "" {
|
||||
columnTableName = alias
|
||||
}
|
||||
|
||||
for _, c := range columns {
|
||||
c.setTableName(name)
|
||||
c.setTableName(columnTableName)
|
||||
}
|
||||
|
||||
return &t
|
||||
|
|
@ -41,14 +48,6 @@ type tableImpl struct {
|
|||
columnList []ColumnExpression
|
||||
}
|
||||
|
||||
func (t *tableImpl) AS(alias string) {
|
||||
t.alias = alias
|
||||
|
||||
for _, c := range t.columnList {
|
||||
c.setTableName(alias)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tableImpl) SchemaName() string {
|
||||
return t.schemaName
|
||||
}
|
||||
|
|
@ -67,13 +66,21 @@ func (t *tableImpl) columns() []Column {
|
|||
return ret
|
||||
}
|
||||
|
||||
func (t *tableImpl) Alias() string {
|
||||
return t.alias
|
||||
}
|
||||
|
||||
func (t *tableImpl) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
if t == nil {
|
||||
panic("jet: tableImpl is nil")
|
||||
}
|
||||
|
||||
out.WriteIdentifier(t.schemaName)
|
||||
out.WriteString(".")
|
||||
// Use default schema if the schema name is not set
|
||||
if len(t.schemaName) > 0 {
|
||||
out.WriteIdentifier(t.schemaName)
|
||||
out.WriteString(".")
|
||||
}
|
||||
|
||||
out.WriteIdentifier(t.name)
|
||||
|
||||
if len(t.alias) > 0 {
|
||||
|
|
@ -129,9 +136,6 @@ func (t *joinTableImpl) TableName() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func (t *joinTableImpl) AS(alias string) {
|
||||
}
|
||||
|
||||
func (t *joinTableImpl) columns() []Column {
|
||||
var ret []Column
|
||||
|
||||
|
|
@ -145,6 +149,10 @@ func (t *joinTableImpl) columns() []Column {
|
|||
return ret
|
||||
}
|
||||
|
||||
func (t *joinTableImpl) Alias() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (t *joinTableImpl) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
if t == nil {
|
||||
panic("jet: Join table is nil. ")
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
func TestNewTable(t *testing.T) {
|
||||
newTable := NewTable("schema", "table", IntegerColumn("intCol"))
|
||||
newTable := NewTable("schema", "table", "", IntegerColumn("intCol"))
|
||||
|
||||
require.Equal(t, newTable.SchemaName(), "schema")
|
||||
require.Equal(t, newTable.TableName(), "table")
|
||||
|
|
@ -16,8 +16,8 @@ func TestNewTable(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestNewJoinTable(t *testing.T) {
|
||||
newTable1 := NewTable("schema", "table", IntegerColumn("intCol1"))
|
||||
newTable2 := NewTable("schema", "table2", IntegerColumn("intCol2"))
|
||||
newTable1 := NewTable("schema", "table", "", IntegerColumn("intCol1"))
|
||||
newTable2 := NewTable("schema", "table2", "", IntegerColumn("intCol2"))
|
||||
|
||||
joinTable := NewJoinTable(newTable1, newTable2, InnerJoin, IntegerColumn("intCol1").EQ(IntegerColumn("intCol2")))
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ var (
|
|||
table1ColBool = BoolColumn("col_bool")
|
||||
table1ColDate = DateColumn("col_date")
|
||||
)
|
||||
var table1 = NewTable("db", "table1", table1Col1, table1ColInt, table1ColFloat, table1Col3, table1ColTime, table1ColTimez, table1ColBool, table1ColDate, table1ColTimestamp, table1ColTimestampz)
|
||||
var table1 = NewTable("db", "table1", "", table1Col1, table1ColInt, table1ColFloat, table1Col3, table1ColTime, table1ColTimez, table1ColBool, table1ColDate, table1ColTimestamp, table1ColTimestampz)
|
||||
|
||||
var (
|
||||
table2Col3 = IntegerColumn("col3")
|
||||
|
|
@ -41,14 +41,14 @@ var (
|
|||
table2ColTimestampz = TimestampzColumn("col_timestampz")
|
||||
table2ColDate = DateColumn("col_date")
|
||||
)
|
||||
var table2 = NewTable("db", "table2", table2Col3, table2Col4, table2ColInt, table2ColFloat, table2ColStr, table2ColBool, table2ColTime, table2ColTimez, table2ColDate, table2ColTimestamp, table2ColTimestampz)
|
||||
var table2 = NewTable("db", "table2", "", table2Col3, table2Col4, table2ColInt, table2ColFloat, table2ColStr, table2ColBool, table2ColTime, table2ColTimez, table2ColDate, table2ColTimestamp, table2ColTimestampz)
|
||||
|
||||
var (
|
||||
table3Col1 = IntegerColumn("col1")
|
||||
table3ColInt = IntegerColumn("col_int")
|
||||
table3StrCol = StringColumn("col2")
|
||||
)
|
||||
var table3 = NewTable("db", "table3", table3Col1, table3ColInt, table3StrCol)
|
||||
var table3 = NewTable("db", "table3", "", table3Col1, table3ColInt, table3StrCol)
|
||||
|
||||
func assertClauseSerialize(t *testing.T, clause Serializer, query string, args ...interface{}) {
|
||||
out := SQLBuilder{Dialect: defaultDialect}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"github.com/go-jet/jet/v2/internal/utils"
|
||||
"github.com/go-jet/jet/v2/qrm"
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
|
@ -89,7 +90,7 @@ func AssertJSONFile(t *testing.T, data interface{}, testRelativePath string) {
|
|||
// AssertStatementSql check if statement Sql() is the same as expectedQuery and expectedArgs
|
||||
func AssertStatementSql(t *testing.T, query jet.Statement, expectedQuery string, expectedArgs ...interface{}) {
|
||||
queryStr, args := query.Sql()
|
||||
require.Equal(t, queryStr, expectedQuery)
|
||||
assertQueryString(t, queryStr, expectedQuery)
|
||||
|
||||
if len(expectedArgs) == 0 {
|
||||
return
|
||||
|
|
@ -115,8 +116,8 @@ func AssertDebugStatementSql(t *testing.T, query jet.Statement, expectedQuery st
|
|||
AssertDeepEqual(t, args, expectedArgs, "arguments are not equal")
|
||||
}
|
||||
|
||||
debuqSql := query.DebugSql()
|
||||
require.Equal(t, debuqSql, expectedQuery)
|
||||
debugSql := query.DebugSql()
|
||||
assertQueryString(t, debugSql, expectedQuery)
|
||||
}
|
||||
|
||||
// AssertSerialize checks if clause serialize produces expected query and args
|
||||
|
|
@ -133,18 +134,6 @@ func AssertSerialize(t *testing.T, dialect jet.Dialect, serializer jet.Serialize
|
|||
}
|
||||
}
|
||||
|
||||
// AssertClauseSerialize checks if clause serialize produces expected query and args
|
||||
func AssertClauseSerialize(t *testing.T, dialect jet.Dialect, clause jet.Clause, query string, args ...interface{}) {
|
||||
out := jet.SQLBuilder{Dialect: dialect}
|
||||
clause.Serialize(jet.SelectStatementType, &out)
|
||||
|
||||
require.Equal(t, out.Buff.String(), query)
|
||||
|
||||
if len(args) > 0 {
|
||||
AssertDeepEqual(t, out.Args, args)
|
||||
}
|
||||
}
|
||||
|
||||
// AssertDebugSerialize checks if clause serialize produces expected debug query and args
|
||||
func AssertDebugSerialize(t *testing.T, dialect jet.Dialect, clause jet.Serializer, query string, args ...interface{}) {
|
||||
out := jet.SQLBuilder{Dialect: dialect, Debug: true}
|
||||
|
|
@ -157,6 +146,18 @@ func AssertDebugSerialize(t *testing.T, dialect jet.Dialect, clause jet.Serializ
|
|||
}
|
||||
}
|
||||
|
||||
// AssertClauseSerialize checks if clause serialize produces expected query and args
|
||||
func AssertClauseSerialize(t *testing.T, dialect jet.Dialect, clause jet.Clause, query string, args ...interface{}) {
|
||||
out := jet.SQLBuilder{Dialect: dialect}
|
||||
clause.Serialize(jet.SelectStatementType, &out)
|
||||
|
||||
require.Equal(t, out.Buff.String(), query)
|
||||
|
||||
if len(args) > 0 {
|
||||
AssertDeepEqual(t, out.Args, args)
|
||||
}
|
||||
}
|
||||
|
||||
// AssertPanicErr checks if running a function fun produces a panic with errorStr string
|
||||
func AssertPanicErr(t *testing.T, fun func(), errorStr string) {
|
||||
defer func() {
|
||||
|
|
@ -194,7 +195,7 @@ func AssertQueryPanicErr(t *testing.T, stmt jet.Statement, db qrm.DB, dest inter
|
|||
require.Equal(t, r, errString)
|
||||
}()
|
||||
|
||||
stmt.Query(db, dest)
|
||||
_ = stmt.Query(db, dest)
|
||||
}
|
||||
|
||||
// AssertFileContent check if file content at filePath contains expectedContent text.
|
||||
|
|
@ -223,7 +224,24 @@ func AssertFileNamesEqual(t *testing.T, fileInfos []os.FileInfo, fileNames ...st
|
|||
|
||||
// AssertDeepEqual checks if actual and expected objects are deeply equal.
|
||||
func AssertDeepEqual(t *testing.T, actual, expected interface{}, msg ...string) {
|
||||
require.True(t, cmp.Equal(actual, expected), msg)
|
||||
if !assert.True(t, cmp.Equal(actual, expected), msg) {
|
||||
printDiff(actual, expected)
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
func assertQueryString(t *testing.T, actual, expected string) {
|
||||
if !assert.Equal(t, actual, expected) {
|
||||
printDiff(actual, expected)
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
func printDiff(actual, expected interface{}) {
|
||||
fmt.Println("Actual: ")
|
||||
fmt.Println(actual)
|
||||
fmt.Println("Expected: ")
|
||||
fmt.Println(expected)
|
||||
}
|
||||
|
||||
// BoolPtr returns address of bool parameter
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ type DeleteStatement interface {
|
|||
Statement
|
||||
|
||||
WHERE(expression BoolExpression) DeleteStatement
|
||||
ORDER_BY(orderByClauses ...jet.OrderByClause) DeleteStatement
|
||||
ORDER_BY(orderByClauses ...OrderByClause) DeleteStatement
|
||||
LIMIT(limit int64) DeleteStatement
|
||||
}
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ func (d *deleteStatementImpl) WHERE(expression BoolExpression) DeleteStatement {
|
|||
return d
|
||||
}
|
||||
|
||||
func (d *deleteStatementImpl) ORDER_BY(orderByClauses ...jet.OrderByClause) DeleteStatement {
|
||||
func (d *deleteStatementImpl) ORDER_BY(orderByClauses ...OrderByClause) DeleteStatement {
|
||||
d.OrderBy.List = orderByClauses
|
||||
return d
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package mysql
|
|||
import "github.com/go-jet/jet/v2/internal/jet"
|
||||
|
||||
// Expression is common interface for all expressions.
|
||||
// Can be Bool, Int, Float, String, Date, Time, Timez, Timestamp or Timestampz expressions.
|
||||
// Can be Bool, Int, Float, String, Date, Time or Timestamp expressions.
|
||||
type Expression = jet.Expression
|
||||
|
||||
// BoolExpression interface
|
||||
|
|
@ -70,9 +70,25 @@ var DateTimeExp = jet.TimestampExp
|
|||
// Does not add sql cast to generated sql builder output.
|
||||
var TimestampExp = jet.TimestampExp
|
||||
|
||||
// RawArgs is type used to pass optional arguments to Raw method
|
||||
type RawArgs = map[string]interface{}
|
||||
|
||||
// Raw can be used for any unsupported functions, operators or expressions.
|
||||
// For example: Raw("current_database()")
|
||||
var Raw = jet.Raw
|
||||
// Raw helper methods for each of the mysql types
|
||||
var (
|
||||
Raw = jet.Raw
|
||||
|
||||
RawInt = jet.RawInt
|
||||
RawFloat = jet.RawFloat
|
||||
RawString = jet.RawString
|
||||
RawTime = jet.RawTime
|
||||
RawTimestamp = jet.RawTimestamp
|
||||
RawDate = jet.RawDate
|
||||
)
|
||||
|
||||
// Func can be used to call an custom or as of yet unsupported function in the database.
|
||||
var Func = jet.Func
|
||||
|
||||
// NewEnumValue creates new named enum value
|
||||
var NewEnumValue = jet.NewEnumValue
|
||||
|
|
|
|||
62
mysql/expressions_test.go
Normal file
62
mysql/expressions_test.go
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
package mysql
|
||||
|
||||
import (
|
||||
"testing"
|
||||
time2 "time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestRaw(t *testing.T) {
|
||||
assertSerialize(t, Raw("current_database()"), "(current_database())")
|
||||
assertDebugSerialize(t, Raw("current_database()"), "(current_database())")
|
||||
|
||||
assertSerialize(t, Raw(":first_arg + table.colInt + :second_arg", RawArgs{":first_arg": 11, ":second_arg": 22}),
|
||||
"(? + table.colInt + ?)", 11, 22)
|
||||
assertDebugSerialize(t, Raw(":first_arg + table.colInt + :second_arg", RawArgs{":first_arg": 11, ":second_arg": 22}),
|
||||
"(11 + table.colInt + 22)")
|
||||
|
||||
assertSerialize(t,
|
||||
Int(700).ADD(RawInt("#1 + table.colInt + #2", RawArgs{"#1": 11, "#2": 22})),
|
||||
"(? + (? + table.colInt + ?))",
|
||||
int64(700), 11, 22)
|
||||
assertDebugSerialize(t,
|
||||
Int(700).ADD(RawInt("#1 + table.colInt + #2", RawArgs{"#1": 11, "#2": 22})),
|
||||
"(700 + (11 + table.colInt + 22))")
|
||||
}
|
||||
|
||||
func TestRawDuplicateArguments(t *testing.T) {
|
||||
assertSerialize(t, Raw(":arg + table.colInt + :arg", RawArgs{":arg": 11}),
|
||||
"(? + table.colInt + ?)", 11, 11)
|
||||
|
||||
assertSerialize(t, Raw("#age + table.colInt + #year + #age + #year + 11", RawArgs{"#age": 11, "#year": 2000}),
|
||||
"(? + table.colInt + ? + ? + ? + 11)", 11, 2000, 11, 2000)
|
||||
|
||||
assertSerialize(t, Raw("#1 + all_types.integer + #2 + #1 + #2 + #3 + #4",
|
||||
RawArgs{"#1": 11, "#2": 22, "#3": 33, "#4": 44}),
|
||||
`(? + all_types.integer + ? + ? + ? + ? + ?)`, 11, 22, 11, 22, 33, 44)
|
||||
}
|
||||
|
||||
func TestRawInvalidArguments(t *testing.T) {
|
||||
defer func() {
|
||||
r := recover()
|
||||
require.Equal(t, "jet: named argument 'first_arg' does not appear in raw query", r)
|
||||
}()
|
||||
|
||||
assertSerialize(t, Raw("table.colInt + :second_arg", RawArgs{"first_arg": 11}), "(table.colInt + ?)", 22)
|
||||
}
|
||||
|
||||
func TestRawType(t *testing.T) {
|
||||
assertSerialize(t, RawFloat("table.colInt + &float", RawArgs{"&float": 11.22}).EQ(Float(3.14)),
|
||||
"((table.colInt + ?) = ?)", 11.22, 3.14)
|
||||
assertSerialize(t, RawString("table.colStr || str", RawArgs{"str": "doe"}).EQ(String("john doe")),
|
||||
"((table.colStr || ?) = ?)", "doe", "john doe")
|
||||
|
||||
time := time2.Now()
|
||||
assertSerialize(t, RawTime("table.colTime").EQ(TimeT(time)),
|
||||
"((table.colTime) = CAST(? AS TIME))", time)
|
||||
assertSerialize(t, RawTimestamp("table.colTimestamp").EQ(TimestampT(time)),
|
||||
"((table.colTimestamp) = TIMESTAMP(?))", time)
|
||||
assertSerialize(t, RawDate("table.colDate").EQ(DateT(time)),
|
||||
"((table.colDate) = CAST(? AS DATE))", time)
|
||||
}
|
||||
|
|
@ -253,8 +253,3 @@ var EXISTS = jet.EXISTS
|
|||
|
||||
// CASE create CASE operator with optional list of expressions
|
||||
var CASE = jet.CASE
|
||||
|
||||
//----------------- Bit operators ---------------//
|
||||
|
||||
// BIT_NOT inverts every bit in integer expression
|
||||
var BIT_NOT = jet.BIT_NOT
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ func INTERVAL(value interface{}, unitType unitType) Interval {
|
|||
// INTERVALe creates new temporal interval from expresion and unit type.
|
||||
func INTERVALe(expr Expression, unitType unitType) Interval {
|
||||
return jet.NewInterval(jet.ListSerializer{
|
||||
Serializers: []jet.Serializer{expr, jet.Raw(string(unitType))},
|
||||
Serializers: []jet.Serializer{expr, jet.RawWithParent(string(unitType))},
|
||||
Separator: " ",
|
||||
})
|
||||
}
|
||||
|
|
|
|||
24
mysql/lateral.go
Normal file
24
mysql/lateral.go
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
package mysql
|
||||
|
||||
import "github.com/go-jet/jet/v2/internal/jet"
|
||||
|
||||
// LATERAL derived tables constructor from select statement
|
||||
func LATERAL(selectStmt SelectStatement) lateralImpl {
|
||||
return lateralImpl{
|
||||
selectStmt: selectStmt,
|
||||
}
|
||||
}
|
||||
|
||||
type lateralImpl struct {
|
||||
selectStmt SelectStatement
|
||||
}
|
||||
|
||||
func (l lateralImpl) AS(alias string) SelectTable {
|
||||
subQuery := &selectTableImpl{
|
||||
SelectTable: jet.NewLateral(l.selectStmt, alias),
|
||||
}
|
||||
|
||||
subQuery.readableTableInterfaceImpl.parent = subQuery
|
||||
|
||||
return subQuery
|
||||
}
|
||||
|
|
@ -15,15 +15,46 @@ var (
|
|||
// Bool creates new bool literal expression
|
||||
var Bool = jet.Bool
|
||||
|
||||
// Int is constructor for integer expressions literals.
|
||||
// Int is constructor for 64 bit signed integer expressions literals.
|
||||
var Int = jet.Int
|
||||
|
||||
// Float creates new float literal expression
|
||||
// Int8 is constructor for 8 bit signed integer expressions literals.
|
||||
var Int8 = jet.Int8
|
||||
|
||||
// Int16 is constructor for 16 bit signed integer expressions literals.
|
||||
var Int16 = jet.Int16
|
||||
|
||||
// Int32 is constructor for 32 bit signed integer expressions literals.
|
||||
var Int32 = jet.Int32
|
||||
|
||||
// Int64 is constructor for 64 bit signed integer expressions literals.
|
||||
var Int64 = jet.Int
|
||||
|
||||
// Uint8 is constructor for 8 bit unsigned integer expressions literals.
|
||||
var Uint8 = jet.Uint8
|
||||
|
||||
// Uint16 is constructor for 16 bit unsigned integer expressions literals.
|
||||
var Uint16 = jet.Uint16
|
||||
|
||||
// Uint32 is constructor for 32 bit unsigned integer expressions literals.
|
||||
var Uint32 = jet.Uint32
|
||||
|
||||
// Uint64 is constructor for 64 bit unsigned integer expressions literals.
|
||||
var Uint64 = jet.Uint64
|
||||
|
||||
// Float creates new float literal expression from float64 value
|
||||
var Float = jet.Float
|
||||
|
||||
// Decimal creates new float literal expression from string value
|
||||
var Decimal = jet.Decimal
|
||||
|
||||
// String creates new string literal expression
|
||||
var String = jet.String
|
||||
|
||||
// UUID is a helper function to create string literal expression from uuid object
|
||||
// value can be any uuid type with a String method
|
||||
var UUID = jet.UUID
|
||||
|
||||
// Date creates new date literal
|
||||
var Date = func(year int, month time.Month, day int) DateExpression {
|
||||
return CAST(jet.Date(year, month, day)).AS_DATE()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package mysql
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
|
@ -13,6 +14,46 @@ func TestInt(t *testing.T) {
|
|||
assertSerialize(t, Int(11), `?`, int64(11))
|
||||
}
|
||||
|
||||
func TestInt8(t *testing.T) {
|
||||
val := int8(math.MinInt8)
|
||||
assertSerialize(t, Int8(val), `?`, val)
|
||||
}
|
||||
|
||||
func TestInt16(t *testing.T) {
|
||||
val := int16(math.MinInt16)
|
||||
assertSerialize(t, Int16(val), `?`, val)
|
||||
}
|
||||
|
||||
func TestInt32(t *testing.T) {
|
||||
val := int32(math.MinInt32)
|
||||
assertSerialize(t, Int32(val), `?`, val)
|
||||
}
|
||||
|
||||
func TestInt64(t *testing.T) {
|
||||
val := int64(math.MinInt64)
|
||||
assertSerialize(t, Int64(val), `?`, val)
|
||||
}
|
||||
|
||||
func TestUint8(t *testing.T) {
|
||||
val := uint8(math.MaxUint8)
|
||||
assertSerialize(t, Uint8(val), `?`, val)
|
||||
}
|
||||
|
||||
func TestUint16(t *testing.T) {
|
||||
val := uint16(math.MaxUint16)
|
||||
assertSerialize(t, Uint16(val), `?`, val)
|
||||
}
|
||||
|
||||
func TestUint32(t *testing.T) {
|
||||
val := uint32(math.MaxUint32)
|
||||
assertSerialize(t, Uint32(val), `?`, val)
|
||||
}
|
||||
|
||||
func TestUint64(t *testing.T) {
|
||||
val := uint64(math.MaxUint64)
|
||||
assertSerialize(t, Uint64(val), `?`, val)
|
||||
}
|
||||
|
||||
func TestFloat(t *testing.T) {
|
||||
assertSerialize(t, Float(12.34), `?`, float64(12.34))
|
||||
}
|
||||
|
|
|
|||
9
mysql/operators.go
Normal file
9
mysql/operators.go
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
package mysql
|
||||
|
||||
import "github.com/go-jet/jet/v2/internal/jet"
|
||||
|
||||
// NOT returns negation of bool expression result
|
||||
var NOT = jet.NOT
|
||||
|
||||
// BIT_NOT inverts every bit in integer expression result
|
||||
var BIT_NOT = jet.BIT_NOT
|
||||
|
|
@ -41,12 +41,12 @@ type SelectStatement interface {
|
|||
Expression
|
||||
|
||||
DISTINCT() SelectStatement
|
||||
FROM(table ReadableTable) SelectStatement
|
||||
FROM(tables ...ReadableTable) SelectStatement
|
||||
WHERE(expression BoolExpression) SelectStatement
|
||||
GROUP_BY(groupByClauses ...jet.GroupByClause) SelectStatement
|
||||
HAVING(boolExpression BoolExpression) SelectStatement
|
||||
WINDOW(name string) windowExpand
|
||||
ORDER_BY(orderByClauses ...jet.OrderByClause) SelectStatement
|
||||
ORDER_BY(orderByClauses ...OrderByClause) SelectStatement
|
||||
LIMIT(limit int64) SelectStatement
|
||||
OFFSET(offset int64) SelectStatement
|
||||
FOR(lock RowLock) SelectStatement
|
||||
|
|
@ -70,7 +70,9 @@ func newSelectStatement(table ReadableTable, projections []Projection) SelectSta
|
|||
&newSelect.Limit, &newSelect.Offset, &newSelect.For, &newSelect.ShareLock)
|
||||
|
||||
newSelect.Select.ProjectionList = projections
|
||||
newSelect.From.Table = table
|
||||
if table != nil {
|
||||
newSelect.From.Tables = []jet.Serializer{table}
|
||||
}
|
||||
newSelect.Limit.Count = -1
|
||||
newSelect.Offset.Count = -1
|
||||
newSelect.ShareLock.Name = "LOCK IN SHARE MODE"
|
||||
|
|
@ -103,8 +105,11 @@ func (s *selectStatementImpl) DISTINCT() SelectStatement {
|
|||
return s
|
||||
}
|
||||
|
||||
func (s *selectStatementImpl) FROM(table ReadableTable) SelectStatement {
|
||||
s.From.Table = table
|
||||
func (s *selectStatementImpl) FROM(tables ...ReadableTable) SelectStatement {
|
||||
s.From.Tables = nil
|
||||
for _, table := range tables {
|
||||
s.From.Tables = append(s.From.Tables, table)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
|
|
@ -128,7 +133,7 @@ func (s *selectStatementImpl) WINDOW(name string) windowExpand {
|
|||
return windowExpand{selectStatement: s}
|
||||
}
|
||||
|
||||
func (s *selectStatementImpl) ORDER_BY(orderByClauses ...jet.OrderByClause) SelectStatement {
|
||||
func (s *selectStatementImpl) ORDER_BY(orderByClauses ...OrderByClause) SelectStatement {
|
||||
s.OrderBy.List = orderByClauses
|
||||
return s
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,3 +132,25 @@ FROM db.table1
|
|||
LOCK IN SHARE MODE;
|
||||
`)
|
||||
}
|
||||
|
||||
func TestSelect_NOT_EXISTS(t *testing.T) {
|
||||
testutils.AssertStatementSql(t,
|
||||
SELECT(table1ColInt).
|
||||
FROM(table1).
|
||||
WHERE(
|
||||
NOT(EXISTS(
|
||||
SELECT(table2ColInt).
|
||||
FROM(table2).
|
||||
WHERE(
|
||||
table1ColInt.EQ(table2ColInt),
|
||||
),
|
||||
))), `
|
||||
SELECT table1.col_int AS "table1.col_int"
|
||||
FROM db.table1
|
||||
WHERE (NOT (EXISTS (
|
||||
SELECT table2.col_int AS "table2.col_int"
|
||||
FROM db.table2
|
||||
WHERE table1.col_int = table2.col_int
|
||||
)));
|
||||
`)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ func UNION_ALL(lhs, rhs jet.SerializerStatement, selects ...jet.SerializerStatem
|
|||
type setStatement interface {
|
||||
setOperators
|
||||
|
||||
ORDER_BY(orderByClauses ...jet.OrderByClause) setStatement
|
||||
ORDER_BY(orderByClauses ...OrderByClause) setStatement
|
||||
|
||||
LIMIT(limit int64) setStatement
|
||||
OFFSET(offset int64) setStatement
|
||||
|
|
@ -70,7 +70,7 @@ func newSetStatementImpl(operator string, all bool, selects []jet.SerializerStat
|
|||
return newSetStatement
|
||||
}
|
||||
|
||||
func (s *setStatementImpl) ORDER_BY(orderByClauses ...jet.OrderByClause) setStatement {
|
||||
func (s *setStatementImpl) ORDER_BY(orderByClauses ...OrderByClause) setStatement {
|
||||
s.setOperator.OrderBy.List = orderByClauses
|
||||
return s
|
||||
}
|
||||
|
|
|
|||
8
mysql/statement.go
Normal file
8
mysql/statement.go
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
package mysql
|
||||
|
||||
import "github.com/go-jet/jet/v2/internal/jet"
|
||||
|
||||
// RawStatement creates new sql statements from raw query and optional map of named arguments
|
||||
func RawStatement(rawQuery string, namedArguments ...RawArgs) Statement {
|
||||
return jet.RawStatement(Dialect, rawQuery, namedArguments...)
|
||||
}
|
||||
|
|
@ -77,9 +77,9 @@ func (r readableTableInterfaceImpl) CROSS_JOIN(table ReadableTable) joinSelectUp
|
|||
}
|
||||
|
||||
// NewTable creates new table with schema Name, table Name and list of columns
|
||||
func NewTable(schemaName, name string, columns ...jet.ColumnExpression) Table {
|
||||
func NewTable(schemaName, name, alias string, columns ...jet.ColumnExpression) Table {
|
||||
t := &tableImpl{
|
||||
SerializerTable: jet.NewTable(schemaName, name, columns...),
|
||||
SerializerTable: jet.NewTable(schemaName, name, alias, columns...),
|
||||
}
|
||||
|
||||
t.readableTableInterfaceImpl.parent = t
|
||||
|
|
|
|||
|
|
@ -17,5 +17,8 @@ type ColumnAssigment = jet.ColumnAssigment
|
|||
// PrintableStatement is a statement which sql query can be logged
|
||||
type PrintableStatement = jet.PrintableStatement
|
||||
|
||||
// OrderByClause is the combination of an expression and the wanted ordering to use as input for ORDER BY.
|
||||
type OrderByClause = jet.OrderByClause
|
||||
|
||||
// SetLogger sets automatic statement logging
|
||||
var SetLogger = jet.SetLoggerFunc
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package mysql
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
|
@ -52,11 +53,29 @@ WHERE table1.col1 = ?;
|
|||
).
|
||||
WHERE(table1Col1.EQ(Int(2)))
|
||||
|
||||
//fmt.Println(stmt.Sql())
|
||||
|
||||
assertStatementSql(t, stmt, expectedSQL, int64(2))
|
||||
}
|
||||
|
||||
func TestUpdateReservedWorldColumn(t *testing.T) {
|
||||
type table struct {
|
||||
Load string
|
||||
}
|
||||
|
||||
loadColumn := StringColumn("Load")
|
||||
assertStatementSql(t,
|
||||
table1.UPDATE(loadColumn).
|
||||
MODEL(
|
||||
table{
|
||||
Load: "foo",
|
||||
},
|
||||
).
|
||||
WHERE(loadColumn.EQ(String("bar"))), strings.Replace(`
|
||||
UPDATE db.table1
|
||||
SET ''Load'' = ?
|
||||
WHERE ''Load'' = ?;
|
||||
`, "''", "`", -1), "foo", "bar")
|
||||
}
|
||||
|
||||
func TestInvalidInputs(t *testing.T) {
|
||||
assertStatementSqlErr(t, table1.UPDATE(table1ColInt).SET(1), "jet: WHERE clause not set")
|
||||
assertStatementSqlErr(t, table1.UPDATE(nil).SET(1), "jet: nil column in columns list for SET clause")
|
||||
|
|
|
|||
|
|
@ -16,19 +16,7 @@ var table1ColTimestamp = TimestampColumn("col_timestamp")
|
|||
var table1ColDate = DateColumn("col_date")
|
||||
var table1ColTime = TimeColumn("col_time")
|
||||
|
||||
var table1 = NewTable(
|
||||
"db",
|
||||
"table1",
|
||||
table1Col1,
|
||||
table1ColInt,
|
||||
table1ColFloat,
|
||||
table1ColString,
|
||||
table1Col3,
|
||||
table1ColBool,
|
||||
table1ColDate,
|
||||
table1ColTimestamp,
|
||||
table1ColTime,
|
||||
)
|
||||
var table1 = NewTable("db", "table1", "", table1Col1, table1ColInt, table1ColFloat, table1ColString, table1Col3, table1ColBool, table1ColDate, table1ColTimestamp, table1ColTime)
|
||||
|
||||
var table2Col3 = IntegerColumn("col3")
|
||||
var table2Col4 = IntegerColumn("col4")
|
||||
|
|
@ -39,28 +27,12 @@ var table2ColBool = BoolColumn("col_bool")
|
|||
var table2ColTimestamp = TimestampColumn("col_timestamp")
|
||||
var table2ColDate = DateColumn("col_date")
|
||||
|
||||
var table2 = NewTable(
|
||||
"db",
|
||||
"table2",
|
||||
table2Col3,
|
||||
table2Col4,
|
||||
table2ColInt,
|
||||
table2ColFloat,
|
||||
table2ColStr,
|
||||
table2ColBool,
|
||||
table2ColDate,
|
||||
table2ColTimestamp,
|
||||
)
|
||||
var table2 = NewTable("db", "table2", "", table2Col3, table2Col4, table2ColInt, table2ColFloat, table2ColStr, table2ColBool, table2ColDate, table2ColTimestamp)
|
||||
|
||||
var table3Col1 = IntegerColumn("col1")
|
||||
var table3ColInt = IntegerColumn("col_int")
|
||||
var table3StrCol = StringColumn("col2")
|
||||
var table3 = NewTable(
|
||||
"db",
|
||||
"table3",
|
||||
table3Col1,
|
||||
table3ColInt,
|
||||
table3StrCol)
|
||||
var table3 = NewTable("db", "table3", "", table3Col1, table3ColInt, table3StrCol)
|
||||
|
||||
func assertSerialize(t *testing.T, clause jet.Serializer, query string, args ...interface{}) {
|
||||
testutils.AssertSerialize(t, Dialect, clause, query, args...)
|
||||
|
|
|
|||
|
|
@ -80,13 +80,7 @@ func TestReservedWordEscaped(t *testing.T) {
|
|||
var table1ColVariadic = IntervalColumn("VARIADIC")
|
||||
var table1ColProcedure = IntervalColumn("procedure")
|
||||
|
||||
_ = NewTable(
|
||||
"db",
|
||||
"table1",
|
||||
table1ColUser,
|
||||
table1ColVariadic,
|
||||
table1ColProcedure,
|
||||
)
|
||||
_ = NewTable("db", "table1", "", table1ColUser, table1ColVariadic, table1ColProcedure)
|
||||
|
||||
assertSerialize(t, table1ColUser, `table1."user"`)
|
||||
assertSerialize(t, table1ColVariadic, `table1."VARIADIC"`)
|
||||
|
|
|
|||
|
|
@ -81,9 +81,27 @@ var TimestampExp = jet.TimestampExp
|
|||
// Does not add sql cast to generated sql builder output.
|
||||
var TimestampzExp = jet.TimestampzExp
|
||||
|
||||
// RawArgs is type used to pass optional arguments to Raw method
|
||||
type RawArgs = map[string]interface{}
|
||||
|
||||
// Raw can be used for any unsupported functions, operators or expressions.
|
||||
// For example: Raw("current_database()")
|
||||
var Raw = jet.Raw
|
||||
// Raw helper methods for each of the postgres types
|
||||
var (
|
||||
Raw = jet.Raw
|
||||
|
||||
RawInt = jet.RawInt
|
||||
RawFloat = jet.RawFloat
|
||||
RawString = jet.RawString
|
||||
RawTime = jet.RawTime
|
||||
RawTimez = jet.RawTimez
|
||||
RawTimestamp = jet.RawTimestamp
|
||||
RawTimestampz = jet.RawTimestampz
|
||||
RawDate = jet.RawDate
|
||||
)
|
||||
|
||||
// Func can be used to call an custom or as of yet unsupported function in the database.
|
||||
var Func = jet.Func
|
||||
|
||||
// NewEnumValue creates new named enum value
|
||||
var NewEnumValue = jet.NewEnumValue
|
||||
|
|
|
|||
76
postgres/expressions_test.go
Normal file
76
postgres/expressions_test.go
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
package postgres
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestRaw(t *testing.T) {
|
||||
assertSerialize(t, Raw("current_database()"), "(current_database())")
|
||||
assertDebugSerialize(t, Raw("current_database()"), "(current_database())")
|
||||
|
||||
assertSerialize(t, Raw(":first_arg + table.colInt + :second_arg", RawArgs{":first_arg": 11, ":second_arg": 22}),
|
||||
"($1 + table.colInt + $2)", 11, 22)
|
||||
assertDebugSerialize(t, Raw(":first_arg + table.colInt + :second_arg", RawArgs{":first_arg": 11, ":second_arg": 22}),
|
||||
"(11 + table.colInt + 22)")
|
||||
|
||||
assertSerialize(t,
|
||||
Int(700).ADD(RawInt(":first_arg + table.colInt + :second_arg", RawArgs{":first_arg": 11, ":second_arg": 22})),
|
||||
"($1 + ($2 + table.colInt + $3))",
|
||||
int64(700), 11, 22)
|
||||
assertDebugSerialize(t,
|
||||
Int(700).ADD(RawInt(":first_arg + table.colInt + :second_arg", RawArgs{":first_arg": 11, ":second_arg": 22})),
|
||||
"(700 + (11 + table.colInt + 22))")
|
||||
}
|
||||
|
||||
func TestDuplicateArguments(t *testing.T) {
|
||||
assertSerialize(t, Raw(":arg + table.colInt + :arg", RawArgs{":arg": 11}),
|
||||
"($1 + table.colInt + $1)", 11)
|
||||
assertDebugSerialize(t, Raw(":arg + table.colInt + :arg", RawArgs{":arg": 11}),
|
||||
"(11 + table.colInt + 11)")
|
||||
|
||||
assertSerialize(t, Raw("#age + table.colInt + #year + #age + #year + 11", RawArgs{"#age": 11, "#year": 2000}),
|
||||
"($1 + table.colInt + $2 + $1 + $2 + 11)", 11, 2000)
|
||||
assertDebugSerialize(t, Raw("#age + table.colInt + #year + #age + #year + 11", RawArgs{"#age": 11, "#year": 2000}),
|
||||
"(11 + table.colInt + 2000 + 11 + 2000 + 11)")
|
||||
|
||||
assertSerialize(t, Raw("#1 + all_types.integer + #2 + #1 + #2 + #3 + #4",
|
||||
RawArgs{"#1": 11, "#2": 22, "#3": 33, "#4": 44}),
|
||||
`($1 + all_types.integer + $2 + $1 + $2 + $3 + $4)`, 11, 22, 33, 44)
|
||||
assertDebugSerialize(t, Raw("#1 + all_types.integer + #2 + #1 + #2 + #3 + #4",
|
||||
RawArgs{"#1": 11, "#2": 22, "#3": 33, "#4": 44}),
|
||||
`(11 + all_types.integer + 22 + 11 + 22 + 33 + 44)`)
|
||||
}
|
||||
|
||||
func TestRawInvalidArguments(t *testing.T) {
|
||||
defer func() {
|
||||
r := recover()
|
||||
require.Equal(t, "jet: named argument 'first_arg' does not appear in raw query", r)
|
||||
}()
|
||||
|
||||
assertSerialize(t, Raw("table.colInt + :second_arg", RawArgs{
|
||||
"first_arg": 11,
|
||||
"second_arg": 22,
|
||||
}), "(table.colInt + $1)", 22)
|
||||
}
|
||||
|
||||
func TestRawHelperMethods(t *testing.T) {
|
||||
assertSerialize(t, RawFloat("table.colInt + :float", RawArgs{":float": 11.22}).EQ(Float(3.14)),
|
||||
"((table.colInt + $1) = $2)", 11.22, 3.14)
|
||||
assertSerialize(t, RawString("table.colStr || str", RawArgs{"str": "doe"}).EQ(String("john doe")),
|
||||
"((table.colStr || $1) = $2)", "doe", "john doe")
|
||||
|
||||
now := time.Now()
|
||||
assertSerialize(t, RawTime("table.colTime").EQ(TimeT(now)),
|
||||
"((table.colTime) = $1::time without time zone)", now)
|
||||
assertSerialize(t, RawTimez("table.colTime").EQ(TimezT(now)),
|
||||
"((table.colTime) = $1::time with time zone)", now)
|
||||
assertSerialize(t, RawTimestamp("table.colTimestamp").EQ(TimestampT(now)),
|
||||
"((table.colTimestamp) = $1::timestamp without time zone)", now)
|
||||
assertSerialize(t, RawTimestampz("table.colTimestampz").EQ(TimestampzT(now)),
|
||||
"((table.colTimestampz) = $1::timestamp with time zone)", now)
|
||||
assertSerialize(t, RawDate("table.colDate").EQ(DateT(now)),
|
||||
"((table.colDate) = $1::date)", now)
|
||||
}
|
||||
|
|
@ -128,7 +128,7 @@ func INTERVAL(quantityAndUnit ...quantityAndUnit) IntervalExpression {
|
|||
|
||||
newInterval := &intervalExpression{}
|
||||
|
||||
newInterval.Expression = jet.Raw(intervalStr, newInterval)
|
||||
newInterval.Expression = jet.RawWithParent(intervalStr, newInterval)
|
||||
newInterval.intervalInterfaceImpl.parent = newInterval
|
||||
|
||||
return newInterval
|
||||
|
|
|
|||
24
postgres/lateral.go
Normal file
24
postgres/lateral.go
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
package postgres
|
||||
|
||||
import "github.com/go-jet/jet/v2/internal/jet"
|
||||
|
||||
// LATERAL derived tables constructor from select statement
|
||||
func LATERAL(selectStmt SelectStatement) lateralImpl {
|
||||
return lateralImpl{
|
||||
selectStmt: selectStmt,
|
||||
}
|
||||
}
|
||||
|
||||
type lateralImpl struct {
|
||||
selectStmt SelectStatement
|
||||
}
|
||||
|
||||
func (l lateralImpl) AS(alias string) SelectTable {
|
||||
subQuery := &selectTableImpl{
|
||||
SelectTable: jet.NewLateral(l.selectStmt, alias),
|
||||
}
|
||||
|
||||
subQuery.readableTableInterfaceImpl.parent = subQuery
|
||||
|
||||
return subQuery
|
||||
}
|
||||
14
postgres/lateral_test.go
Normal file
14
postgres/lateral_test.go
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
package postgres
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestLATERAL(t *testing.T) {
|
||||
assertSerialize(t,
|
||||
LATERAL(
|
||||
SELECT(Int(1)),
|
||||
).AS("lat1"),
|
||||
|
||||
`LATERAL (
|
||||
SELECT $1
|
||||
) AS lat1`)
|
||||
}
|
||||
|
|
@ -1,25 +1,62 @@
|
|||
package postgres
|
||||
|
||||
import (
|
||||
"github.com/go-jet/jet/v2/internal/jet"
|
||||
"time"
|
||||
|
||||
"github.com/go-jet/jet/v2/internal/jet"
|
||||
)
|
||||
|
||||
// Bool creates new bool literal expression
|
||||
var Bool = jet.Bool
|
||||
|
||||
// Int creates new integer literal expression
|
||||
// Int is constructor for 64 bit signed integer expressions literals.
|
||||
var Int = jet.Int
|
||||
|
||||
// Int8 is constructor for 8 bit signed integer expressions literals.
|
||||
var Int8 = jet.Int8
|
||||
|
||||
// Int16 is constructor for 16 bit signed integer expressions literals.
|
||||
var Int16 = jet.Int16
|
||||
|
||||
// Int32 is constructor for 32 bit signed integer expressions literals.
|
||||
var Int32 = jet.Int32
|
||||
|
||||
// Int64 is constructor for 64 bit signed integer expressions literals.
|
||||
var Int64 = jet.Int
|
||||
|
||||
// Uint8 is constructor for 8 bit unsigned integer expressions literals.
|
||||
var Uint8 = jet.Uint8
|
||||
|
||||
// Uint16 is constructor for 16 bit unsigned integer expressions literals.
|
||||
var Uint16 = jet.Uint16
|
||||
|
||||
// Uint32 is constructor for 32 bit unsigned integer expressions literals.
|
||||
var Uint32 = jet.Uint32
|
||||
|
||||
// Uint64 is constructor for 64 bit unsigned integer expressions literals.
|
||||
var Uint64 = jet.Uint64
|
||||
|
||||
// Float creates new float literal expression
|
||||
var Float = jet.Float
|
||||
|
||||
// Decimal creates new float literal expression
|
||||
var Decimal = jet.Decimal
|
||||
|
||||
// String creates new string literal expression
|
||||
var String = jet.String
|
||||
|
||||
// Bytea craates new bytea literal expression
|
||||
var Bytea = func(value string) StringExpression {
|
||||
return CAST(jet.String(value)).AS_BYTEA()
|
||||
// UUID is a helper function to create string literal expression from uuid object
|
||||
// value can be any uuid type with a String method
|
||||
var UUID = jet.UUID
|
||||
|
||||
// Bytea creates new bytea literal expression
|
||||
var Bytea = func(value interface{}) StringExpression {
|
||||
switch value.(type) {
|
||||
case string, []byte:
|
||||
default:
|
||||
panic("Bytea parameter value has to be of the type string or []byte")
|
||||
}
|
||||
return CAST(jet.Literal(value)).AS_BYTEA()
|
||||
}
|
||||
|
||||
// Date creates new date literal expression
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package postgres
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
|
@ -13,6 +14,46 @@ func TestInt(t *testing.T) {
|
|||
assertSerialize(t, Int(11), `$1`, int64(11))
|
||||
}
|
||||
|
||||
func TestInt8(t *testing.T) {
|
||||
val := int8(math.MinInt8)
|
||||
assertSerialize(t, Int8(val), `$1`, val)
|
||||
}
|
||||
|
||||
func TestInt16(t *testing.T) {
|
||||
val := int16(math.MinInt16)
|
||||
assertSerialize(t, Int16(val), `$1`, val)
|
||||
}
|
||||
|
||||
func TestInt32(t *testing.T) {
|
||||
val := int32(math.MinInt32)
|
||||
assertSerialize(t, Int32(val), `$1`, val)
|
||||
}
|
||||
|
||||
func TestInt64(t *testing.T) {
|
||||
val := int64(math.MinInt64)
|
||||
assertSerialize(t, Int64(val), `$1`, val)
|
||||
}
|
||||
|
||||
func TestUint8(t *testing.T) {
|
||||
val := uint8(math.MaxUint8)
|
||||
assertSerialize(t, Uint8(val), `$1`, val)
|
||||
}
|
||||
|
||||
func TestUint16(t *testing.T) {
|
||||
val := uint16(math.MaxUint16)
|
||||
assertSerialize(t, Uint16(val), `$1`, val)
|
||||
}
|
||||
|
||||
func TestUint32(t *testing.T) {
|
||||
val := uint32(math.MaxUint32)
|
||||
assertSerialize(t, Uint32(val), `$1`, val)
|
||||
}
|
||||
|
||||
func TestUint64(t *testing.T) {
|
||||
val := uint64(math.MaxUint64)
|
||||
assertSerialize(t, Uint64(val), `$1`, val)
|
||||
}
|
||||
|
||||
func TestFloat(t *testing.T) {
|
||||
assertSerialize(t, Float(12.34), `$1`, float64(12.34))
|
||||
}
|
||||
|
|
@ -21,6 +62,11 @@ func TestString(t *testing.T) {
|
|||
assertSerialize(t, String("Some text"), `$1`, "Some text")
|
||||
}
|
||||
|
||||
func TestBytea(t *testing.T) {
|
||||
assertSerialize(t, Bytea("Some text"), `$1::bytea`, "Some text")
|
||||
assertSerialize(t, Bytea([]byte("Some byte array")), `$1::bytea`, []byte("Some byte array"))
|
||||
}
|
||||
|
||||
func TestDate(t *testing.T) {
|
||||
assertSerialize(t, Date(2014, time.January, 2), `$1::date`, "2014-01-02")
|
||||
assertSerialize(t, DateT(time.Now()), `$1::date`)
|
||||
|
|
|
|||
|
|
@ -44,12 +44,12 @@ type SelectStatement interface {
|
|||
Expression
|
||||
|
||||
DISTINCT() SelectStatement
|
||||
FROM(table ReadableTable) SelectStatement
|
||||
FROM(tables ...ReadableTable) SelectStatement
|
||||
WHERE(expression BoolExpression) SelectStatement
|
||||
GROUP_BY(groupByClauses ...jet.GroupByClause) SelectStatement
|
||||
HAVING(boolExpression BoolExpression) SelectStatement
|
||||
WINDOW(name string) windowExpand
|
||||
ORDER_BY(orderByClauses ...jet.OrderByClause) SelectStatement
|
||||
ORDER_BY(orderByClauses ...OrderByClause) SelectStatement
|
||||
LIMIT(limit int64) SelectStatement
|
||||
OFFSET(offset int64) SelectStatement
|
||||
FOR(lock RowLock) SelectStatement
|
||||
|
|
@ -76,7 +76,9 @@ func newSelectStatement(table ReadableTable, projections []Projection) SelectSta
|
|||
&newSelect.Limit, &newSelect.Offset, &newSelect.For)
|
||||
|
||||
newSelect.Select.ProjectionList = projections
|
||||
newSelect.From.Table = table
|
||||
if table != nil {
|
||||
newSelect.From.Tables = []jet.Serializer{table}
|
||||
}
|
||||
newSelect.Limit.Count = -1
|
||||
newSelect.Offset.Count = -1
|
||||
|
||||
|
|
@ -106,8 +108,11 @@ func (s *selectStatementImpl) DISTINCT() SelectStatement {
|
|||
return s
|
||||
}
|
||||
|
||||
func (s *selectStatementImpl) FROM(table ReadableTable) SelectStatement {
|
||||
s.From.Table = table
|
||||
func (s *selectStatementImpl) FROM(tables ...ReadableTable) SelectStatement {
|
||||
s.From.Tables = nil
|
||||
for _, table := range tables {
|
||||
s.From.Tables = append(s.From.Tables, table)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
|
|
@ -131,7 +136,7 @@ func (s *selectStatementImpl) WINDOW(name string) windowExpand {
|
|||
return windowExpand{selectStatement: s}
|
||||
}
|
||||
|
||||
func (s *selectStatementImpl) ORDER_BY(orderByClauses ...jet.OrderByClause) SelectStatement {
|
||||
func (s *selectStatementImpl) ORDER_BY(orderByClauses ...OrderByClause) SelectStatement {
|
||||
s.OrderBy.List = orderByClauses
|
||||
return s
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ func EXCEPT_ALL(lhs, rhs jet.SerializerStatement) setStatement {
|
|||
type setStatement interface {
|
||||
setOperators
|
||||
|
||||
ORDER_BY(orderByClauses ...jet.OrderByClause) setStatement
|
||||
ORDER_BY(orderByClauses ...OrderByClause) setStatement
|
||||
|
||||
LIMIT(limit int64) setStatement
|
||||
OFFSET(offset int64) setStatement
|
||||
|
|
@ -114,7 +114,7 @@ func newSetStatementImpl(operator string, all bool, selects []jet.SerializerStat
|
|||
return newSetStatement
|
||||
}
|
||||
|
||||
func (s *setStatementImpl) ORDER_BY(orderByClauses ...jet.OrderByClause) setStatement {
|
||||
func (s *setStatementImpl) ORDER_BY(orderByClauses ...OrderByClause) setStatement {
|
||||
s.setOperator.OrderBy.List = orderByClauses
|
||||
return s
|
||||
}
|
||||
|
|
|
|||
8
postgres/statement.go
Normal file
8
postgres/statement.go
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
package postgres
|
||||
|
||||
import "github.com/go-jet/jet/v2/internal/jet"
|
||||
|
||||
// RawStatement creates new sql statements from raw query and optional map of named arguments
|
||||
func RawStatement(rawQuery string, namedArguments ...RawArgs) Statement {
|
||||
return jet.RawStatement(Dialect, rawQuery, namedArguments...)
|
||||
}
|
||||
|
|
@ -109,10 +109,10 @@ type tableImpl struct {
|
|||
}
|
||||
|
||||
// NewTable creates new table with schema Name, table Name and list of columns
|
||||
func NewTable(schemaName, name string, columns ...jet.ColumnExpression) Table {
|
||||
func NewTable(schemaName, name, alias string, columns ...jet.ColumnExpression) Table {
|
||||
|
||||
t := &tableImpl{
|
||||
SerializerTable: jet.NewTable(schemaName, name, columns...),
|
||||
SerializerTable: jet.NewTable(schemaName, name, alias, columns...),
|
||||
}
|
||||
|
||||
t.readableTableInterfaceImpl.parent = t
|
||||
|
|
|
|||
|
|
@ -99,3 +99,26 @@ CROSS JOIN db.table2`)
|
|||
CROSS JOIN db.table2
|
||||
CROSS JOIN db.table3`)
|
||||
}
|
||||
|
||||
func TestImplicitCROSS_JOIN(t *testing.T) {
|
||||
assertDebugStatementSql(t,
|
||||
SELECT(table1Col1, table2Col3).
|
||||
FROM(table1, table2),
|
||||
`
|
||||
SELECT table1.col1 AS "table1.col1",
|
||||
table2.col3 AS "table2.col3"
|
||||
FROM db.table1,
|
||||
db.table2;
|
||||
`)
|
||||
assertDebugStatementSql(t,
|
||||
SELECT(
|
||||
table1Col1, table2Col3,
|
||||
).FROM(table1, table2, table3),
|
||||
`
|
||||
SELECT table1.col1 AS "table1.col1",
|
||||
table2.col3 AS "table2.col3"
|
||||
FROM db.table1,
|
||||
db.table2,
|
||||
db.table3;
|
||||
`)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,5 +17,8 @@ type ColumnAssigment = jet.ColumnAssigment
|
|||
// PrintableStatement is a statement which sql query can be logged
|
||||
type PrintableStatement = jet.PrintableStatement
|
||||
|
||||
// OrderByClause is the combination of an expression and the wanted ordering to use as input for ORDER BY.
|
||||
type OrderByClause = jet.OrderByClause
|
||||
|
||||
// SetLogger sets automatic statement logging
|
||||
var SetLogger = jet.SetLoggerFunc
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ var table1ColInterval = IntervalColumn("col_interval")
|
|||
var table1 = NewTable(
|
||||
"db",
|
||||
"table1",
|
||||
"",
|
||||
table1Col1,
|
||||
table1ColInt,
|
||||
table1ColFloat,
|
||||
|
|
@ -46,37 +47,21 @@ var table2ColTimestampz = TimestampzColumn("col_timestampz")
|
|||
var table2ColDate = DateColumn("col_date")
|
||||
var table2ColInterval = IntervalColumn("col_interval")
|
||||
|
||||
var table2 = NewTable(
|
||||
"db",
|
||||
"table2",
|
||||
table2Col3,
|
||||
table2Col4,
|
||||
table2ColInt,
|
||||
table2ColFloat,
|
||||
table2ColStr,
|
||||
table2ColBool,
|
||||
table2ColTime,
|
||||
table2ColTimez,
|
||||
table2ColDate,
|
||||
table2ColTimestamp,
|
||||
table2ColTimestampz,
|
||||
table2ColInterval,
|
||||
)
|
||||
var table2 = NewTable("db", "table2", "", table2Col3, table2Col4, table2ColInt, table2ColFloat, table2ColStr, table2ColBool, table2ColTime, table2ColTimez, table2ColDate, table2ColTimestamp, table2ColTimestampz, table2ColInterval)
|
||||
|
||||
var table3Col1 = IntegerColumn("col1")
|
||||
var table3ColInt = IntegerColumn("col_int")
|
||||
var table3StrCol = StringColumn("col2")
|
||||
var table3 = NewTable(
|
||||
"db",
|
||||
"table3",
|
||||
table3Col1,
|
||||
table3ColInt,
|
||||
table3StrCol)
|
||||
var table3 = NewTable("db", "table3", "", table3Col1, table3ColInt, table3StrCol)
|
||||
|
||||
func assertSerialize(t *testing.T, serializer jet.Serializer, query string, args ...interface{}) {
|
||||
testutils.AssertSerialize(t, Dialect, serializer, query, args...)
|
||||
}
|
||||
|
||||
func assertDebugSerialize(t *testing.T, serializer jet.Serializer, query string, args ...interface{}) {
|
||||
testutils.AssertDebugSerialize(t, Dialect, serializer, query, args...)
|
||||
}
|
||||
|
||||
func assertClauseSerialize(t *testing.T, clause jet.Clause, query string, args ...interface{}) {
|
||||
testutils.AssertClauseSerialize(t, Dialect, clause, query, args...)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ import (
|
|||
"database/sql"
|
||||
)
|
||||
|
||||
// DB is common database interface used by jet execution
|
||||
// DB is common database interface used by query result mapping
|
||||
// Both *sql.DB and *sql.Tx implements DB interface
|
||||
type DB interface {
|
||||
Exec(query string, args ...interface{}) (sql.Result, error)
|
||||
ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
|
||||
|
|
|
|||
51
qrm/qrm.go
51
qrm/qrm.go
|
|
@ -2,9 +2,12 @@ package qrm
|
|||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"github.com/go-jet/jet/v2/internal/utils"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/go-jet/jet/v2/internal/utils"
|
||||
)
|
||||
|
||||
// ErrNoRows is returned by Query when query result set is empty
|
||||
|
|
@ -56,6 +59,52 @@ func Query(ctx context.Context, db DB, query string, args []interface{}, destPtr
|
|||
}
|
||||
}
|
||||
|
||||
// ScanOneRowToDest will scan one row into struct destination
|
||||
func ScanOneRowToDest(rows *sql.Rows, destPtr interface{}) error {
|
||||
utils.MustBeInitializedPtr(destPtr, "jet: destination is nil")
|
||||
utils.MustBe(destPtr, reflect.Ptr, "jet: destination has to be a pointer to slice or pointer to struct")
|
||||
|
||||
scanContext, err := newScanContext(rows)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create scan context, %w", err)
|
||||
}
|
||||
|
||||
if len(scanContext.row) == 0 {
|
||||
return errors.New("empty row slice")
|
||||
}
|
||||
|
||||
err = rows.Scan(scanContext.row...)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("rows scan error, %w", err)
|
||||
}
|
||||
|
||||
destinationPtrType := reflect.TypeOf(destPtr)
|
||||
tempSlicePtrValue := reflect.New(reflect.SliceOf(destinationPtrType))
|
||||
tempSliceValue := tempSlicePtrValue.Elem()
|
||||
|
||||
_, err = mapRowToSlice(scanContext, "", tempSlicePtrValue, nil)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to map a row, %w", err)
|
||||
}
|
||||
|
||||
// edge case when row result set contains only NULLs.
|
||||
if tempSliceValue.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
destValue := reflect.ValueOf(destPtr).Elem()
|
||||
firstTempSliceValue := tempSliceValue.Index(0).Elem()
|
||||
|
||||
if destValue.Type().AssignableTo(firstTempSliceValue.Type()) {
|
||||
destValue.Set(tempSliceValue.Index(0).Elem())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func queryToSlice(ctx context.Context, db DB, query string, args []interface{}, slicePtr interface{}) (rowsProcessed int64, err error) {
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
|
|
|
|||
32
qrm/utill.go
32
qrm/utill.go
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/go-jet/jet/v2/qrm/internal"
|
||||
"github.com/google/uuid"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
|
@ -182,12 +183,16 @@ func isIntegerType(value reflect.Type) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func tryAssign(source, destination reflect.Value) bool {
|
||||
if source.Type().ConvertibleTo(destination.Type()) {
|
||||
source = source.Convert(destination.Type())
|
||||
}
|
||||
func isNumber(valueType reflect.Type) bool {
|
||||
return isIntegerType(valueType) || valueType == float64Type || valueType == float32Type
|
||||
}
|
||||
|
||||
if isIntegerType(source.Type()) && destination.Type() == boolType {
|
||||
func tryAssign(source, destination reflect.Value) bool {
|
||||
|
||||
switch {
|
||||
case source.Type().ConvertibleTo(destination.Type()):
|
||||
source = source.Convert(destination.Type())
|
||||
case isIntegerType(source.Type()) && destination.Type() == boolType:
|
||||
intValue := source.Int()
|
||||
|
||||
if intValue == 1 {
|
||||
|
|
@ -195,6 +200,18 @@ func tryAssign(source, destination reflect.Value) bool {
|
|||
} else if intValue == 0 {
|
||||
source = reflect.ValueOf(false)
|
||||
}
|
||||
case source.Type() == stringType && isNumber(destination.Type()):
|
||||
// if source is string and destination is a number(int8, int32, float32, ...), we first parse string to float64 number
|
||||
// and then parsed number is converted into destination type
|
||||
f, err := strconv.ParseFloat(source.String(), 64)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
source = reflect.ValueOf(f)
|
||||
|
||||
if source.Type().ConvertibleTo(destination.Type()) {
|
||||
source = source.Convert(destination.Type())
|
||||
}
|
||||
}
|
||||
|
||||
if source.Type().AssignableTo(destination.Type()) {
|
||||
|
|
@ -281,6 +298,9 @@ var int32Type = reflect.TypeOf(int32(1))
|
|||
var uint32Type = reflect.TypeOf(uint32(1))
|
||||
var int64Type = reflect.TypeOf(int64(1))
|
||||
var uint64Type = reflect.TypeOf(uint64(1))
|
||||
var float32Type = reflect.TypeOf(float32(1))
|
||||
var float64Type = reflect.TypeOf(float64(1))
|
||||
var stringType = reflect.TypeOf("")
|
||||
|
||||
var nullBoolType = reflect.TypeOf(sql.NullBool{})
|
||||
var nullInt8Type = reflect.TypeOf(internal.NullInt8{})
|
||||
|
|
@ -308,7 +328,7 @@ func newScanType(columnType *sql.ColumnType) reflect.Type {
|
|||
return nullStringType
|
||||
case "FLOAT4":
|
||||
return nullFloat32Type
|
||||
case "FLOAT8", "NUMERIC", "DECIMAL", "FLOAT", "DOUBLE":
|
||||
case "FLOAT8", "FLOAT", "DOUBLE":
|
||||
return nullFloat64Type
|
||||
case "BOOL":
|
||||
return nullBoolType
|
||||
|
|
|
|||
|
|
@ -35,3 +35,48 @@ func TestIsSimpleModelType(t *testing.T) {
|
|||
require.Equal(t, isSimpleModelType(reflect.TypeOf([]string{"str"})), false)
|
||||
require.Equal(t, isSimpleModelType(reflect.TypeOf([]int{1, 2})), false)
|
||||
}
|
||||
|
||||
func TestTryAssign(t *testing.T) {
|
||||
convertible := int16(16)
|
||||
intBool1 := int32(1)
|
||||
intBool0 := int32(0)
|
||||
intBool2 := int32(2)
|
||||
floatStr := "1.11"
|
||||
floatErr := "1.abcd2"
|
||||
str := "some string"
|
||||
|
||||
destination := struct {
|
||||
Convertible int64
|
||||
IntBool1 bool
|
||||
IntBool0 bool
|
||||
IntBool2 bool
|
||||
FloatStr float64
|
||||
FloatErr float64
|
||||
Str string
|
||||
}{}
|
||||
|
||||
testValue := reflect.ValueOf(&destination).Elem()
|
||||
|
||||
// convertible
|
||||
require.True(t, tryAssign(reflect.ValueOf(convertible), testValue.FieldByName("Convertible")))
|
||||
require.Equal(t, int64(16), destination.Convertible)
|
||||
|
||||
// 1/0 to bool
|
||||
require.True(t, tryAssign(reflect.ValueOf(intBool1), testValue.FieldByName("IntBool1")))
|
||||
require.Equal(t, true, destination.IntBool1)
|
||||
require.True(t, tryAssign(reflect.ValueOf(intBool0), testValue.FieldByName("IntBool0")))
|
||||
require.Equal(t, false, destination.IntBool0)
|
||||
|
||||
require.False(t, tryAssign(reflect.ValueOf(intBool2), testValue.FieldByName("IntBool2")))
|
||||
require.Equal(t, false, destination.IntBool2)
|
||||
|
||||
// string to float
|
||||
require.True(t, tryAssign(reflect.ValueOf(floatStr), testValue.FieldByName("FloatStr")))
|
||||
require.Equal(t, 1.11, destination.FloatStr)
|
||||
require.False(t, tryAssign(reflect.ValueOf(floatErr), testValue.FieldByName("FloatErr")))
|
||||
require.Equal(t, 0.00, destination.FloatErr)
|
||||
|
||||
// string to string
|
||||
require.True(t, tryAssign(reflect.ValueOf(str), testValue.FieldByName("Str")))
|
||||
require.Equal(t, str, destination.Str)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ func initMySQLDB() {
|
|||
|
||||
mySQLDBs := []string{
|
||||
"dvds",
|
||||
"dvds2",
|
||||
"test_sample",
|
||||
}
|
||||
|
||||
|
|
@ -89,6 +90,7 @@ func initPostgresDB() {
|
|||
"dvds",
|
||||
"test_sample",
|
||||
"chinook",
|
||||
"chinook2",
|
||||
"northwind",
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package mysql
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/shopspring/decimal"
|
||||
"github.com/stretchr/testify/require"
|
||||
"strings"
|
||||
"testing"
|
||||
|
|
@ -78,7 +78,7 @@ func TestUUID(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
require.True(t, dest.StrUUID != nil)
|
||||
require.True(t, dest.UUID.String() != uuid.UUID{}.String())
|
||||
require.True(t, dest.StrUUID.String() != uuid.UUID{}.String())
|
||||
require.Equal(t, dest.StrUUID.String(), "dc8daae3-b83b-11e9-8eb4-98ded00c39c6")
|
||||
require.Equal(t, dest.StrUUID.String(), dest.BinUUID.String())
|
||||
requireLogged(t, query)
|
||||
}
|
||||
|
|
@ -89,14 +89,17 @@ func TestExpressionOperators(t *testing.T) {
|
|||
AllTypes.DatePtr.IS_NOT_NULL().AS("result.is_not_null"),
|
||||
AllTypes.SmallIntPtr.IN(Int(11), Int(22)).AS("result.in"),
|
||||
AllTypes.SmallIntPtr.IN(AllTypes.SELECT(AllTypes.Integer)).AS("result.in_select"),
|
||||
|
||||
Raw("CURRENT_USER()").AS("result.raw"),
|
||||
Raw(":first + COALESCE(all_types.small_int_ptr, 0) + :second", RawArgs{":first": 78, ":second": 56}).
|
||||
AS("result.raw_arg"),
|
||||
Raw("#1 + all_types.integer + #2 + #1 + #3 + #4", RawArgs{"#1": 11, "#2": 22, "#3": 33, "#4": 44}).
|
||||
AS("result.raw_arg2"),
|
||||
|
||||
AllTypes.SmallIntPtr.NOT_IN(Int(11), Int(22), NULL).AS("result.not_in"),
|
||||
AllTypes.SmallIntPtr.NOT_IN(AllTypes.SELECT(AllTypes.Integer)).AS("result.not_in_select"),
|
||||
|
||||
Raw("DATABASE()"),
|
||||
).LIMIT(2)
|
||||
|
||||
//fmt.Println(query.Sql())
|
||||
|
||||
testutils.AssertStatementSql(t, query, strings.Replace(`
|
||||
SELECT all_types.'integer' IS NULL AS "result.is_null",
|
||||
all_types.date_ptr IS NOT NULL AS "result.is_not_null",
|
||||
|
|
@ -105,46 +108,34 @@ SELECT all_types.'integer' IS NULL AS "result.is_null",
|
|||
SELECT all_types.'integer' AS "all_types.integer"
|
||||
FROM test_sample.all_types
|
||||
))) AS "result.in_select",
|
||||
(CURRENT_USER()) AS "result.raw",
|
||||
(? + COALESCE(all_types.small_int_ptr, 0) + ?) AS "result.raw_arg",
|
||||
(? + all_types.integer + ? + ? + ? + ?) AS "result.raw_arg2",
|
||||
(all_types.small_int_ptr NOT IN (?, ?, NULL)) AS "result.not_in",
|
||||
(all_types.small_int_ptr NOT IN ((
|
||||
SELECT all_types.'integer' AS "all_types.integer"
|
||||
FROM test_sample.all_types
|
||||
))) AS "result.not_in_select",
|
||||
DATABASE()
|
||||
))) AS "result.not_in_select"
|
||||
FROM test_sample.all_types
|
||||
LIMIT ?;
|
||||
`, "'", "`", -1), int64(11), int64(22), int64(11), int64(22), int64(2))
|
||||
`, "'", "`", -1), int64(11), int64(22), 78, 56, 11, 22, 11, 33, 44, int64(11), int64(22), int64(2))
|
||||
|
||||
var dest []struct {
|
||||
common.ExpressionTestResult `alias:"result.*"`
|
||||
}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
//testutils.PrintJson(dest)
|
||||
|
||||
testutils.AssertJSON(t, dest, `
|
||||
[
|
||||
{
|
||||
"IsNull": false,
|
||||
"IsNotNull": true,
|
||||
"In": false,
|
||||
"InSelect": false,
|
||||
"NotIn": null,
|
||||
"NotInSelect": true
|
||||
},
|
||||
{
|
||||
"IsNull": false,
|
||||
"IsNotNull": false,
|
||||
"In": null,
|
||||
"InSelect": null,
|
||||
"NotIn": null,
|
||||
"NotInSelect": null
|
||||
}
|
||||
]
|
||||
`)
|
||||
require.Equal(t, *dest[0].IsNull, false)
|
||||
require.Equal(t, *dest[0].IsNotNull, true)
|
||||
require.Equal(t, *dest[0].In, false)
|
||||
require.Equal(t, *dest[0].InSelect, false)
|
||||
require.True(t, strings.Contains(*dest[0].Raw, "jet"))
|
||||
require.Equal(t, *dest[0].RawArg, int32(148))
|
||||
require.Equal(t, *dest[0].RawArg2, int32(-1479))
|
||||
require.Nil(t, dest[0].NotIn)
|
||||
require.Equal(t, *dest[0].NotInSelect, true)
|
||||
}
|
||||
|
||||
func TestBoolOperators(t *testing.T) {
|
||||
|
|
@ -974,7 +965,7 @@ func TestAllTypesInsert(t *testing.T) {
|
|||
stmt := AllTypes.INSERT(AllTypes.AllColumns).
|
||||
MODEL(toInsert)
|
||||
|
||||
fmt.Println(stmt.DebugSql())
|
||||
//fmt.Println(stmt.DebugSql())
|
||||
|
||||
testutils.AssertExec(t, stmt, tx, 1)
|
||||
|
||||
|
|
@ -1028,7 +1019,7 @@ func TestAllTypesInsertOnDuplicateKeyUpdate(t *testing.T) {
|
|||
AllTypes.Date.SET(DateT(time.Now())),
|
||||
)
|
||||
|
||||
fmt.Println(stmt.DebugSql())
|
||||
//fmt.Println(stmt.DebugSql())
|
||||
|
||||
_, err = stmt.Exec(tx)
|
||||
require.NoError(t, err)
|
||||
|
|
@ -1257,7 +1248,7 @@ FROM test_sample.user;
|
|||
err := stmt.Query(db, &dest)
|
||||
require.NoError(t, err)
|
||||
|
||||
testutils.PrintJson(dest)
|
||||
//testutils.PrintJson(dest)
|
||||
|
||||
testutils.AssertJSON(t, dest, `
|
||||
[
|
||||
|
|
@ -1279,3 +1270,99 @@ FROM test_sample.user;
|
|||
]
|
||||
`)
|
||||
}
|
||||
|
||||
func TestExactDecimals(t *testing.T) {
|
||||
|
||||
type floats struct {
|
||||
model.Floats
|
||||
Numeric decimal.Decimal
|
||||
NumericPtr decimal.Decimal
|
||||
Decimal decimal.Decimal
|
||||
DecimalPtr decimal.Decimal
|
||||
}
|
||||
|
||||
t.Run("should query decimal", func(t *testing.T) {
|
||||
query := SELECT(
|
||||
Floats.AllColumns,
|
||||
).FROM(
|
||||
Floats,
|
||||
).WHERE(Floats.Decimal.EQ(Decimal("1.11111111111111111111")))
|
||||
|
||||
var result floats
|
||||
|
||||
err := query.Query(db, &result)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, "1.11111111111111111111", result.Decimal.String())
|
||||
require.Equal(t, "0", result.DecimalPtr.String()) // NULL
|
||||
require.Equal(t, "2.22222222222222222222", result.Numeric.String())
|
||||
require.Equal(t, "0", result.NumericPtr.String()) // NULL
|
||||
|
||||
require.Equal(t, 1.1111111111111112, result.Floats.Decimal) // precision loss
|
||||
require.Equal(t, (*float64)(nil), result.Floats.DecimalPtr)
|
||||
require.Equal(t, 2.2222222222222223, result.Floats.Numeric) // precision loss
|
||||
require.Equal(t, (*float64)(nil), result.Floats.NumericPtr)
|
||||
|
||||
// floating point
|
||||
require.Equal(t, 3.3333333, result.Floats.Float) // precision loss
|
||||
require.Equal(t, (*float64)(nil), result.Floats.FloatPtr)
|
||||
require.Equal(t, 4.444444444444445, result.Floats.Double) // precision loss
|
||||
require.Equal(t, (*float64)(nil), result.Floats.DoublePtr)
|
||||
require.Equal(t, 5.555555555555555, result.Floats.Real) // precision loss
|
||||
require.Equal(t, (*float64)(nil), result.Floats.RealPtr)
|
||||
})
|
||||
|
||||
t.Run("should insert decimal", func(t *testing.T) {
|
||||
|
||||
insertQuery := Floats.INSERT(
|
||||
Floats.AllColumns,
|
||||
).MODEL(
|
||||
floats{
|
||||
Floats: model.Floats{
|
||||
// overwritten by wrapped(floats) scope
|
||||
Numeric: 0.1,
|
||||
NumericPtr: testutils.Float64Ptr(0.1),
|
||||
Decimal: 0.1,
|
||||
DecimalPtr: testutils.Float64Ptr(0.1),
|
||||
|
||||
// not overwritten
|
||||
Float: 0.2,
|
||||
FloatPtr: testutils.Float64Ptr(0.22),
|
||||
Double: 0.3,
|
||||
DoublePtr: testutils.Float64Ptr(0.33),
|
||||
Real: 0.4,
|
||||
RealPtr: testutils.Float64Ptr(0.44),
|
||||
},
|
||||
Numeric: decimal.RequireFromString("12.35"),
|
||||
NumericPtr: decimal.RequireFromString("56.79"),
|
||||
Decimal: decimal.RequireFromString("91.23"),
|
||||
DecimalPtr: decimal.RequireFromString("45.67"),
|
||||
},
|
||||
)
|
||||
|
||||
testutils.AssertDebugStatementSql(t, insertQuery, strings.Replace(`
|
||||
INSERT INTO test_sample.floats (''decimal'', decimal_ptr, ''numeric'', numeric_ptr, ''float'', float_ptr, ''double'', double_ptr, ''real'', real_ptr)
|
||||
VALUES ('91.23', '45.67', '12.35', '56.79', 0.2, 0.22, 0.3, 0.33, 0.4, 0.44);
|
||||
`, "''", "`", -1))
|
||||
_, err := insertQuery.Exec(db)
|
||||
require.NoError(t, err)
|
||||
|
||||
var result floats
|
||||
|
||||
err = SELECT(Floats.AllColumns).
|
||||
FROM(Floats).
|
||||
WHERE(Floats.Numeric.EQ(Float(12.35))).
|
||||
Query(db, &result)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, "12.35", result.Numeric.String())
|
||||
require.Equal(t, "56.79", result.NumericPtr.String())
|
||||
require.Equal(t, "91.23", result.Decimal.String())
|
||||
require.Equal(t, "45.67", result.DecimalPtr.String())
|
||||
|
||||
require.Equal(t, 12.35, result.Floats.Numeric)
|
||||
require.Equal(t, 56.79, *result.Floats.NumericPtr)
|
||||
require.Equal(t, 91.23, result.Floats.Decimal)
|
||||
require.Equal(t, 45.67, *result.Floats.DecimalPtr)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,12 +35,7 @@ func TestGenerator(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCmdGenerator(t *testing.T) {
|
||||
goInstallJet := exec.Command("sh", "-c", "cd $GOPATH/src/ && GO111MODULE=off go get github.com/go-jet/jet/cmd/jet")
|
||||
goInstallJet.Stderr = os.Stderr
|
||||
err := goInstallJet.Run()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = os.RemoveAll(genTestDir3)
|
||||
err := os.RemoveAll(genTestDir3)
|
||||
require.NoError(t, err)
|
||||
|
||||
cmd := exec.Command("jet", "-source=MySQL", "-dbname=dvds", "-host=localhost", "-port=3306",
|
||||
|
|
@ -140,7 +135,7 @@ import (
|
|||
"github.com/go-jet/jet/v2/mysql"
|
||||
)
|
||||
|
||||
var Actor = newActorTable()
|
||||
var Actor = newActorTable("dvds", "actor", "")
|
||||
|
||||
type ActorTable struct {
|
||||
mysql.Table
|
||||
|
|
@ -156,13 +151,16 @@ type ActorTable struct {
|
|||
}
|
||||
|
||||
// AS creates new ActorTable with assigned alias
|
||||
func (a *ActorTable) AS(alias string) ActorTable {
|
||||
aliasTable := newActorTable()
|
||||
aliasTable.Table.AS(alias)
|
||||
return aliasTable
|
||||
func (a ActorTable) AS(alias string) ActorTable {
|
||||
return newActorTable(a.SchemaName(), a.TableName(), alias)
|
||||
}
|
||||
|
||||
func newActorTable() ActorTable {
|
||||
// Schema creates new ActorTable with assigned schema name
|
||||
func (a ActorTable) FromSchema(schemaName string) ActorTable {
|
||||
return newActorTable(schemaName, a.TableName(), a.Alias())
|
||||
}
|
||||
|
||||
func newActorTable(schemaName, tableName, alias string) ActorTable {
|
||||
var (
|
||||
ActorIDColumn = mysql.IntegerColumn("actor_id")
|
||||
FirstNameColumn = mysql.StringColumn("first_name")
|
||||
|
|
@ -173,7 +171,7 @@ func newActorTable() ActorTable {
|
|||
)
|
||||
|
||||
return ActorTable{
|
||||
Table: mysql.NewTable("dvds", "actor", allColumns...),
|
||||
Table: mysql.NewTable(schemaName, tableName, alias, allColumns...),
|
||||
|
||||
//Columns
|
||||
ActorID: ActorIDColumn,
|
||||
|
|
@ -223,7 +221,7 @@ import (
|
|||
"github.com/go-jet/jet/v2/mysql"
|
||||
)
|
||||
|
||||
var ActorInfo = newActorInfoTable()
|
||||
var ActorInfo = newActorInfoTable("dvds", "actor_info", "")
|
||||
|
||||
type ActorInfoTable struct {
|
||||
mysql.Table
|
||||
|
|
@ -239,13 +237,16 @@ type ActorInfoTable struct {
|
|||
}
|
||||
|
||||
// AS creates new ActorInfoTable with assigned alias
|
||||
func (a *ActorInfoTable) AS(alias string) ActorInfoTable {
|
||||
aliasTable := newActorInfoTable()
|
||||
aliasTable.Table.AS(alias)
|
||||
return aliasTable
|
||||
func (a ActorInfoTable) AS(alias string) ActorInfoTable {
|
||||
return newActorInfoTable(a.SchemaName(), a.TableName(), alias)
|
||||
}
|
||||
|
||||
func newActorInfoTable() ActorInfoTable {
|
||||
// Schema creates new ActorInfoTable with assigned schema name
|
||||
func (a ActorInfoTable) FromSchema(schemaName string) ActorInfoTable {
|
||||
return newActorInfoTable(schemaName, a.TableName(), a.Alias())
|
||||
}
|
||||
|
||||
func newActorInfoTable(schemaName, tableName, alias string) ActorInfoTable {
|
||||
var (
|
||||
ActorIDColumn = mysql.IntegerColumn("actor_id")
|
||||
FirstNameColumn = mysql.StringColumn("first_name")
|
||||
|
|
@ -256,7 +257,7 @@ func newActorInfoTable() ActorInfoTable {
|
|||
)
|
||||
|
||||
return ActorInfoTable{
|
||||
Table: mysql.NewTable("dvds", "actor_info", allColumns...),
|
||||
Table: mysql.NewTable(schemaName, tableName, alias, allColumns...),
|
||||
|
||||
//Columns
|
||||
ActorID: ActorIDColumn,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package mysql
|
|||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"flag"
|
||||
jetmysql "github.com/go-jet/jet/v2/mysql"
|
||||
"github.com/go-jet/jet/v2/postgres"
|
||||
"github.com/go-jet/jet/v2/tests/dbconfig"
|
||||
|
|
@ -25,8 +24,7 @@ var source string
|
|||
const MariaDB = "MariaDB"
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&source, "source", "", "MySQL or MariaDB")
|
||||
flag.Parse()
|
||||
source = os.Getenv("MY_SQL_SOURCE")
|
||||
}
|
||||
|
||||
func sourceIsMariaDB() bool {
|
||||
|
|
@ -66,3 +64,9 @@ func requireLogged(t *testing.T, statement postgres.Statement) {
|
|||
require.Equal(t, loggedSQLArgs, args)
|
||||
require.Equal(t, loggedDebugSQL, statement.DebugSql())
|
||||
}
|
||||
|
||||
func skipForMariaDB(t *testing.T) {
|
||||
if sourceIsMariaDB() {
|
||||
t.SkipNow()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
123
tests/mysql/raw_statement_test.go
Normal file
123
tests/mysql/raw_statement_test.go
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
package mysql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/go-jet/jet/v2/internal/testutils"
|
||||
"github.com/go-jet/jet/v2/tests/.gentestdata/mysql/dvds/model"
|
||||
|
||||
. "github.com/go-jet/jet/v2/mysql"
|
||||
)
|
||||
|
||||
func TestRawStatementSelect(t *testing.T) {
|
||||
stmt := RawStatement(`
|
||||
SELECT actor.first_name AS "actor.first_name"
|
||||
FROM dvds.actor
|
||||
WHERE actor.actor_id = 2`)
|
||||
|
||||
testutils.AssertStatementSql(t, stmt, `
|
||||
SELECT actor.first_name AS "actor.first_name"
|
||||
FROM dvds.actor
|
||||
WHERE actor.actor_id = 2;
|
||||
`)
|
||||
testutils.AssertDebugStatementSql(t, stmt, `
|
||||
SELECT actor.first_name AS "actor.first_name"
|
||||
FROM dvds.actor
|
||||
WHERE actor.actor_id = 2;
|
||||
`)
|
||||
var actor model.Actor
|
||||
err := stmt.Query(db, &actor)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, actor.FirstName, "NICK")
|
||||
}
|
||||
|
||||
func TestRawStatementSelectWithArguments(t *testing.T) {
|
||||
stmt := RawStatement(`
|
||||
SELECT DISTINCT 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"
|
||||
FROM dvds.actor
|
||||
WHERE actor.actor_id IN (#actorID1, #actorID2, #actorID3) AND ((#actorID1 / #actorID2) <> (#actorID2 * #actorID3))
|
||||
ORDER BY actor.actor_id`,
|
||||
RawArgs{
|
||||
"#actorID1": int64(1),
|
||||
"#actorID2": int64(2),
|
||||
"#actorID3": int64(3),
|
||||
},
|
||||
)
|
||||
|
||||
testutils.AssertStatementSql(t, stmt, `
|
||||
SELECT DISTINCT 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"
|
||||
FROM dvds.actor
|
||||
WHERE actor.actor_id IN (?, ?, ?) AND ((? / ?) <> (? * ?))
|
||||
ORDER BY actor.actor_id;
|
||||
`, int64(1), int64(2), int64(3), int64(1), int64(2), int64(2), int64(3))
|
||||
|
||||
testutils.AssertDebugStatementSql(t, stmt, `
|
||||
SELECT DISTINCT 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"
|
||||
FROM dvds.actor
|
||||
WHERE actor.actor_id IN (1, 2, 3) AND ((1 / 2) <> (2 * 3))
|
||||
ORDER BY actor.actor_id;
|
||||
`)
|
||||
|
||||
var actor []model.Actor
|
||||
err := stmt.Query(db, &actor)
|
||||
require.NoError(t, err)
|
||||
|
||||
testutils.AssertDeepEqual(t, actor[1], model.Actor{
|
||||
ActorID: 2,
|
||||
FirstName: "NICK",
|
||||
LastName: "WAHLBERG",
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2006-02-15 04:34:33", 2),
|
||||
})
|
||||
}
|
||||
|
||||
func TestRawStatementRows(t *testing.T) {
|
||||
stmt := RawStatement(`
|
||||
SELECT 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"
|
||||
FROM dvds.actor
|
||||
ORDER BY actor.actor_id`)
|
||||
|
||||
rows, err := stmt.Rows(context.Background(), db)
|
||||
require.NoError(t, err)
|
||||
|
||||
for rows.Next() {
|
||||
var actor model.Actor
|
||||
err := rows.Scan(&actor)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NotEqual(t, actor.ActorID, int16(0))
|
||||
require.NotEqual(t, actor.FirstName, "")
|
||||
require.NotEqual(t, actor.LastName, "")
|
||||
require.NotEqual(t, actor.LastUpdate, time.Time{})
|
||||
|
||||
if actor.ActorID == 54 {
|
||||
require.Equal(t, actor.ActorID, uint16(54))
|
||||
require.Equal(t, actor.FirstName, "PENELOPE")
|
||||
require.Equal(t, actor.LastName, "PINKETT")
|
||||
require.Equal(t, actor.LastUpdate.Format(time.RFC3339), "2006-02-15T04:34:33Z")
|
||||
}
|
||||
}
|
||||
|
||||
err = rows.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = rows.Err()
|
||||
require.NoError(t, err)
|
||||
|
||||
requireLogged(t, stmt)
|
||||
}
|
||||
|
|
@ -1,15 +1,19 @@
|
|||
package mysql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-jet/jet/v2/internal/testutils"
|
||||
. "github.com/go-jet/jet/v2/mysql"
|
||||
"github.com/go-jet/jet/v2/tests/.gentestdata/mysql/dvds/enum"
|
||||
"github.com/go-jet/jet/v2/tests/.gentestdata/mysql/dvds/model"
|
||||
. "github.com/go-jet/jet/v2/tests/.gentestdata/mysql/dvds/table"
|
||||
"github.com/go-jet/jet/v2/tests/.gentestdata/mysql/dvds/view"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"testing"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSelect_ScanToStruct(t *testing.T) {
|
||||
|
|
@ -744,3 +748,227 @@ LIMIT 3;
|
|||
|
||||
require.Equal(t, len(dest), 3)
|
||||
}
|
||||
|
||||
func Test_SchemaRename(t *testing.T) {
|
||||
Film := Film.FromSchema("dvds2")
|
||||
Language := Language.FromSchema("dvds2")
|
||||
|
||||
stmt := SELECT(
|
||||
Film.FilmID,
|
||||
Film.Title,
|
||||
Language.LanguageID,
|
||||
Language.Name,
|
||||
).FROM(
|
||||
Language.
|
||||
INNER_JOIN(Film, Film.LanguageID.EQ(Language.LanguageID)),
|
||||
).WHERE(
|
||||
Language.LanguageID.EQ(Int(1)),
|
||||
).ORDER_BY(
|
||||
Language.LanguageID, Film.FilmID,
|
||||
).LIMIT(5)
|
||||
|
||||
testutils.AssertDebugStatementSql(t, stmt, `
|
||||
SELECT film.film_id AS "film.film_id",
|
||||
film.title AS "film.title",
|
||||
language.language_id AS "language.language_id",
|
||||
language.name AS "language.name"
|
||||
FROM dvds2.language
|
||||
INNER JOIN dvds2.film ON (film.language_id = language.language_id)
|
||||
WHERE language.language_id = 1
|
||||
ORDER BY language.language_id, film.film_id
|
||||
LIMIT 5;
|
||||
`)
|
||||
|
||||
dest := struct {
|
||||
model.Language
|
||||
Films []model.Film
|
||||
}{}
|
||||
|
||||
err := stmt.Query(db, &dest)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, dest.Films, 5)
|
||||
require.Equal(t, dest.Films[0].Title, "ACADEMY DINOSAUR")
|
||||
require.Equal(t, dest.Films[1].Title, "ACE GOLDFINGER")
|
||||
require.Equal(t, dest.Films[4].Title, "AFRICAN EGG")
|
||||
}
|
||||
|
||||
func TestLateral(t *testing.T) {
|
||||
skipForMariaDB(t) // MariaDB does not implement LATERAL
|
||||
|
||||
languages := LATERAL(
|
||||
SELECT(
|
||||
Language.AllColumns,
|
||||
).FROM(
|
||||
Language,
|
||||
).WHERE(
|
||||
Language.Name.NOT_IN(String("spanish")).
|
||||
AND(Film.LanguageID.EQ(Language.LanguageID)),
|
||||
),
|
||||
).AS("films")
|
||||
|
||||
stmt := SELECT(
|
||||
Film.FilmID,
|
||||
Film.Title,
|
||||
languages.AllColumns(),
|
||||
).FROM(
|
||||
Film.CROSS_JOIN(languages),
|
||||
).WHERE(
|
||||
Film.FilmID.EQ(Int(1)),
|
||||
).ORDER_BY(
|
||||
Film.FilmID,
|
||||
).LIMIT(1)
|
||||
|
||||
testutils.AssertDebugStatementSql(t, stmt, strings.Replace(`
|
||||
SELECT film.film_id AS "film.film_id",
|
||||
film.title AS "film.title",
|
||||
films.''language.language_id'' AS "language.language_id",
|
||||
films.''language.name'' AS "language.name",
|
||||
films.''language.last_update'' AS "language.last_update"
|
||||
FROM dvds.film
|
||||
CROSS JOIN LATERAL (
|
||||
SELECT language.language_id AS "language.language_id",
|
||||
language.name AS "language.name",
|
||||
language.last_update AS "language.last_update"
|
||||
FROM dvds.language
|
||||
WHERE (language.name NOT IN ('spanish')) AND (film.language_id = language.language_id)
|
||||
) AS films
|
||||
WHERE film.film_id = 1
|
||||
ORDER BY film.film_id
|
||||
LIMIT 1;
|
||||
`, "''", "`", -1))
|
||||
|
||||
type FilmLanguage struct {
|
||||
model.Film
|
||||
model.Language
|
||||
}
|
||||
|
||||
var dest []FilmLanguage
|
||||
|
||||
err := stmt.Query(db, &dest)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, dest[0].Film.Title, "ACADEMY DINOSAUR")
|
||||
require.Equal(t, dest[0].Language.Name, "English")
|
||||
|
||||
t.Run("implicit cross join", func(t *testing.T) {
|
||||
stmt2 := SELECT(
|
||||
Film.FilmID,
|
||||
Film.Title,
|
||||
languages.AllColumns(),
|
||||
).FROM(
|
||||
Film,
|
||||
languages,
|
||||
).WHERE(
|
||||
Film.FilmID.EQ(Int(1)),
|
||||
).ORDER_BY(
|
||||
Film.FilmID,
|
||||
).LIMIT(1)
|
||||
|
||||
testutils.AssertDebugStatementSql(t, stmt2, strings.Replace(`
|
||||
SELECT film.film_id AS "film.film_id",
|
||||
film.title AS "film.title",
|
||||
films.''language.language_id'' AS "language.language_id",
|
||||
films.''language.name'' AS "language.name",
|
||||
films.''language.last_update'' AS "language.last_update"
|
||||
FROM dvds.film,
|
||||
LATERAL (
|
||||
SELECT language.language_id AS "language.language_id",
|
||||
language.name AS "language.name",
|
||||
language.last_update AS "language.last_update"
|
||||
FROM dvds.language
|
||||
WHERE (language.name NOT IN ('spanish')) AND (film.language_id = language.language_id)
|
||||
) AS films
|
||||
WHERE film.film_id = 1
|
||||
ORDER BY film.film_id
|
||||
LIMIT 1;
|
||||
`, "''", "`", -1))
|
||||
|
||||
var dest2 []FilmLanguage
|
||||
|
||||
err2 := stmt2.Query(db, &dest2)
|
||||
require.NoError(t, err2)
|
||||
require.Equal(t, dest, dest2)
|
||||
})
|
||||
}
|
||||
|
||||
func TestRowsScan(t *testing.T) {
|
||||
|
||||
stmt := SELECT(
|
||||
Inventory.AllColumns,
|
||||
).FROM(
|
||||
Inventory,
|
||||
).ORDER_BY(
|
||||
Inventory.InventoryID.ASC(),
|
||||
)
|
||||
|
||||
rows, err := stmt.Rows(context.Background(), db)
|
||||
require.NoError(t, err)
|
||||
|
||||
for rows.Next() {
|
||||
var inventory model.Inventory
|
||||
err = rows.Scan(&inventory)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NotEqual(t, inventory.InventoryID, uint32(0))
|
||||
require.NotEqual(t, inventory.FilmID, uint16(0))
|
||||
require.NotEqual(t, inventory.StoreID, uint16(0))
|
||||
require.NotEqual(t, inventory.LastUpdate, time.Time{})
|
||||
|
||||
if inventory.InventoryID == 2103 {
|
||||
require.Equal(t, inventory.FilmID, uint16(456))
|
||||
require.Equal(t, inventory.StoreID, uint8(2))
|
||||
require.Equal(t, inventory.LastUpdate.Format(time.RFC3339), "2006-02-15T05:09:17Z")
|
||||
}
|
||||
}
|
||||
|
||||
err = rows.Close()
|
||||
require.NoError(t, err)
|
||||
err = rows.Err()
|
||||
require.NoError(t, err)
|
||||
|
||||
requireLogged(t, stmt)
|
||||
}
|
||||
|
||||
func TestScanNumericToNumber(t *testing.T) {
|
||||
type Number struct {
|
||||
Int8 int8
|
||||
UInt8 uint8
|
||||
Int16 int16
|
||||
UInt16 uint16
|
||||
Int32 int32
|
||||
UInt32 uint32
|
||||
Int64 int64
|
||||
UInt64 uint64
|
||||
Float32 float32
|
||||
Float64 float64
|
||||
}
|
||||
|
||||
numeric := CAST(Decimal("1234567890.111")).AS_DECIMAL()
|
||||
|
||||
stmt := SELECT(
|
||||
numeric.AS("number.int8"),
|
||||
numeric.AS("number.uint8"),
|
||||
numeric.AS("number.int16"),
|
||||
numeric.AS("number.uint16"),
|
||||
numeric.AS("number.int32"),
|
||||
numeric.AS("number.uint32"),
|
||||
numeric.AS("number.int64"),
|
||||
numeric.AS("number.uint64"),
|
||||
numeric.AS("number.float32"),
|
||||
numeric.AS("number.float64"),
|
||||
)
|
||||
|
||||
var number Number
|
||||
err := stmt.Query(db, &number)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, number.Int8, int8(-46)) // overflow
|
||||
require.Equal(t, number.UInt8, uint8(210)) // overflow
|
||||
require.Equal(t, number.Int16, int16(722)) // overflow
|
||||
require.Equal(t, number.UInt16, uint16(722)) // overflow
|
||||
require.Equal(t, number.Int32, int32(1234567890))
|
||||
require.Equal(t, number.UInt32, uint32(1234567890))
|
||||
require.Equal(t, number.Int64, int64(1234567890))
|
||||
require.Equal(t, number.UInt64, uint64(1234567890))
|
||||
require.Equal(t, number.Float32, float32(1.234568e+09))
|
||||
require.Equal(t, number.Float64, float64(1.23456789e+09))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package mysql
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/go-jet/jet/v2/internal/testutils"
|
||||
. "github.com/go-jet/jet/v2/mysql"
|
||||
"github.com/go-jet/jet/v2/tests/.gentestdata/mysql/dvds/table"
|
||||
|
|
@ -193,7 +192,7 @@ SET url = 'http://www.duckduckgo.com',
|
|||
description = NULL
|
||||
WHERE link.id = 201;
|
||||
`
|
||||
fmt.Println(stmt.DebugSql())
|
||||
//fmt.Println(stmt.DebugSql())
|
||||
|
||||
testutils.AssertDebugStatementSql(t, stmt, expectedSQL, "http://www.duckduckgo.com", "DuckDuckGo", nil, int64(201))
|
||||
testutils.AssertExec(t, stmt, db)
|
||||
|
|
|
|||
|
|
@ -1,20 +1,24 @@
|
|||
package postgres
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/go-jet/jet/v2/internal/testutils"
|
||||
. "github.com/go-jet/jet/v2/postgres"
|
||||
"github.com/go-jet/jet/v2/tests/.gentestdata/jetdb/test_sample/model"
|
||||
. "github.com/go-jet/jet/v2/tests/.gentestdata/jetdb/test_sample/table"
|
||||
"github.com/go-jet/jet/v2/tests/.gentestdata/jetdb/test_sample/view"
|
||||
"github.com/go-jet/jet/v2/tests/testdata/results/common"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func TestAllTypesSelect(t *testing.T) {
|
||||
skipForPgxDriver(t) // pgx driver returns time with time zone as string
|
||||
|
||||
dest := []model.AllTypes{}
|
||||
|
||||
err := AllTypes.SELECT(AllTypes.AllColumns).Query(db, &dest)
|
||||
|
|
@ -25,6 +29,8 @@ func TestAllTypesSelect(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAllTypesViewSelect(t *testing.T) {
|
||||
skipForPgxDriver(t) // pgx driver returns time with time zone as string
|
||||
|
||||
type AllTypesView model.AllTypes
|
||||
|
||||
dest := []AllTypesView{}
|
||||
|
|
@ -37,6 +43,8 @@ func TestAllTypesViewSelect(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAllTypesInsertModel(t *testing.T) {
|
||||
skipForPgxDriver(t) // pgx driver does not handle well time with time zone
|
||||
|
||||
query := AllTypes.INSERT(AllTypes.AllColumns).
|
||||
MODEL(allTypesRow0).
|
||||
MODEL(&allTypesRow1).
|
||||
|
|
@ -52,6 +60,8 @@ func TestAllTypesInsertModel(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAllTypesInsertQuery(t *testing.T) {
|
||||
skipForPgxDriver(t) // pgx driver does not handle well time with time zone
|
||||
|
||||
query := AllTypes.INSERT(AllTypes.AllColumns).
|
||||
QUERY(
|
||||
AllTypes.
|
||||
|
|
@ -70,6 +80,7 @@ func TestAllTypesInsertQuery(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAllTypesFromSubQuery(t *testing.T) {
|
||||
skipForPgxDriver(t)
|
||||
|
||||
subQuery := SELECT(AllTypes.AllColumns).
|
||||
FROM(AllTypes).
|
||||
|
|
@ -221,12 +232,16 @@ func TestExpressionOperators(t *testing.T) {
|
|||
AllTypes.DatePtr.IS_NOT_NULL().AS("result.is_not_null"),
|
||||
AllTypes.SmallIntPtr.IN(Int(11), Int(22)).AS("result.in"),
|
||||
AllTypes.SmallIntPtr.IN(AllTypes.SELECT(AllTypes.Integer)).AS("result.in_select"),
|
||||
|
||||
Raw("CURRENT_USER").AS("result.raw"),
|
||||
Raw("#1 + COALESCE(all_types.small_int_ptr, 0) + #2", RawArgs{"#1": 78, "#2": 56}).AS("result.raw_arg"),
|
||||
Raw("#1 + all_types.integer + #2 + #1 + #3 + #4",
|
||||
RawArgs{"#1": 11, "#2": 22, "#3": 33, "#4": 44}).AS("result.raw_arg2"),
|
||||
|
||||
AllTypes.SmallIntPtr.NOT_IN(Int(11), Int(22), NULL).AS("result.not_in"),
|
||||
AllTypes.SmallIntPtr.NOT_IN(AllTypes.SELECT(AllTypes.Integer)).AS("result.not_in_select"),
|
||||
).LIMIT(2)
|
||||
|
||||
//fmt.Println(query.Sql())
|
||||
|
||||
testutils.AssertStatementSql(t, query, `
|
||||
SELECT all_types.integer IS NULL AS "result.is_null",
|
||||
all_types.date_ptr IS NOT NULL AS "result.is_not_null",
|
||||
|
|
@ -235,14 +250,17 @@ SELECT all_types.integer IS NULL AS "result.is_null",
|
|||
SELECT all_types.integer AS "all_types.integer"
|
||||
FROM test_sample.all_types
|
||||
))) AS "result.in_select",
|
||||
(all_types.small_int_ptr NOT IN ($3, $4, NULL)) AS "result.not_in",
|
||||
(CURRENT_USER) AS "result.raw",
|
||||
($3 + COALESCE(all_types.small_int_ptr, 0) + $4) AS "result.raw_arg",
|
||||
($5 + all_types.integer + $6 + $5 + $7 + $8) AS "result.raw_arg2",
|
||||
(all_types.small_int_ptr NOT IN ($9, $10, NULL)) AS "result.not_in",
|
||||
(all_types.small_int_ptr NOT IN ((
|
||||
SELECT all_types.integer AS "all_types.integer"
|
||||
FROM test_sample.all_types
|
||||
))) AS "result.not_in_select"
|
||||
FROM test_sample.all_types
|
||||
LIMIT $5;
|
||||
`, int64(11), int64(22), int64(11), int64(22), int64(2))
|
||||
LIMIT $11;
|
||||
`, int64(11), int64(22), 78, 56, 11, 22, 33, 44, int64(11), int64(22), int64(2))
|
||||
|
||||
var dest []struct {
|
||||
common.ExpressionTestResult `alias:"result.*"`
|
||||
|
|
@ -261,6 +279,9 @@ LIMIT $5;
|
|||
"IsNotNull": true,
|
||||
"In": false,
|
||||
"InSelect": false,
|
||||
"Raw": "jet",
|
||||
"RawArg": 148,
|
||||
"RawArg2": 421,
|
||||
"NotIn": null,
|
||||
"NotInSelect": true
|
||||
},
|
||||
|
|
@ -269,6 +290,9 @@ LIMIT $5;
|
|||
"IsNotNull": false,
|
||||
"In": null,
|
||||
"InSelect": null,
|
||||
"Raw": "jet",
|
||||
"RawArg": 134,
|
||||
"RawArg2": 421,
|
||||
"NotIn": null,
|
||||
"NotInSelect": null
|
||||
}
|
||||
|
|
@ -278,6 +302,8 @@ LIMIT $5;
|
|||
|
||||
func TestExpressionCast(t *testing.T) {
|
||||
|
||||
skipForPgxDriver(t) // for some reason, pgx driver, 150:char(12) returns as int value
|
||||
|
||||
query := AllTypes.SELECT(
|
||||
CAST(Int(150)).AS_CHAR(12).AS("char12"),
|
||||
CAST(String("TRUE")).AS_BOOL(),
|
||||
|
|
@ -323,6 +349,8 @@ func TestExpressionCast(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestStringOperators(t *testing.T) {
|
||||
skipForPgxDriver(t) // pgx driver returns text column as int value
|
||||
|
||||
query := AllTypes.SELECT(
|
||||
AllTypes.Text.EQ(AllTypes.Char),
|
||||
AllTypes.Text.EQ(String("Text")),
|
||||
|
|
@ -838,6 +866,7 @@ func TestInterval(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestSubQueryColumnReference(t *testing.T) {
|
||||
skipForPgxDriver(t) // pgx driver returns time with time zone as string value
|
||||
|
||||
type expected struct {
|
||||
sql string
|
||||
|
|
@ -1015,6 +1044,7 @@ FROM`
|
|||
}
|
||||
|
||||
func TestTimeLiterals(t *testing.T) {
|
||||
skipForPgxDriver(t) // pgx driver returns time with time zone as string
|
||||
|
||||
loc, err := time.LoadLocation("Europe/Berlin")
|
||||
require.NoError(t, err)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package postgres
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/go-jet/jet/v2/internal/testutils"
|
||||
. "github.com/go-jet/jet/v2/postgres"
|
||||
"github.com/go-jet/jet/v2/tests/.gentestdata/jetdb/chinook/model"
|
||||
|
|
@ -17,7 +16,7 @@ func TestSelect(t *testing.T) {
|
|||
SELECT(Album.AllColumns).
|
||||
ORDER_BY(Album.AlbumId.ASC())
|
||||
|
||||
fmt.Println(stmt.DebugSql())
|
||||
//fmt.Println(stmt.DebugSql())
|
||||
|
||||
testutils.AssertDebugStatementSql(t, stmt, `
|
||||
SELECT "Album"."AlbumId" AS "Album.AlbumId",
|
||||
|
|
@ -330,8 +329,71 @@ ORDER BY "first10Artist"."Artist.ArtistId";
|
|||
err := stmt.Query(db, &dest)
|
||||
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
//spew.Dump(dest)
|
||||
func Test_SchemaRename(t *testing.T) {
|
||||
|
||||
Artist2 := Artist.FromSchema("chinook2")
|
||||
Album2 := Album.FromSchema("chinook2")
|
||||
|
||||
first10Artist := Artist2.
|
||||
SELECT(Artist2.AllColumns).
|
||||
ORDER_BY(Artist2.ArtistId).
|
||||
LIMIT(10).
|
||||
AsTable("first10Artist")
|
||||
|
||||
artistID := Artist2.ArtistId.From(first10Artist)
|
||||
|
||||
first10Albums := Album2.
|
||||
SELECT(Album2.AllColumns).
|
||||
ORDER_BY(Album2.AlbumId).
|
||||
LIMIT(10).
|
||||
AsTable("first10Albums")
|
||||
|
||||
albumArtistID := Album2.ArtistId.From(first10Albums)
|
||||
|
||||
stmt := SELECT(first10Artist.AllColumns(), first10Albums.AllColumns()).
|
||||
FROM(first10Artist.
|
||||
INNER_JOIN(first10Albums, artistID.EQ(albumArtistID))).
|
||||
ORDER_BY(artistID)
|
||||
|
||||
testutils.AssertDebugStatementSql(t, stmt, `
|
||||
SELECT "first10Artist"."Artist.ArtistId" AS "Artist.ArtistId",
|
||||
"first10Artist"."Artist.Name" AS "Artist.Name",
|
||||
"first10Albums"."Album.AlbumId" AS "Album.AlbumId",
|
||||
"first10Albums"."Album.Title" AS "Album.Title",
|
||||
"first10Albums"."Album.ArtistId" AS "Album.ArtistId"
|
||||
FROM (
|
||||
SELECT "Artist"."ArtistId" AS "Artist.ArtistId",
|
||||
"Artist"."Name" AS "Artist.Name"
|
||||
FROM chinook2."Artist"
|
||||
ORDER BY "Artist"."ArtistId"
|
||||
LIMIT 10
|
||||
) AS "first10Artist"
|
||||
INNER JOIN (
|
||||
SELECT "Album"."AlbumId" AS "Album.AlbumId",
|
||||
"Album"."Title" AS "Album.Title",
|
||||
"Album"."ArtistId" AS "Album.ArtistId"
|
||||
FROM chinook2."Album"
|
||||
ORDER BY "Album"."AlbumId"
|
||||
LIMIT 10
|
||||
) AS "first10Albums" ON ("first10Artist"."Artist.ArtistId" = "first10Albums"."Album.ArtistId")
|
||||
ORDER BY "first10Artist"."Artist.ArtistId";
|
||||
`)
|
||||
|
||||
var dest []struct {
|
||||
model.Artist
|
||||
|
||||
Album []model.Album
|
||||
}
|
||||
|
||||
err := stmt.Query(db, &dest)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Len(t, dest, 2)
|
||||
require.Equal(t, *dest[0].Artist.Name, "Apocalyptica")
|
||||
require.Len(t, dest[0].Album, 1)
|
||||
require.Equal(t, dest[0].Album[0].Title, "Plays Metallica By Four Cellos")
|
||||
}
|
||||
|
||||
var album1 = model.Album{
|
||||
|
|
|
|||
|
|
@ -46,12 +46,7 @@ func TestGeneratedModel(t *testing.T) {
|
|||
const genTestDir2 = "./.gentestdata2"
|
||||
|
||||
func TestCmdGenerator(t *testing.T) {
|
||||
goInstallJet := exec.Command("sh", "-c", "cd $GOPATH/src/ && GO111MODULE=off go get github.com/go-jet/jet/cmd/jet")
|
||||
goInstallJet.Stderr = os.Stderr
|
||||
err := goInstallJet.Run()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = os.RemoveAll(genTestDir2)
|
||||
err := os.RemoveAll(genTestDir2)
|
||||
require.NoError(t, err)
|
||||
|
||||
cmd := exec.Command("jet", "-source=PostgreSQL", "-dbname=jetdb", "-host=localhost", "-port=5432",
|
||||
|
|
@ -173,7 +168,7 @@ import (
|
|||
"github.com/go-jet/jet/v2/postgres"
|
||||
)
|
||||
|
||||
var Actor = newActorTable()
|
||||
var Actor = newActorTable("dvds", "actor", "")
|
||||
|
||||
type actorTable struct {
|
||||
postgres.Table
|
||||
|
|
@ -195,20 +190,23 @@ type ActorTable struct {
|
|||
}
|
||||
|
||||
// AS creates new ActorTable with assigned alias
|
||||
func (a *ActorTable) AS(alias string) *ActorTable {
|
||||
aliasTable := newActorTable()
|
||||
aliasTable.Table.AS(alias)
|
||||
return aliasTable
|
||||
func (a ActorTable) AS(alias string) *ActorTable {
|
||||
return newActorTable(a.SchemaName(), a.TableName(), alias)
|
||||
}
|
||||
|
||||
func newActorTable() *ActorTable {
|
||||
// Schema creates new ActorTable with assigned schema name
|
||||
func (a ActorTable) FromSchema(schemaName string) *ActorTable {
|
||||
return newActorTable(schemaName, a.TableName(), a.Alias())
|
||||
}
|
||||
|
||||
func newActorTable(schemaName, tableName, alias string) *ActorTable {
|
||||
return &ActorTable{
|
||||
actorTable: newActorTableImpl("dvds", "actor"),
|
||||
EXCLUDED: newActorTableImpl("", "excluded"),
|
||||
actorTable: newActorTableImpl(schemaName, tableName, alias),
|
||||
EXCLUDED: newActorTableImpl("", "excluded", ""),
|
||||
}
|
||||
}
|
||||
|
||||
func newActorTableImpl(schemaName, tableName string) actorTable {
|
||||
func newActorTableImpl(schemaName, tableName, alias string) actorTable {
|
||||
var (
|
||||
ActorIDColumn = postgres.IntegerColumn("actor_id")
|
||||
FirstNameColumn = postgres.StringColumn("first_name")
|
||||
|
|
@ -219,7 +217,7 @@ func newActorTableImpl(schemaName, tableName string) actorTable {
|
|||
)
|
||||
|
||||
return actorTable{
|
||||
Table: postgres.NewTable(schemaName, tableName, allColumns...),
|
||||
Table: postgres.NewTable(schemaName, tableName, alias, allColumns...),
|
||||
|
||||
//Columns
|
||||
ActorID: ActorIDColumn,
|
||||
|
|
@ -269,7 +267,7 @@ import (
|
|||
"github.com/go-jet/jet/v2/postgres"
|
||||
)
|
||||
|
||||
var ActorInfo = newActorInfoTable()
|
||||
var ActorInfo = newActorInfoTable("dvds", "actor_info", "")
|
||||
|
||||
type actorInfoTable struct {
|
||||
postgres.Table
|
||||
|
|
@ -291,20 +289,23 @@ type ActorInfoTable struct {
|
|||
}
|
||||
|
||||
// AS creates new ActorInfoTable with assigned alias
|
||||
func (a *ActorInfoTable) AS(alias string) *ActorInfoTable {
|
||||
aliasTable := newActorInfoTable()
|
||||
aliasTable.Table.AS(alias)
|
||||
return aliasTable
|
||||
func (a ActorInfoTable) AS(alias string) *ActorInfoTable {
|
||||
return newActorInfoTable(a.SchemaName(), a.TableName(), alias)
|
||||
}
|
||||
|
||||
func newActorInfoTable() *ActorInfoTable {
|
||||
// Schema creates new ActorInfoTable with assigned schema name
|
||||
func (a ActorInfoTable) FromSchema(schemaName string) *ActorInfoTable {
|
||||
return newActorInfoTable(schemaName, a.TableName(), a.Alias())
|
||||
}
|
||||
|
||||
func newActorInfoTable(schemaName, tableName, alias string) *ActorInfoTable {
|
||||
return &ActorInfoTable{
|
||||
actorInfoTable: newActorInfoTableImpl("dvds", "actor_info"),
|
||||
EXCLUDED: newActorInfoTableImpl("", "excluded"),
|
||||
actorInfoTable: newActorInfoTableImpl(schemaName, tableName, alias),
|
||||
EXCLUDED: newActorInfoTableImpl("", "excluded", ""),
|
||||
}
|
||||
}
|
||||
|
||||
func newActorInfoTableImpl(schemaName, tableName string) actorInfoTable {
|
||||
func newActorInfoTableImpl(schemaName, tableName, alias string) actorInfoTable {
|
||||
var (
|
||||
ActorIDColumn = postgres.IntegerColumn("actor_id")
|
||||
FirstNameColumn = postgres.StringColumn("first_name")
|
||||
|
|
@ -315,7 +316,7 @@ func newActorInfoTableImpl(schemaName, tableName string) actorInfoTable {
|
|||
)
|
||||
|
||||
return actorInfoTable{
|
||||
Table: postgres.NewTable(schemaName, tableName, allColumns...),
|
||||
Table: postgres.NewTable(schemaName, tableName, alias, allColumns...),
|
||||
|
||||
//Columns
|
||||
ActorID: ActorIDColumn,
|
||||
|
|
@ -345,7 +346,7 @@ func TestGeneratedAllTypesSQLBuilderFiles(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
testutils.AssertFileNamesEqual(t, modelFiles, "all_types.go", "all_types_view.go", "employee.go", "link.go",
|
||||
"mood.go", "person.go", "person_phone.go", "weird_names_table.go", "level.go", "user.go")
|
||||
"mood.go", "person.go", "person_phone.go", "weird_names_table.go", "level.go", "user.go", "floats.go")
|
||||
|
||||
testutils.AssertFileContent(t, modelDir+"all_types.go", allTypesModelContent)
|
||||
|
||||
|
|
@ -353,7 +354,7 @@ func TestGeneratedAllTypesSQLBuilderFiles(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
testutils.AssertFileNamesEqual(t, tableFiles, "all_types.go", "employee.go", "link.go",
|
||||
"person.go", "person_phone.go", "weird_names_table.go", "user.go")
|
||||
"person.go", "person_phone.go", "weird_names_table.go", "user.go", "floats.go")
|
||||
|
||||
testutils.AssertFileContent(t, tableDir+"all_types.go", allTypesTableContent)
|
||||
}
|
||||
|
|
@ -502,7 +503,7 @@ import (
|
|||
"github.com/go-jet/jet/v2/postgres"
|
||||
)
|
||||
|
||||
var AllTypes = newAllTypesTable()
|
||||
var AllTypes = newAllTypesTable("test_sample", "all_types", "")
|
||||
|
||||
type allTypesTable struct {
|
||||
postgres.Table
|
||||
|
|
@ -581,20 +582,23 @@ type AllTypesTable struct {
|
|||
}
|
||||
|
||||
// AS creates new AllTypesTable with assigned alias
|
||||
func (a *AllTypesTable) AS(alias string) *AllTypesTable {
|
||||
aliasTable := newAllTypesTable()
|
||||
aliasTable.Table.AS(alias)
|
||||
return aliasTable
|
||||
func (a AllTypesTable) AS(alias string) *AllTypesTable {
|
||||
return newAllTypesTable(a.SchemaName(), a.TableName(), alias)
|
||||
}
|
||||
|
||||
func newAllTypesTable() *AllTypesTable {
|
||||
// Schema creates new AllTypesTable with assigned schema name
|
||||
func (a AllTypesTable) FromSchema(schemaName string) *AllTypesTable {
|
||||
return newAllTypesTable(schemaName, a.TableName(), a.Alias())
|
||||
}
|
||||
|
||||
func newAllTypesTable(schemaName, tableName, alias string) *AllTypesTable {
|
||||
return &AllTypesTable{
|
||||
allTypesTable: newAllTypesTableImpl("test_sample", "all_types"),
|
||||
EXCLUDED: newAllTypesTableImpl("", "excluded"),
|
||||
allTypesTable: newAllTypesTableImpl(schemaName, tableName, alias),
|
||||
EXCLUDED: newAllTypesTableImpl("", "excluded", ""),
|
||||
}
|
||||
}
|
||||
|
||||
func newAllTypesTableImpl(schemaName, tableName string) allTypesTable {
|
||||
func newAllTypesTableImpl(schemaName, tableName, alias string) allTypesTable {
|
||||
var (
|
||||
SmallIntPtrColumn = postgres.IntegerColumn("small_int_ptr")
|
||||
SmallIntColumn = postgres.IntegerColumn("small_int")
|
||||
|
|
@ -662,7 +666,7 @@ func newAllTypesTableImpl(schemaName, tableName string) allTypesTable {
|
|||
)
|
||||
|
||||
return allTypesTable{
|
||||
Table: postgres.NewTable(schemaName, tableName, allColumns...),
|
||||
Table: postgres.NewTable(schemaName, tableName, alias, allColumns...),
|
||||
|
||||
//Columns
|
||||
SmallIntPtr: SmallIntPtrColumn,
|
||||
|
|
|
|||
|
|
@ -3,17 +3,23 @@ package postgres
|
|||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"github.com/go-jet/jet/v2/postgres"
|
||||
"github.com/go-jet/jet/v2/tests/dbconfig"
|
||||
_ "github.com/lib/pq"
|
||||
"github.com/pkg/profile"
|
||||
"github.com/stretchr/testify/require"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v4/stdlib"
|
||||
|
||||
"github.com/go-jet/jet/v2/postgres"
|
||||
"github.com/go-jet/jet/v2/tests/dbconfig"
|
||||
_ "github.com/lib/pq"
|
||||
"github.com/pkg/profile"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
_ "github.com/jackc/pgx/v4/stdlib"
|
||||
)
|
||||
|
||||
var db *sql.DB
|
||||
|
|
@ -25,16 +31,23 @@ func TestMain(m *testing.M) {
|
|||
|
||||
setTestRoot()
|
||||
|
||||
var err error
|
||||
db, err = sql.Open("postgres", dbconfig.PostgresConnectString)
|
||||
if err != nil {
|
||||
panic("Failed to connect to test db")
|
||||
for _, driverName := range []string{"postgres", "pgx"} {
|
||||
func() {
|
||||
var err error
|
||||
db, err = sql.Open(driverName, dbconfig.PostgresConnectString)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
panic("Failed to connect to test db")
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
ret := m.Run()
|
||||
|
||||
if ret != 0 {
|
||||
os.Exit(ret)
|
||||
}
|
||||
}()
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
ret := m.Run()
|
||||
|
||||
os.Exit(ret)
|
||||
}
|
||||
|
||||
func setTestRoot() {
|
||||
|
|
@ -64,3 +77,10 @@ func requireLogged(t *testing.T, statement postgres.Statement) {
|
|||
require.Equal(t, loggedSQLArgs, args)
|
||||
require.Equal(t, loggedDebugSQL, statement.DebugSql())
|
||||
}
|
||||
|
||||
func skipForPgxDriver(t *testing.T) {
|
||||
switch db.Driver().(type) {
|
||||
case *stdlib.Driver:
|
||||
t.SkipNow()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
179
tests/postgres/raw_statements_test.go
Normal file
179
tests/postgres/raw_statements_test.go
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/go-jet/jet/v2/internal/testutils"
|
||||
"github.com/go-jet/jet/v2/tests/.gentestdata/jetdb/dvds/model"
|
||||
model2 "github.com/go-jet/jet/v2/tests/.gentestdata/mysql/test_sample/model"
|
||||
|
||||
. "github.com/go-jet/jet/v2/postgres"
|
||||
)
|
||||
|
||||
func TestRawStatementSelect(t *testing.T) {
|
||||
stmt := RawStatement(`
|
||||
SELECT actor.first_name AS "actor.first_name"
|
||||
FROM dvds.actor
|
||||
WHERE actor.actor_id = 2`)
|
||||
|
||||
testutils.AssertStatementSql(t, stmt, `
|
||||
SELECT actor.first_name AS "actor.first_name"
|
||||
FROM dvds.actor
|
||||
WHERE actor.actor_id = 2;
|
||||
`)
|
||||
testutils.AssertDebugStatementSql(t, stmt, `
|
||||
SELECT actor.first_name AS "actor.first_name"
|
||||
FROM dvds.actor
|
||||
WHERE actor.actor_id = 2;
|
||||
`)
|
||||
var actor model.Actor
|
||||
err := stmt.Query(db, &actor)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, actor.FirstName, "Nick")
|
||||
}
|
||||
|
||||
func TestRawStatementSelectWithArguments(t *testing.T) {
|
||||
stmt := RawStatement(`
|
||||
SELECT DISTINCT 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"
|
||||
FROM dvds.actor
|
||||
WHERE actor.actor_id IN (#actorID1, #actorID2, #actorID3) AND ((#actorID1 / #actorID2) <> (#actorID2 * #actorID3))
|
||||
ORDER BY actor.actor_id`,
|
||||
RawArgs{
|
||||
"#actorID1": int64(1),
|
||||
"#actorID2": int64(2),
|
||||
"#actorID3": int64(3),
|
||||
},
|
||||
)
|
||||
|
||||
testutils.AssertStatementSql(t, stmt, `
|
||||
SELECT DISTINCT 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"
|
||||
FROM dvds.actor
|
||||
WHERE actor.actor_id IN ($1, $2, $3) AND (($1 / $2) <> ($2 * $3))
|
||||
ORDER BY actor.actor_id;
|
||||
`, int64(1), int64(2), int64(3))
|
||||
|
||||
testutils.AssertDebugStatementSql(t, stmt, `
|
||||
SELECT DISTINCT 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"
|
||||
FROM dvds.actor
|
||||
WHERE actor.actor_id IN (1, 2, 3) AND ((1 / 2) <> (2 * 3))
|
||||
ORDER BY actor.actor_id;
|
||||
`)
|
||||
|
||||
var actor []model.Actor
|
||||
err := stmt.Query(db, &actor)
|
||||
require.NoError(t, err)
|
||||
|
||||
testutils.AssertDeepEqual(t, actor[1], model.Actor{
|
||||
ActorID: 2,
|
||||
FirstName: "Nick",
|
||||
LastName: "Wahlberg",
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2013-05-26 14:47:57.62", 2),
|
||||
})
|
||||
}
|
||||
|
||||
func TestRawInsert(t *testing.T) {
|
||||
cleanUpLinkTable(t)
|
||||
|
||||
stmt := RawStatement(`
|
||||
INSERT INTO test_sample.link (id, url, name, description)
|
||||
VALUES (@id1, @url1, @name1, DEFAULT),
|
||||
(200, @url1, @name1, NULL),
|
||||
(@id2, @url2, @name2, DEFAULT),
|
||||
(@id3, @url3, @name3, NULL)
|
||||
RETURNING link.id AS "link.id",
|
||||
link.url AS "link.url",
|
||||
link.name AS "link.name",
|
||||
link.description AS "link.description"`,
|
||||
RawArgs{
|
||||
"@id1": 100, "@url1": "http://www.postgresqltutorial.com", "@name1": "PostgreSQL Tutorial",
|
||||
"@id2": 101, "@url2": "http://www.google.com", "@name2": "Google",
|
||||
"@id3": 102, "@url3": "http://www.yahoo.com", "@name3": "Yahoo",
|
||||
})
|
||||
|
||||
testutils.AssertStatementSql(t, stmt, `
|
||||
INSERT INTO test_sample.link (id, url, name, description)
|
||||
VALUES ($1, $2, $3, DEFAULT),
|
||||
(200, $2, $3, NULL),
|
||||
($4, $5, $6, DEFAULT),
|
||||
($7, $8, $9, NULL)
|
||||
RETURNING link.id AS "link.id",
|
||||
link.url AS "link.url",
|
||||
link.name AS "link.name",
|
||||
link.description AS "link.description";
|
||||
`, 100, "http://www.postgresqltutorial.com", "PostgreSQL Tutorial",
|
||||
101, "http://www.google.com", "Google",
|
||||
102, "http://www.yahoo.com", "Yahoo")
|
||||
|
||||
testutils.AssertDebugStatementSql(t, stmt, `
|
||||
INSERT INTO test_sample.link (id, url, name, description)
|
||||
VALUES (100, 'http://www.postgresqltutorial.com', 'PostgreSQL Tutorial', DEFAULT),
|
||||
(200, 'http://www.postgresqltutorial.com', 'PostgreSQL Tutorial', NULL),
|
||||
(101, 'http://www.google.com', 'Google', DEFAULT),
|
||||
(102, 'http://www.yahoo.com', 'Yahoo', NULL)
|
||||
RETURNING link.id AS "link.id",
|
||||
link.url AS "link.url",
|
||||
link.name AS "link.name",
|
||||
link.description AS "link.description";
|
||||
`)
|
||||
|
||||
var links []model2.Link
|
||||
err := stmt.Query(db, &links)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, links, 4)
|
||||
require.Equal(t, links[0].ID, int32(100))
|
||||
require.Equal(t, links[1].URL, "http://www.postgresqltutorial.com")
|
||||
require.Equal(t, links[2].Name, "Google")
|
||||
require.Nil(t, links[2].Description)
|
||||
}
|
||||
|
||||
func TestRawStatementRows(t *testing.T) {
|
||||
stmt := RawStatement(`
|
||||
SELECT 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"
|
||||
FROM dvds.actor
|
||||
ORDER BY actor.actor_id`)
|
||||
|
||||
rows, err := stmt.Rows(context.Background(), db)
|
||||
require.NoError(t, err)
|
||||
|
||||
for rows.Next() {
|
||||
var actor model.Actor
|
||||
err := rows.Scan(&actor)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NotEqual(t, actor.ActorID, int32(0))
|
||||
require.NotEqual(t, actor.FirstName, "")
|
||||
require.NotEqual(t, actor.LastName, "")
|
||||
require.NotEqual(t, actor.LastUpdate, time.Time{})
|
||||
|
||||
if actor.ActorID == 54 {
|
||||
require.Equal(t, actor.ActorID, int32(54))
|
||||
require.Equal(t, actor.FirstName, "Penelope")
|
||||
require.Equal(t, actor.LastName, "Pinkett")
|
||||
require.Equal(t, actor.LastUpdate.Format(time.RFC3339), "2013-05-26T14:47:57Z")
|
||||
}
|
||||
}
|
||||
|
||||
err = rows.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = rows.Err()
|
||||
require.NoError(t, err)
|
||||
|
||||
requireLogged(t, stmt)
|
||||
}
|
||||
|
|
@ -1,19 +1,26 @@
|
|||
package postgres
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/go-jet/jet/v2/internal/testutils"
|
||||
. "github.com/go-jet/jet/v2/postgres"
|
||||
"github.com/go-jet/jet/v2/tests/.gentestdata/jetdb/test_sample/model"
|
||||
. "github.com/go-jet/jet/v2/tests/.gentestdata/jetdb/test_sample/table"
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
func TestUUIDType(t *testing.T) {
|
||||
|
||||
id := uuid.MustParse("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11")
|
||||
|
||||
query := AllTypes.
|
||||
SELECT(AllTypes.UUID, AllTypes.UUIDPtr).
|
||||
WHERE(AllTypes.UUID.EQ(String("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11")))
|
||||
WHERE(AllTypes.UUID.EQ(UUID(id)))
|
||||
|
||||
testutils.AssertDebugStatementSql(t, query, `
|
||||
SELECT all_types.uuid AS "all_types.uuid",
|
||||
|
|
@ -31,6 +38,110 @@ WHERE all_types.uuid = 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11';
|
|||
requireLogged(t, query)
|
||||
}
|
||||
|
||||
func TestExactDecimals(t *testing.T) {
|
||||
|
||||
type floats struct {
|
||||
model.Floats
|
||||
Numeric decimal.Decimal
|
||||
NumericPtr decimal.Decimal
|
||||
Decimal decimal.Decimal
|
||||
DecimalPtr decimal.Decimal
|
||||
}
|
||||
|
||||
t.Run("should query decimal", func(t *testing.T) {
|
||||
query := SELECT(
|
||||
Floats.AllColumns,
|
||||
).FROM(
|
||||
Floats,
|
||||
).WHERE(Floats.Decimal.EQ(Decimal("1.11111111111111111111")))
|
||||
|
||||
var result floats
|
||||
|
||||
err := query.Query(db, &result)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, "1.11111111111111111111", result.Decimal.String())
|
||||
require.Equal(t, "0", result.DecimalPtr.String()) // NULL
|
||||
require.Equal(t, "2.22222222222222222222", result.Numeric.String())
|
||||
require.Equal(t, "0", result.NumericPtr.String()) // NULL
|
||||
|
||||
require.Equal(t, 1.1111111111111112, result.Floats.Decimal) // precision loss
|
||||
require.Equal(t, (*float64)(nil), result.Floats.DecimalPtr)
|
||||
require.Equal(t, 2.2222222222222223, result.Floats.Numeric) // precision loss
|
||||
require.Equal(t, (*float64)(nil), result.Floats.NumericPtr)
|
||||
|
||||
// floating point
|
||||
require.Equal(t, float32(3.3333333), result.Floats.Real) // precision loss
|
||||
require.Equal(t, (*float32)(nil), result.Floats.RealPtr)
|
||||
require.Equal(t, 4.444444444444445, result.Floats.Double) // precision loss
|
||||
require.Equal(t, (*float64)(nil), result.Floats.DoublePtr)
|
||||
})
|
||||
|
||||
t.Run("should insert decimal", func(t *testing.T) {
|
||||
|
||||
insertQuery := Floats.INSERT(
|
||||
Floats.AllColumns,
|
||||
).MODEL(
|
||||
floats{
|
||||
Floats: model.Floats{
|
||||
// overwritten by wrapped(floats) scope
|
||||
Numeric: 0.1,
|
||||
NumericPtr: testutils.Float64Ptr(0.1),
|
||||
Decimal: 0.1,
|
||||
DecimalPtr: testutils.Float64Ptr(0.1),
|
||||
|
||||
// not overwritten
|
||||
Real: 0.4,
|
||||
RealPtr: testutils.Float32Ptr(0.44),
|
||||
Double: 0.3,
|
||||
DoublePtr: testutils.Float64Ptr(0.33),
|
||||
},
|
||||
Numeric: decimal.RequireFromString("0.1234567890123456789"),
|
||||
NumericPtr: decimal.RequireFromString("1.1111111111111111111"),
|
||||
Decimal: decimal.RequireFromString("2.2222222222222222222"),
|
||||
DecimalPtr: decimal.RequireFromString("3.3333333333333333333"),
|
||||
},
|
||||
).RETURNING(
|
||||
Floats.AllColumns,
|
||||
)
|
||||
|
||||
testutils.AssertDebugStatementSql(t, insertQuery, `
|
||||
INSERT INTO test_sample.floats (decimal_ptr, decimal, numeric_ptr, numeric, real_ptr, real, double_ptr, double)
|
||||
VALUES ('3.3333333333333333333', '2.2222222222222222222', '1.1111111111111111111', '0.1234567890123456789', 0.4399999976158142, 0.4000000059604645, 0.33, 0.3)
|
||||
RETURNING floats.decimal_ptr AS "floats.decimal_ptr",
|
||||
floats.decimal AS "floats.decimal",
|
||||
floats.numeric_ptr AS "floats.numeric_ptr",
|
||||
floats.numeric AS "floats.numeric",
|
||||
floats.real_ptr AS "floats.real_ptr",
|
||||
floats.real AS "floats.real",
|
||||
floats.double_ptr AS "floats.double_ptr",
|
||||
floats.double AS "floats.double";
|
||||
`)
|
||||
|
||||
var result floats
|
||||
err := insertQuery.Query(db, &result)
|
||||
require.NoError(t, err)
|
||||
|
||||
// exact decimal
|
||||
require.Equal(t, "0.1234567890123456789", result.Numeric.String())
|
||||
require.Equal(t, "1.1111111111111111111", result.NumericPtr.String())
|
||||
require.Equal(t, "2.2222222222222222222", result.Decimal.String())
|
||||
require.Equal(t, "3.3333333333333333333", result.DecimalPtr.String())
|
||||
|
||||
// precision loss
|
||||
require.Equal(t, 0.12345678901234568, result.Floats.Numeric)
|
||||
require.Equal(t, 1.1111111111111112, *result.Floats.NumericPtr)
|
||||
require.Equal(t, 2.2222222222222223, result.Floats.Decimal)
|
||||
require.Equal(t, 3.3333333333333335, *result.Floats.DecimalPtr)
|
||||
|
||||
// floating points numbers
|
||||
require.Equal(t, float32(0.4), result.Floats.Real)
|
||||
require.Equal(t, float32(0.44), *result.Floats.RealPtr)
|
||||
require.Equal(t, 0.3, result.Floats.Double)
|
||||
require.Equal(t, 0.33, *result.Floats.DoublePtr)
|
||||
})
|
||||
}
|
||||
|
||||
func TestUUIDComplex(t *testing.T) {
|
||||
query := Person.INNER_JOIN(PersonPhone, PersonPhone.PersonID.EQ(Person.PersonID)).
|
||||
SELECT(Person.AllColumns, PersonPhone.AllColumns).
|
||||
|
|
@ -364,7 +475,7 @@ FROM test_sample."User";
|
|||
err := stmt.Query(db, &dest)
|
||||
require.NoError(t, err)
|
||||
|
||||
testutils.PrintJson(dest)
|
||||
//testutils.PrintJson(dest)
|
||||
|
||||
testutils.AssertJSON(t, dest, `
|
||||
[
|
||||
|
|
@ -386,3 +497,54 @@ FROM test_sample."User";
|
|||
]
|
||||
`)
|
||||
}
|
||||
|
||||
func TestBytea(t *testing.T) {
|
||||
byteArrHex := "\\x48656c6c6f20476f7068657221"
|
||||
byteArrBin := []byte("\x48\x65\x6c\x6c\x6f\x20\x47\x6f\x70\x68\x65\x72\x21")
|
||||
|
||||
insertStmt := AllTypes.INSERT(AllTypes.Bytea, AllTypes.ByteaPtr).
|
||||
VALUES(byteArrHex, byteArrBin).
|
||||
RETURNING(AllTypes.Bytea, AllTypes.ByteaPtr)
|
||||
|
||||
testutils.AssertStatementSql(t, insertStmt, `
|
||||
INSERT INTO test_sample.all_types (bytea, bytea_ptr)
|
||||
VALUES ($1, $2)
|
||||
RETURNING all_types.bytea AS "all_types.bytea",
|
||||
all_types.bytea_ptr AS "all_types.bytea_ptr";
|
||||
`, byteArrHex, byteArrBin)
|
||||
|
||||
var inserted model.AllTypes
|
||||
err := insertStmt.Query(db, &inserted)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, string(*inserted.ByteaPtr), "Hello Gopher!")
|
||||
// It is not possible to initiate bytea column using hex format '\xDEADBEEF' with pq driver.
|
||||
// pq driver always encodes parameter string if destination column is of type bytea.
|
||||
// Probably pq driver error.
|
||||
// require.Equal(t, string(inserted.Bytea), "Hello Gopher!")
|
||||
|
||||
stmt := SELECT(
|
||||
AllTypes.Bytea,
|
||||
AllTypes.ByteaPtr,
|
||||
).FROM(
|
||||
AllTypes,
|
||||
).WHERE(
|
||||
AllTypes.ByteaPtr.EQ(Bytea(byteArrBin)),
|
||||
)
|
||||
|
||||
testutils.AssertStatementSql(t, stmt, `
|
||||
SELECT all_types.bytea AS "all_types.bytea",
|
||||
all_types.bytea_ptr AS "all_types.bytea_ptr"
|
||||
FROM test_sample.all_types
|
||||
WHERE all_types.bytea_ptr = $1::bytea;
|
||||
`, byteArrBin)
|
||||
|
||||
var dest model.AllTypes
|
||||
|
||||
err = stmt.Query(db, &dest)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, string(*dest.ByteaPtr), "Hello Gopher!")
|
||||
// Probably pq driver error.
|
||||
// require.Equal(t, string(dest.Bytea), "Hello Gopher!")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,18 @@
|
|||
package postgres
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/go-jet/jet/v2/internal/testutils"
|
||||
. "github.com/go-jet/jet/v2/postgres"
|
||||
"github.com/go-jet/jet/v2/qrm"
|
||||
"github.com/go-jet/jet/v2/tests/.gentestdata/jetdb/dvds/model"
|
||||
. "github.com/go-jet/jet/v2/tests/.gentestdata/jetdb/dvds/table"
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var oneInventoryQuery = Inventory.
|
||||
|
|
@ -93,7 +96,7 @@ func TestScanToStruct(t *testing.T) {
|
|||
SELECT(Inventory.AllColumns).
|
||||
ORDER_BY(Inventory.InventoryID)
|
||||
|
||||
fmt.Println(query.DebugSql())
|
||||
//fmt.Println(query.DebugSql())
|
||||
|
||||
t.Run("one struct", func(t *testing.T) {
|
||||
dest := model.Inventory{}
|
||||
|
|
@ -723,6 +726,89 @@ func TestStructScanAllNull(t *testing.T) {
|
|||
}{})
|
||||
}
|
||||
|
||||
func TestRowsScan(t *testing.T) {
|
||||
|
||||
stmt := SELECT(
|
||||
Inventory.AllColumns,
|
||||
).FROM(
|
||||
Inventory,
|
||||
).ORDER_BY(
|
||||
Inventory.InventoryID.ASC(),
|
||||
)
|
||||
|
||||
rows, err := stmt.Rows(context.Background(), db)
|
||||
require.NoError(t, err)
|
||||
|
||||
for rows.Next() {
|
||||
var inventory model.Inventory
|
||||
err = rows.Scan(&inventory)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NotEqual(t, inventory.InventoryID, int32(0))
|
||||
require.NotEqual(t, inventory.FilmID, int16(0))
|
||||
require.NotEqual(t, inventory.StoreID, int16(0))
|
||||
require.NotEqual(t, inventory.LastUpdate, time.Time{})
|
||||
|
||||
if inventory.InventoryID == 2103 {
|
||||
require.Equal(t, inventory.FilmID, int16(456))
|
||||
require.Equal(t, inventory.StoreID, int16(2))
|
||||
require.Equal(t, inventory.LastUpdate.Format(time.RFC3339), "2006-02-15T10:09:17Z")
|
||||
}
|
||||
}
|
||||
|
||||
err = rows.Close()
|
||||
require.NoError(t, err)
|
||||
err = rows.Err()
|
||||
require.NoError(t, err)
|
||||
|
||||
requireLogged(t, stmt)
|
||||
}
|
||||
|
||||
func TestScanNumericToNumber(t *testing.T) {
|
||||
type Number struct {
|
||||
Int8 int8
|
||||
UInt8 uint8
|
||||
Int16 int16
|
||||
UInt16 uint16
|
||||
Int32 int32
|
||||
UInt32 uint32
|
||||
Int64 int64
|
||||
UInt64 uint64
|
||||
Float32 float32
|
||||
Float64 float64
|
||||
}
|
||||
|
||||
numeric := CAST(Decimal("1234567890.111")).AS_NUMERIC()
|
||||
|
||||
stmt := SELECT(
|
||||
numeric.AS("number.int8"),
|
||||
numeric.AS("number.uint8"),
|
||||
numeric.AS("number.int16"),
|
||||
numeric.AS("number.uint16"),
|
||||
numeric.AS("number.int32"),
|
||||
numeric.AS("number.uint32"),
|
||||
numeric.AS("number.int64"),
|
||||
numeric.AS("number.uint64"),
|
||||
numeric.AS("number.float32"),
|
||||
numeric.AS("number.float64"),
|
||||
)
|
||||
|
||||
var number Number
|
||||
err := stmt.Query(db, &number)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, number.Int8, int8(-46)) // overflow
|
||||
require.Equal(t, number.UInt8, uint8(210)) // overflow
|
||||
require.Equal(t, number.Int16, int16(722)) // overflow
|
||||
require.Equal(t, number.UInt16, uint16(722)) // overflow
|
||||
require.Equal(t, number.Int32, int32(1234567890))
|
||||
require.Equal(t, number.UInt32, uint32(1234567890))
|
||||
require.Equal(t, number.Int64, int64(1234567890))
|
||||
require.Equal(t, number.UInt64, uint64(1234567890))
|
||||
require.Equal(t, number.Float32, float32(1.234568e+09))
|
||||
require.Equal(t, number.Float64, float64(1.234567890111e+09))
|
||||
}
|
||||
|
||||
var address256 = model.Address{
|
||||
AddressID: 256,
|
||||
Address: "1497 Yuzhou Drive",
|
||||
|
|
|
|||
|
|
@ -1,16 +1,17 @@
|
|||
package postgres
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/go-jet/jet/v2/internal/testutils"
|
||||
. "github.com/go-jet/jet/v2/postgres"
|
||||
"github.com/go-jet/jet/v2/tests/.gentestdata/jetdb/dvds/enum"
|
||||
"github.com/go-jet/jet/v2/tests/.gentestdata/jetdb/dvds/model"
|
||||
. "github.com/go-jet/jet/v2/tests/.gentestdata/jetdb/dvds/table"
|
||||
"github.com/go-jet/jet/v2/tests/.gentestdata/jetdb/dvds/view"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestSelect_ScanToStruct(t *testing.T) {
|
||||
|
|
@ -1255,7 +1256,7 @@ OFFSET 20;
|
|||
LIMIT(10).
|
||||
OFFSET(20)
|
||||
|
||||
fmt.Println(query.DebugSql())
|
||||
//fmt.Println(query.DebugSql())
|
||||
|
||||
testutils.AssertDebugStatementSql(t, query, expectedQuery, float64(100), float64(200), int64(10), int64(20))
|
||||
|
||||
|
|
@ -1788,7 +1789,7 @@ func TestJoinViewWithTable(t *testing.T) {
|
|||
Rentals []model.Rental
|
||||
}
|
||||
|
||||
fmt.Println(query.DebugSql())
|
||||
//fmt.Println(query.DebugSql())
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
require.NoError(t, err)
|
||||
|
|
@ -1894,3 +1895,100 @@ WHERE ($1 AND (customer.customer_id = $2)) AND (customer.activebool = $3);
|
|||
require.Len(t, dest, 1)
|
||||
testutils.AssertDeepEqual(t, dest[0], customer0)
|
||||
}
|
||||
|
||||
func TestLateral(t *testing.T) {
|
||||
|
||||
languages := LATERAL(
|
||||
SELECT(
|
||||
Language.AllColumns,
|
||||
).FROM(
|
||||
Language,
|
||||
).WHERE(
|
||||
Language.Name.NOT_IN(String("spanish")).
|
||||
AND(Film.LanguageID.EQ(Language.LanguageID)),
|
||||
),
|
||||
).AS("films")
|
||||
|
||||
stmt := SELECT(
|
||||
Film.FilmID,
|
||||
Film.Title,
|
||||
languages.AllColumns(),
|
||||
).FROM(
|
||||
Film.CROSS_JOIN(languages),
|
||||
).WHERE(
|
||||
Film.FilmID.EQ(Int(1)),
|
||||
).ORDER_BY(
|
||||
Film.FilmID,
|
||||
).LIMIT(1)
|
||||
|
||||
testutils.AssertDebugStatementSql(t, stmt, `
|
||||
SELECT film.film_id AS "film.film_id",
|
||||
film.title AS "film.title",
|
||||
films."language.language_id" AS "language.language_id",
|
||||
films."language.name" AS "language.name",
|
||||
films."language.last_update" AS "language.last_update"
|
||||
FROM dvds.film
|
||||
CROSS JOIN LATERAL (
|
||||
SELECT language.language_id AS "language.language_id",
|
||||
language.name AS "language.name",
|
||||
language.last_update AS "language.last_update"
|
||||
FROM dvds.language
|
||||
WHERE (language.name NOT IN ('spanish')) AND (film.language_id = language.language_id)
|
||||
) AS films
|
||||
WHERE film.film_id = 1
|
||||
ORDER BY film.film_id
|
||||
LIMIT 1;
|
||||
`)
|
||||
|
||||
type FilmLanguage struct {
|
||||
model.Film
|
||||
model.Language
|
||||
}
|
||||
|
||||
var dest []FilmLanguage
|
||||
|
||||
err := stmt.Query(db, &dest)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, dest[0].Film.Title, "Academy Dinosaur")
|
||||
require.Equal(t, dest[0].Language.Name, "English ")
|
||||
|
||||
t.Run("implicit cross join", func(t *testing.T) {
|
||||
stmt2 := SELECT(
|
||||
Film.FilmID,
|
||||
Film.Title,
|
||||
languages.AllColumns(),
|
||||
).FROM(
|
||||
Film,
|
||||
languages,
|
||||
).WHERE(
|
||||
Film.FilmID.EQ(Int(1)),
|
||||
).ORDER_BY(
|
||||
Film.FilmID,
|
||||
).LIMIT(1)
|
||||
|
||||
testutils.AssertDebugStatementSql(t, stmt2, `
|
||||
SELECT film.film_id AS "film.film_id",
|
||||
film.title AS "film.title",
|
||||
films."language.language_id" AS "language.language_id",
|
||||
films."language.name" AS "language.name",
|
||||
films."language.last_update" AS "language.last_update"
|
||||
FROM dvds.film,
|
||||
LATERAL (
|
||||
SELECT language.language_id AS "language.language_id",
|
||||
language.name AS "language.name",
|
||||
language.last_update AS "language.last_update"
|
||||
FROM dvds.language
|
||||
WHERE (language.name NOT IN ('spanish')) AND (film.language_id = language.language_id)
|
||||
) AS films
|
||||
WHERE film.film_id = 1
|
||||
ORDER BY film.film_id
|
||||
LIMIT 1;
|
||||
`)
|
||||
|
||||
var dest2 []FilmLanguage
|
||||
|
||||
err2 := stmt2.Query(db, &dest2)
|
||||
require.NoError(t, err2)
|
||||
require.Equal(t, dest, dest2)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit ed53a505eb738d1be457877eee251f9ba0418df1
|
||||
Subproject commit a6c1975a167645f913496131ae81d4cabc070046
|
||||
Loading…
Add table
Add a link
Reference in a new issue