Update wiki pages.
This commit is contained in:
parent
518ff49a77
commit
c78ca8a876
17 changed files with 105 additions and 81 deletions
13
README.md
13
README.md
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
Jet is a framework for writing type-safe SQL queries for PostgreSQL in Go, with ability to easily
|
Jet is a framework for writing type-safe SQL queries for PostgreSQL in Go, with ability to easily
|
||||||
convert database query result to desired arbitrary structure.
|
convert database query result to desired arbitrary structure.
|
||||||
_Support for other databases will be added in future releases._
|
_Support for additional databases will be added in future jet releases._
|
||||||
|
|
||||||
|
|
||||||
## Contents
|
## Contents
|
||||||
|
|
@ -105,7 +105,7 @@ Generated files folder structure will look like this:
|
||||||
| | |-- mpaa_rating.go
|
| | |-- mpaa_rating.go
|
||||||
| | ...
|
| | ...
|
||||||
```
|
```
|
||||||
Types from `table` and `enum` are used to write type safe SQL in Go, and `model` types are combined and used to store
|
Types from `table` and `enum` are used to write type safe SQL in Go, and `model` types are combined to store
|
||||||
results of the SQL queries.
|
results of the SQL queries.
|
||||||
|
|
||||||
#### Lets write some SQL queries in Go
|
#### Lets write some SQL queries in Go
|
||||||
|
|
@ -150,7 +150,7 @@ Note that every column has a type. String column `Language.Name` and `Category.N
|
||||||
string columns and expressions. `Actor.ActorID`, `FilmActor.ActorID`, `Film.Length` are integer columns
|
string columns and expressions. `Actor.ActorID`, `FilmActor.ActorID`, `Film.Length` are integer columns
|
||||||
and can be compared only with integer columns and expressions.
|
and can be compared only with integer columns and expressions.
|
||||||
|
|
||||||
__To get parametrized SQL query created with above statement__
|
__How get parametrized SQL query?__
|
||||||
```go
|
```go
|
||||||
query, args, err := stmt.Sql()
|
query, args, err := stmt.Sql()
|
||||||
```
|
```
|
||||||
|
|
@ -200,7 +200,7 @@ ORDER BY actor.actor_id ASC, film.film_id ASC;
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
__To get debug SQL that can be copy pasted to sql editor and executed.__
|
__How to get debug SQL that can be copy pasted to sql editor and executed?__
|
||||||
```go
|
```go
|
||||||
debugSql, err := stmt.DebugSql()
|
debugSql, err := stmt.DebugSql()
|
||||||
```
|
```
|
||||||
|
|
@ -272,7 +272,7 @@ err := stmt.Query(db, &dest)
|
||||||
handleError(err)
|
handleError(err)
|
||||||
```
|
```
|
||||||
|
|
||||||
__And thats It.__
|
__And thats it.__
|
||||||
|
|
||||||
`dest` now contains the list of all actors(with list of films acted, where each film has information about language and list of belonging categories) that acted in films longer than 180 minutes, film language is 'English'
|
`dest` now contains the list of all actors(with list of films acted, where each film has information about language and list of belonging categories) that acted in films longer than 180 minutes, film language is 'English'
|
||||||
and film category is not 'Action'.
|
and film category is not 'Action'.
|
||||||
|
|
@ -468,7 +468,8 @@ handleError(err)
|
||||||
Complete code example can be found at [./examples/quick-start/quick-start.go](./examples/quick-start/quick-start.go)
|
Complete code example can be found at [./examples/quick-start/quick-start.go](./examples/quick-start/quick-start.go)
|
||||||
|
|
||||||
|
|
||||||
This example represent probably the most common use case, but Jet offers much more. Detail info can be found at project wiki page.
|
This example represent probably the most common use case. Detail info about additional features and use cases can be
|
||||||
|
found at project [wiki](https://github.com/go-jet/jet/wiki) page.
|
||||||
|
|
||||||
## Benefits
|
## Benefits
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,11 +52,11 @@ func (b *boolInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs BoolExpression) BoolExpress
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *boolInterfaceImpl) AND(expression BoolExpression) BoolExpression {
|
func (b *boolInterfaceImpl) AND(expression BoolExpression) BoolExpression {
|
||||||
return newBinaryBoolExpression(b.parent, expression, "AND")
|
return newBinaryBoolOperator(b.parent, expression, "AND")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *boolInterfaceImpl) OR(expression BoolExpression) BoolExpression {
|
func (b *boolInterfaceImpl) OR(expression BoolExpression) BoolExpression {
|
||||||
return newBinaryBoolExpression(b.parent, expression, "OR")
|
return newBinaryBoolOperator(b.parent, expression, "OR")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *boolInterfaceImpl) IS_TRUE() BoolExpression {
|
func (b *boolInterfaceImpl) IS_TRUE() BoolExpression {
|
||||||
|
|
@ -91,7 +91,7 @@ type binaryBoolExpression struct {
|
||||||
binaryOpExpression
|
binaryOpExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBinaryBoolExpression(lhs, rhs Expression, operator string) BoolExpression {
|
func newBinaryBoolOperator(lhs, rhs Expression, operator string) BoolExpression {
|
||||||
boolExpression := binaryBoolExpression{}
|
boolExpression := binaryBoolExpression{}
|
||||||
|
|
||||||
boolExpression.binaryOpExpression = newBinaryExpression(lhs, rhs, operator)
|
boolExpression.binaryOpExpression = newBinaryExpression(lhs, rhs, operator)
|
||||||
|
|
@ -109,7 +109,7 @@ type prefixBoolExpression struct {
|
||||||
prefixOpExpression
|
prefixOpExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPrefixBoolExpression(expression Expression, operator string) BoolExpression {
|
func newPrefixBoolOperator(expression Expression, operator string) BoolExpression {
|
||||||
exp := prefixBoolExpression{}
|
exp := prefixBoolExpression{}
|
||||||
exp.prefixOpExpression = newPrefixExpression(expression, operator)
|
exp.prefixOpExpression = newPrefixExpression(expression, operator)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,11 +47,11 @@ func (e *expressionInterfaceImpl) IS_NOT_NULL() BoolExpression {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *expressionInterfaceImpl) IN(expressions ...Expression) BoolExpression {
|
func (e *expressionInterfaceImpl) IN(expressions ...Expression) BoolExpression {
|
||||||
return newBinaryBoolExpression(e.parent, WRAP(expressions...), "IN")
|
return newBinaryBoolOperator(e.parent, WRAP(expressions...), "IN")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *expressionInterfaceImpl) NOT_IN(expressions ...Expression) BoolExpression {
|
func (e *expressionInterfaceImpl) NOT_IN(expressions ...Expression) BoolExpression {
|
||||||
return newBinaryBoolExpression(e.parent, WRAP(expressions...), "NOT IN")
|
return newBinaryBoolOperator(e.parent, WRAP(expressions...), "NOT IN")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *expressionInterfaceImpl) AS(alias string) projection {
|
func (e *expressionInterfaceImpl) AS(alias string) projection {
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,6 @@ type IntegerExpression interface {
|
||||||
BIT_OR(rhs IntegerExpression) IntegerExpression
|
BIT_OR(rhs IntegerExpression) IntegerExpression
|
||||||
// expression # rhs
|
// expression # rhs
|
||||||
BIT_XOR(rhs IntegerExpression) IntegerExpression
|
BIT_XOR(rhs IntegerExpression) IntegerExpression
|
||||||
// ~expression
|
|
||||||
BIT_NOT() IntegerExpression
|
|
||||||
// expression << rhs
|
// expression << rhs
|
||||||
BIT_SHIFT_LEFT(shift IntegerExpression) IntegerExpression
|
BIT_SHIFT_LEFT(shift IntegerExpression) IntegerExpression
|
||||||
// expression >> rhs
|
// expression >> rhs
|
||||||
|
|
@ -102,12 +100,12 @@ func (i *integerInterfaceImpl) DIV(expression IntegerExpression) IntegerExpressi
|
||||||
return newBinaryIntegerExpression(i.parent, expression, "/")
|
return newBinaryIntegerExpression(i.parent, expression, "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *integerInterfaceImpl) MOD(expression IntegerExpression) IntegerExpression {
|
func (i *integerInterfaceImpl) MOD(expression IntegerExpression) IntegerExpression {
|
||||||
return newBinaryIntegerExpression(n.parent, expression, "%")
|
return newBinaryIntegerExpression(i.parent, expression, "%")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *integerInterfaceImpl) POW(expression IntegerExpression) IntegerExpression {
|
func (i *integerInterfaceImpl) POW(expression IntegerExpression) IntegerExpression {
|
||||||
return newBinaryIntegerExpression(n.parent, expression, "^")
|
return newBinaryIntegerExpression(i.parent, expression, "^")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *integerInterfaceImpl) BIT_AND(expression IntegerExpression) IntegerExpression {
|
func (i *integerInterfaceImpl) BIT_AND(expression IntegerExpression) IntegerExpression {
|
||||||
|
|
@ -122,10 +120,6 @@ func (i *integerInterfaceImpl) BIT_XOR(expression IntegerExpression) IntegerExpr
|
||||||
return newBinaryIntegerExpression(i.parent, expression, "#")
|
return newBinaryIntegerExpression(i.parent, expression, "#")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *integerInterfaceImpl) BIT_NOT() IntegerExpression {
|
|
||||||
return newPrefixIntegerOpExpression(i.parent, "~")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *integerInterfaceImpl) BIT_SHIFT_LEFT(intExpression IntegerExpression) IntegerExpression {
|
func (i *integerInterfaceImpl) BIT_SHIFT_LEFT(intExpression IntegerExpression) IntegerExpression {
|
||||||
return newBinaryIntegerExpression(i.parent, intExpression, "<<")
|
return newBinaryIntegerExpression(i.parent, intExpression, "<<")
|
||||||
}
|
}
|
||||||
|
|
@ -161,7 +155,7 @@ type prefixIntegerOpExpression struct {
|
||||||
prefixOpExpression
|
prefixOpExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPrefixIntegerOpExpression(expression IntegerExpression, operator string) IntegerExpression {
|
func newPrefixIntegerOperator(expression IntegerExpression, operator string) IntegerExpression {
|
||||||
integerExpression := prefixIntegerOpExpression{}
|
integerExpression := prefixIntegerOpExpression{}
|
||||||
integerExpression.prefixOpExpression = newPrefixExpression(expression, operator)
|
integerExpression.prefixOpExpression = newPrefixExpression(expression, operator)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,11 @@ func TestIntExpressionPOW(t *testing.T) {
|
||||||
assertClauseSerialize(t, table1ColInt.POW(Int(11)), "(table1.col_int ^ $1)", int64(11))
|
assertClauseSerialize(t, table1ColInt.POW(Int(11)), "(table1.col_int ^ $1)", int64(11))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIntExpressionBIT_NOT(t *testing.T) {
|
||||||
|
assertClauseSerialize(t, BIT_NOT(table2ColInt), "~ table2.col_int")
|
||||||
|
assertClauseSerialize(t, BIT_NOT(Int(11)), "~ $1", int64(11))
|
||||||
|
}
|
||||||
|
|
||||||
func TestIntExpressionBIT_SHIFT_LEFT(t *testing.T) {
|
func TestIntExpressionBIT_SHIFT_LEFT(t *testing.T) {
|
||||||
assertClauseSerialize(t, table1ColInt.BIT_SHIFT_LEFT(table2ColInt), "(table1.col_int << table2.col_int)")
|
assertClauseSerialize(t, table1ColInt.BIT_SHIFT_LEFT(table2ColInt), "(table1.col_int << table2.col_int)")
|
||||||
assertClauseSerialize(t, table1ColInt.BIT_SHIFT_LEFT(Int(11)), "(table1.col_int << $1)", int64(11))
|
assertClauseSerialize(t, table1ColInt.BIT_SHIFT_LEFT(Int(11)), "(table1.col_int << $1)", int64(11))
|
||||||
|
|
|
||||||
24
operators.go
24
operators.go
|
|
@ -6,51 +6,55 @@ import "errors"
|
||||||
|
|
||||||
// Returns a representation of "not expr"
|
// Returns a representation of "not expr"
|
||||||
func NOT(expr BoolExpression) BoolExpression {
|
func NOT(expr BoolExpression) BoolExpression {
|
||||||
return newPrefixBoolExpression(expr, "NOT")
|
return newPrefixBoolOperator(expr, "NOT")
|
||||||
|
}
|
||||||
|
|
||||||
|
func BIT_NOT(expr IntegerExpression) IntegerExpression {
|
||||||
|
return newPrefixIntegerOperator(expr, "~")
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------- Comparison operators ---------------//
|
//----------- Comparison operators ---------------//
|
||||||
|
|
||||||
func EXISTS(subQuery SelectStatement) BoolExpression {
|
func EXISTS(subQuery SelectStatement) BoolExpression {
|
||||||
return newPrefixBoolExpression(subQuery, "EXISTS")
|
return newPrefixBoolOperator(subQuery, "EXISTS")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a representation of "a=b"
|
// Returns a representation of "a=b"
|
||||||
func eq(lhs, rhs Expression) BoolExpression {
|
func eq(lhs, rhs Expression) BoolExpression {
|
||||||
return newBinaryBoolExpression(lhs, rhs, "=")
|
return newBinaryBoolOperator(lhs, rhs, "=")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a representation of "a!=b"
|
// Returns a representation of "a!=b"
|
||||||
func notEq(lhs, rhs Expression) BoolExpression {
|
func notEq(lhs, rhs Expression) BoolExpression {
|
||||||
return newBinaryBoolExpression(lhs, rhs, "!=")
|
return newBinaryBoolOperator(lhs, rhs, "!=")
|
||||||
}
|
}
|
||||||
|
|
||||||
func isDistinctFrom(lhs, rhs Expression) BoolExpression {
|
func isDistinctFrom(lhs, rhs Expression) BoolExpression {
|
||||||
return newBinaryBoolExpression(lhs, rhs, "IS DISTINCT FROM")
|
return newBinaryBoolOperator(lhs, rhs, "IS DISTINCT FROM")
|
||||||
}
|
}
|
||||||
|
|
||||||
func isNotDistinctFrom(lhs, rhs Expression) BoolExpression {
|
func isNotDistinctFrom(lhs, rhs Expression) BoolExpression {
|
||||||
return newBinaryBoolExpression(lhs, rhs, "IS NOT DISTINCT FROM")
|
return newBinaryBoolOperator(lhs, rhs, "IS NOT DISTINCT FROM")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a representation of "a<b"
|
// Returns a representation of "a<b"
|
||||||
func lt(lhs Expression, rhs Expression) BoolExpression {
|
func lt(lhs Expression, rhs Expression) BoolExpression {
|
||||||
return newBinaryBoolExpression(lhs, rhs, "<")
|
return newBinaryBoolOperator(lhs, rhs, "<")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a representation of "a<=b"
|
// Returns a representation of "a<=b"
|
||||||
func ltEq(lhs, rhs Expression) BoolExpression {
|
func ltEq(lhs, rhs Expression) BoolExpression {
|
||||||
return newBinaryBoolExpression(lhs, rhs, "<=")
|
return newBinaryBoolOperator(lhs, rhs, "<=")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a representation of "a>b"
|
// Returns a representation of "a>b"
|
||||||
func gt(lhs, rhs Expression) BoolExpression {
|
func gt(lhs, rhs Expression) BoolExpression {
|
||||||
return newBinaryBoolExpression(lhs, rhs, ">")
|
return newBinaryBoolOperator(lhs, rhs, ">")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a representation of "a>=b"
|
// Returns a representation of "a>=b"
|
||||||
func gtEq(lhs, rhs Expression) BoolExpression {
|
func gtEq(lhs, rhs Expression) BoolExpression {
|
||||||
return newBinaryBoolExpression(lhs, rhs, ">=")
|
return newBinaryBoolOperator(lhs, rhs, ">=")
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------- CASE operator -------------------//
|
// --------------- CASE operator -------------------//
|
||||||
|
|
|
||||||
|
|
@ -62,19 +62,19 @@ func (s *stringInterfaceImpl) CONCAT(rhs Expression) StringExpression {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stringInterfaceImpl) LIKE(pattern StringExpression) BoolExpression {
|
func (s *stringInterfaceImpl) LIKE(pattern StringExpression) BoolExpression {
|
||||||
return newBinaryBoolExpression(s.parent, pattern, "LIKE")
|
return newBinaryBoolOperator(s.parent, pattern, "LIKE")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stringInterfaceImpl) NOT_LIKE(pattern StringExpression) BoolExpression {
|
func (s *stringInterfaceImpl) NOT_LIKE(pattern StringExpression) BoolExpression {
|
||||||
return newBinaryBoolExpression(s.parent, pattern, "NOT LIKE")
|
return newBinaryBoolOperator(s.parent, pattern, "NOT LIKE")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stringInterfaceImpl) SIMILAR_TO(pattern StringExpression) BoolExpression {
|
func (s *stringInterfaceImpl) SIMILAR_TO(pattern StringExpression) BoolExpression {
|
||||||
return newBinaryBoolExpression(s.parent, pattern, "SIMILAR TO")
|
return newBinaryBoolOperator(s.parent, pattern, "SIMILAR TO")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stringInterfaceImpl) NOT_SIMILAR_TO(pattern StringExpression) BoolExpression {
|
func (s *stringInterfaceImpl) NOT_SIMILAR_TO(pattern StringExpression) BoolExpression {
|
||||||
return newBinaryBoolExpression(s.parent, pattern, "NOT SIMILAR TO")
|
return newBinaryBoolOperator(s.parent, pattern, "NOT SIMILAR TO")
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------//
|
//---------------------------------------------------//
|
||||||
|
|
|
||||||
|
|
@ -275,6 +275,10 @@ func TestIntegerOperators(t *testing.T) {
|
||||||
AllTypes.Integer.MOD(Int(11)),
|
AllTypes.Integer.MOD(Int(11)),
|
||||||
AllTypes.Integer.POW(AllTypes.Smallint),
|
AllTypes.Integer.POW(AllTypes.Smallint),
|
||||||
AllTypes.Integer.POW(Int(11)),
|
AllTypes.Integer.POW(Int(11)),
|
||||||
|
AllTypes.Integer.BIT_AND(AllTypes.Smallint),
|
||||||
|
AllTypes.Integer.BIT_OR(AllTypes.Smallint),
|
||||||
|
AllTypes.Integer.BIT_XOR(Int(11)),
|
||||||
|
BIT_NOT(AllTypes.Integer),
|
||||||
AllTypes.Integer.BIT_SHIFT_LEFT(AllTypes.Smallint),
|
AllTypes.Integer.BIT_SHIFT_LEFT(AllTypes.Smallint),
|
||||||
AllTypes.Integer.BIT_SHIFT_LEFT(Int(11)),
|
AllTypes.Integer.BIT_SHIFT_LEFT(Int(11)),
|
||||||
AllTypes.Integer.BIT_SHIFT_RIGHT(AllTypes.Smallint),
|
AllTypes.Integer.BIT_SHIFT_RIGHT(AllTypes.Smallint),
|
||||||
|
|
|
||||||
|
|
@ -7,14 +7,14 @@ Jet sql builder supports following expression types:
|
||||||
- String expressions
|
- String expressions
|
||||||
- Date expressions
|
- Date expressions
|
||||||
- Time expressions
|
- Time expressions
|
||||||
- Timez expressions (with time zone)
|
- Timez expressions (Time with time zone)
|
||||||
- Timestamp expressions
|
- Timestamp expressions
|
||||||
- Timestampz expressions (with time zone)
|
- Timestampz expressions (Timestamp with time zone)
|
||||||
|
|
||||||
_This list might be extended with feature Jet releases._
|
_This list might be extended with feature Jet releases._
|
||||||
|
|
||||||
### Literal Types
|
### Literal Types
|
||||||
For every expression type there is a method to create one expression literal type .
|
For every expression type there is a method to create one expression literal type.
|
||||||
Literal type examples:
|
Literal type examples:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
@ -27,7 +27,10 @@ jet.Time(23, 6, 6, 1)
|
||||||
jet.Timez(23, 6, 6, 222, +200)
|
jet.Timez(23, 6, 6, 222, +200)
|
||||||
jet.Timestamp(2010, 10, 21, 15, 30, 12, 333)
|
jet.Timestamp(2010, 10, 21, 15, 30, 12, 333)
|
||||||
jet.Timestampz(2010, 10, 21, 15, 30, 12, 444, 0)
|
jet.Timestampz(2010, 10, 21, 15, 30, 12, 444, 0)
|
||||||
|
```
|
||||||
|
|
||||||
|
There is also:
|
||||||
|
```
|
||||||
jet.NULL
|
jet.NULL
|
||||||
jet.STAR (alias for *)
|
jet.STAR (alias for *)
|
||||||
```
|
```
|
||||||
|
|
@ -105,7 +108,7 @@ Following operators are only available on integer expressions:
|
||||||
| BIT_AND | jet.Int(11).BIT_AND(table.Film.Length) | 11 & film.length |
|
| BIT_AND | jet.Int(11).BIT_AND(table.Film.Length) | 11 & film.length |
|
||||||
| BIT_OR | jet.Int(11).BIT_OR(table.Film.Length) | 11 \| film.length |
|
| BIT_OR | jet.Int(11).BIT_OR(table.Film.Length) | 11 \| film.length |
|
||||||
| BIT_XOR | jet.Int(11).BIT_XOR(table.Film.Length) | 11 # film.length |
|
| BIT_XOR | jet.Int(11).BIT_XOR(table.Film.Length) | 11 # film.length |
|
||||||
| BIT_NOT | jet.Int(11).BIT_NOT(table.Film.Length) | ~ 11 |
|
| BIT_NOT | BIT_NOT(table.Film.Length) | ~ film.length |
|
||||||
| BIT_SHIFT_LEFT | jet.Int(11).BIT_SHIFT_LEFT(table.Film.Length) | 11 >> film.length |
|
| BIT_SHIFT_LEFT | jet.Int(11).BIT_SHIFT_LEFT(table.Film.Length) | 11 >> film.length |
|
||||||
| BIT_SHIFT_RIGHT | jet.Int(11).BIT_SHIFT_RIGHT(table.Film.Length) | 11 >> film.length |
|
| BIT_SHIFT_RIGHT | jet.Int(11).BIT_SHIFT_RIGHT(table.Film.Length) | 11 >> film.length |
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ go install 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.
|
||||||
|
|
||||||
Test jet can be found in the PATH.
|
Test jet generator can be found in the PATH.
|
||||||
```sh
|
```sh
|
||||||
jet -h
|
jet -h
|
||||||
Usage of jet:
|
Usage of jet:
|
||||||
|
|
@ -38,15 +38,19 @@ Usage of jet:
|
||||||
Additional connection string parameters(optional)
|
Additional connection string parameters(optional)
|
||||||
```
|
```
|
||||||
|
|
||||||
Now to generate sample database:
|
To generate jet SQL Builder and Data Model files from postgres database we need to call `jet` generator with postgres
|
||||||
|
connection parameters and root destination folder path for generated files.
|
||||||
|
Assuming we are running local postgres database, with user `jet`, database `jetdb` and schema `dvds` we will use this command:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
jet -host=localhost -port=5432 -user=jet -password=jet -dbname=jetdb -schema dvds -path ./gen
|
jet -host=localhost -port=5432 -user=jet -password=jet -dbname=jetdb -schema=dvds -path=./gen
|
||||||
```
|
```
|
||||||
```sh
|
```sh
|
||||||
Connecting to postgres database: host=localhost port=5432 user=jet password=jet dbname=jetdb sslmode=disable
|
Connecting to postgres database: host=localhost port=5432 user=jet password=jet dbname=jetdb sslmode=disable
|
||||||
Retrieving schema information...
|
Retrieving schema information...
|
||||||
FOUND 15 table(s), 1 enum(s)
|
FOUND 15 table(s), 1 enum(s)
|
||||||
Cleaning up destination directory...
|
Destination directory: ./gen/jetdb/dvds
|
||||||
|
Cleaning up schema destination directory...
|
||||||
Generating table sql builder files...
|
Generating table sql builder files...
|
||||||
Generating table model files...
|
Generating table model files...
|
||||||
Generating enum sql builder files...
|
Generating enum sql builder files...
|
||||||
|
|
@ -55,6 +59,8 @@ Done
|
||||||
```
|
```
|
||||||
#### 2) Generating from code
|
#### 2) Generating from code
|
||||||
|
|
||||||
|
The same files can be generated manually from code.
|
||||||
|
|
||||||
```
|
```
|
||||||
import "github.com/go-jet/jet/generator/postgres"
|
import "github.com/go-jet/jet/generator/postgres"
|
||||||
|
|
||||||
|
|
@ -72,9 +78,9 @@ err = postgres.Generate("./gen", postgres.DBConnection{
|
||||||
```
|
```
|
||||||
|
|
||||||
In both ways, generator will:
|
In both ways, generator will:
|
||||||
- connect to postgres database and retrieve information about the tables and enums of `dvds` schema
|
- connect to postgres database and retrieve information about the _tables_ and _enums_ of `dvds` schema
|
||||||
- delete everything in destination folder `./gen`,
|
- delete everything in schema destination folder - `./gen/jetdb/dvds`,
|
||||||
- generate sql builder and model Go files for each schema tables and enums into destination folder `./gen`.
|
- and finally generate sql builder and model files for each schema tables and enums.
|
||||||
|
|
||||||
Generated files folder structure will look like this:
|
Generated files folder structure will look like this:
|
||||||
```
|
```
|
||||||
|
|
@ -98,4 +104,4 @@ Generated files folder structure will look like this:
|
||||||
|
|
||||||
Table and enums from database schema are used as a template to generate two types of Go files:
|
Table and enums from database schema are used as a template to generate two types of Go files:
|
||||||
* SQL Builder files - used to write type safe SQL statements in Go (`enum` and `table` package)
|
* SQL Builder files - used to write type safe SQL statements in Go (`enum` and `table` package)
|
||||||
* Model files - used to store result from database queries (`model` package)
|
* Model files - used to combine and store result from database queries (`model` package)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
|
|
||||||
The PostgreSQL INSERT statement is used to insert a single record or multiple records
|
INSERT statement is used to insert a single record or multiple records
|
||||||
into a table. More about PostgreSQL INSERT statement can be found here: https://www.postgresql.org/docs/11/sql-insert.html
|
into a table. More about PostgreSQL INSERT statement can be found here: https://www.postgresql.org/docs/11/sql-insert.html
|
||||||
|
|
||||||
Following clauses are supported:
|
Following clauses are supported:
|
||||||
|
|
@ -121,7 +121,6 @@ insertStmt := Link.INSERT(Link.ID, Link.URL, Link.Name, Link.Description).
|
||||||
dest := []model.Link{}
|
dest := []model.Link{}
|
||||||
|
|
||||||
err := insertStmt.Query(db, &dest)
|
err := insertStmt.Query(db, &dest)
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Use `ExecContext` and `QueryContext` to provide context object to execution.
|
Use `ExecContext` and `QueryContext` to provide context object to execution.
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,21 @@
|
||||||
## Model
|
## Model
|
||||||
|
|
||||||
Model files are simple data files used to store result of SQL queries. They are
|
Model files are simple Go struct types used to combine and store result of SQL queries. They are
|
||||||
autogenerated from database tables and enums.
|
autogenerated from database tables and enums.
|
||||||
|
|
||||||
### Table model files
|
### Table model files
|
||||||
|
|
||||||
Following rules are applied to generate model files from database tables:
|
Following rules are applied to generate model types from database tables:
|
||||||
|
|
||||||
- for every table there is one Go file generated. File name is in snake case of the table name.
|
- for every table there is one Go file generated. File name is in snake case of the table name.
|
||||||
- every model file contains one struct type.
|
- every model file contains one struct type. Type name is a camel case of table name. Package name
|
||||||
Type name is a camel case of table name.
|
is always `model`.
|
||||||
- for every column of table there is a field in model struct. Field name is camel case of column name.
|
- for every column of table there is a field in model struct type. Field name is camel case of column name.
|
||||||
See below table for type mapping.
|
See below table for type mapping.
|
||||||
- fields are pointer types, if they relate to column that can be NULL.
|
- fields are pointer types, if they relate to column that can be NULL.
|
||||||
- fields corresponds to primary key columns are tagged with `sql:"primary_key"`.
|
- fields corresponds to primary key columns are tagged with `sql:"primary_key"`.
|
||||||
_This tag is used during query execution to group row results into desired arbitrary structure.
|
_This tag is used during query execution to group row results into desired arbitrary structure.
|
||||||
See more at [Execution](https://github.com/go-jet/jet/wiki/Execution):_
|
See more at [Execution](https://github.com/go-jet/jet/wiki/Execution)_
|
||||||
|
|
||||||
|
|
||||||
##### Mappings of database types to Go types
|
##### Mappings of database types to Go types
|
||||||
|
|
@ -80,11 +80,12 @@ Following rules are applied to generate model files from database enums:
|
||||||
|
|
||||||
- for every enum there is one Go file generated. File name is a snake case of enum name.
|
- for every enum there is one Go file generated. File name is a snake case of enum name.
|
||||||
- every file contains one renamed string type. Type name is a camel case of enum name.
|
- every file contains one renamed string type. Type name is a camel case of enum name.
|
||||||
|
Package name is always `model`.
|
||||||
Enum type has two helper methods to:
|
Enum type has two helper methods to:
|
||||||
- initialize correctly from database query result
|
- initialize correctly from database query result
|
||||||
- easily convert enum to string.
|
- easily convert enum to string.
|
||||||
- for every enum value there is one constant defined.
|
- for every enum value there is one constant defined.
|
||||||
Name of the constant is in format [camel case of enum_name]_[camel case of enum_value_name].
|
Name of the constant is in format `{CamelCase(enum_name)}_{CamelCase(enum_value_name)}`.
|
||||||
|
|
||||||
#### Example
|
#### Example
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ Above SQL clause written in go will produce following raw SQL:
|
||||||
|
|
||||||
```
|
```
|
||||||
SELECT 1 + 12 - 21,
|
SELECT 1 + 12 - 21,
|
||||||
film.name AS "film.name", --
|
film.name AS "film.name",
|
||||||
customer.first_name || customer.last_name AS "FullName"
|
customer.first_name || customer.last_name AS "FullName"
|
||||||
```
|
```
|
||||||
`film.name AS "film.name"` - column names are aliased by default. Alias is used during execution to map row result to
|
`film.name AS "film.name"` - column names are aliased by default. Alias is used during execution to map row result to
|
||||||
|
|
@ -211,7 +211,7 @@ of interest, and than about the columns.
|
||||||
|
|
||||||
## Sub-queries
|
## Sub-queries
|
||||||
|
|
||||||
How to write SELECT statement with sub-queries?
|
__How to write SELECT statement with sub-queries?__
|
||||||
|
|
||||||
Sub-queries are composed first:
|
Sub-queries are composed first:
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
## SQL Builder
|
## SQL Builder
|
||||||
|
|
||||||
SQL Builder files are Go files, containing types necessary to write type safe SQL queries in Go. They are
|
SQL Builder files are Go files, containing types necessary to write type safe SQL queries in Go. They are
|
||||||
autogenerated from database tables and enums. File names are snake case of the table name or enum name.
|
autogenerated from database tables and enums. File names is always snake case of the table or enum name.
|
||||||
|
|
||||||
### Table SQL Builder files
|
### Table SQL Builder files
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ For instance `city.city_id` -> `City.CityID`. This is being used to find appropr
|
||||||
It is not an error if there is not a column for each destination model field. Table and column names does not have
|
It is not an error if there is not a column for each destination model field. Table and column names does not have
|
||||||
to be in snake case.
|
to be in snake case.
|
||||||
|
|
||||||
`Query` uses reflection to introspect destination type structure, and result set column names(aliases), to be able to map result set data to destination object.
|
`Query` uses reflection to introspect destination type structure, and result set column names(aliases), to find appropriate destination field for result set column.
|
||||||
Every new destination struct object is cached by his and all the parents primary key. So grouping to work correctly at least table primary keys has to appear in query result set. If there is no primary key in a result set
|
Every new destination struct object is cached by his and all the parents primary key. So grouping to work correctly at least table primary keys has to appear in query result set. If there is no primary key in a result set
|
||||||
row number is used as grouping condition(which is always unique).
|
row number is used as grouping condition(which is always unique).
|
||||||
For instance, after row 1 is processed, two objects are stored to cache:
|
For instance, after row 1 is processed, two objects are stored to cache:
|
||||||
|
|
|
||||||
|
|
@ -9,16 +9,16 @@ Following statements are supported:
|
||||||
|
|
||||||
_This list might be extended with feature Jet releases._
|
_This list might be extended with feature Jet releases._
|
||||||
|
|
||||||
Statements SQL can be debugged in two ways:
|
### Executing statements
|
||||||
|
|
||||||
- `Sql() (query string, args []interface{}, err error)` - retrieves parametrized sql query with list of arguments
|
Statements can be executed with following methods:
|
||||||
- `DebugSql() (query string, err error)` - retrieves debug query where every parametrized placeholder is replaced with its argument.
|
- `Query(db execution.DB, destination interface{}) error` - executes statements over database connection db and maps
|
||||||
|
row result result set to destination.
|
||||||
Statements can be executed by following methods:
|
- `QueryContext(db execution.DB, context context.Context, destination interface{}) error` - executes statement with a
|
||||||
- `Query(db execution.DB, destination interface{}) error` - executes statements over database connection db and stores row result in destination.
|
context over database connection db and maps row result result set to destination.
|
||||||
- `QueryContext(db execution.DB, context context.Context, destination interface{}) error` - executes statement with a context over database connection db and stores row result in destination.
|
- `Exec(db execution.DB) (sql.Result, error)` - executes statement over db connection and returns `sql.Result`.
|
||||||
- `Exec(db execution.DB) (sql.Result, error)` - executes statement over db connection without returning any rows.
|
- `ExecContext(db execution.DB, context context.Context) (sql.Result, error)` - executes statement with context over
|
||||||
- `ExecContext(db execution.DB, context context.Context) (sql.Result, error)` - executes statement with context over db connection without returning any rows.
|
db connection and returns `sql.Result`.
|
||||||
|
|
||||||
Each execution method first creates parametrized sql query with list of arguments and then initiates query on database connection.
|
Each execution method first creates parametrized sql query with list of arguments and then initiates query on database connection.
|
||||||
Exec and ExecContext are just a wrappers around database `Exec` and `ExecContext`.
|
Exec and ExecContext are just a wrappers around database `Exec` and `ExecContext`.
|
||||||
|
|
@ -41,3 +41,11 @@ These include but are not limited to:
|
||||||
- `sql.DB`
|
- `sql.DB`
|
||||||
- `sql.Tx`
|
- `sql.Tx`
|
||||||
- `sql.Conn`
|
- `sql.Conn`
|
||||||
|
|
||||||
|
|
||||||
|
### Debugging statements
|
||||||
|
|
||||||
|
Statements SQL can be debugged in two ways:
|
||||||
|
|
||||||
|
- `Sql() (query string, args []interface{}, err error)` - retrieves parametrized sql query with list of arguments
|
||||||
|
- `DebugSql() (query string, err error)` - retrieves debug query where every parametrized placeholder is replaced with its argument.
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ SET (name, url) = ('Yahoo', 'http://yahoo.com')
|
||||||
WHERE link.name = 'Bing';
|
WHERE link.name = 'Bing';
|
||||||
```
|
```
|
||||||
|
|
||||||
Short-hand notation to extract model data for column values:
|
Short-hand notation to update values from model data:
|
||||||
|
|
||||||
```
|
```
|
||||||
yahoo := model.Link{
|
yahoo := model.Link{
|
||||||
|
|
@ -71,7 +71,6 @@ updateStmt := Link.
|
||||||
dest := []model.Link{}
|
dest := []model.Link{}
|
||||||
|
|
||||||
err := updateStmt.Query(db, &dest)
|
err := updateStmt.Query(db, &dest)
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Use `ExecContext` and `QueryContext` to provide context object to execution.
|
Use `ExecContext` and `QueryContext` to provide context object to execution.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue