Update wiki pages.

This commit is contained in:
go-jet 2019-07-15 13:06:06 +02:00
parent 518ff49a77
commit c78ca8a876
17 changed files with 105 additions and 81 deletions

View file

@ -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

View file

@ -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)

View file

@ -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 {

View file

@ -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)

View file

@ -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))

View file

@ -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 -------------------//

View file

@ -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")
} }
//---------------------------------------------------// //---------------------------------------------------//

View file

@ -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),

View file

@ -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,9 +27,12 @@ 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 *)
``` ```
### Column Types ### Column Types
@ -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 |

View file

@ -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"
@ -71,10 +77,10 @@ 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)

View file

@ -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.

View file

@ -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
@ -79,12 +79,13 @@ type Address struct {
Following rules are applied to generate model files from database enums: 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

View file

@ -1,7 +1,7 @@
SELECT statement is used to retrieve records from one or more tables in PostgreSQL. SELECT statement is used to retrieve records from one or more tables in PostgreSQL.
More about SELECT statement in postgres can be found at: https://www.postgresql.org/docs/11/sql-select.html More about SELECT statement in postgres can be found at: https://www.postgresql.org/docs/11/sql-select.html
Following clauses are supported: Following clauses are supported:
- SELECT(expressions...) - expressions to form output rows of the SELECT statement. - SELECT(expressions...) - expressions to form output rows of the SELECT statement.
- DISTINCT() - remove all duplicate rows from result set - DISTINCT() - remove all duplicate rows from result set
@ -26,7 +26,7 @@ Following clauses are supported:
- UNION(select) / UNION_ALL(select) - computes the set union of the rows returned by the involved SELECT statements - UNION(select) / UNION_ALL(select) - computes the set union of the rows returned by the involved SELECT statements
- INTERSECT(select) / INTERSECT_ALL(select) - computes the set intersection of the rows returned by the involved SELECT statements - INTERSECT(select) / INTERSECT_ALL(select) - computes the set intersection of the rows returned by the involved SELECT statements
- EXCEPT(select) / EXCEPT_ALL(select) - computes the set of rows that are in the result of the left SELECT statement but not in the result of the right one - EXCEPT(select) / EXCEPT_ALL(select) - computes the set of rows that are in the result of the left SELECT statement but not in the result of the right one
_This list might be extended with feature Jet releases._ _This list might be extended with feature Jet releases._
### Examples per clause ### Examples per clause
@ -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:
``` ```

View file

@ -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

View file

@ -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:

View file

@ -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`.
@ -40,4 +40,12 @@ type DB interface {
These include but are not limited to: 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.

View file

@ -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{
@ -70,8 +70,7 @@ 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.