Skip to content

Commit

Permalink
Merge pull request #32 from go-jet/develop
Browse files Browse the repository at this point in the history
Interval type support. Sample usage can be seen here.
Datetime arithmetic with interval types.
Dynamic projection list support. Sample usage.
[bug] Escape reserved words used as identifier(issue).
[bug] Fix crash on generating enum SQL Builder files when database enum contains numeric values(issue).
  • Loading branch information
go-jet authored Feb 17, 2020
2 parents bdb6bef + 4c6caa4 commit eea776a
Show file tree
Hide file tree
Showing 93 changed files with 3,149 additions and 1,171 deletions.
6 changes: 4 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ jobs:
go get github.com/go-sql-driver/mysql
go get github.com/pkg/profile
go get gotest.tools/assert
go get github.com/stretchr/testify/assert
go get github.com/google/go-cmp/cmp
go get github.com/davecgh/go-spew/spew
go get github.com/jstemmer/go-junit-report
Expand Down Expand Up @@ -142,7 +143,8 @@ jobs:
go get github.com/go-sql-driver/mysql
go get github.com/pkg/profile
go get gotest.tools/assert
go get github.com/stretchr/testify/assert
go get github.com/google/go-cmp/cmp
go get github.com/davecgh/go-spew/spew
go get github.com/jstemmer/go-junit-report
Expand Down
9 changes: 3 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ https://medium.com/@go.jet/jet-5f3667efa0cc
## Features
1) Auto-generated type-safe SQL Builder
- PostgreSQL:
* SELECT `(DISTINCT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, OFFSET, FOR, UNION, INTERSECT, EXCEPT, sub-queries)`
* SELECT `(DISTINCT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, OFFSET, FOR, UNION, INTERSECT, EXCEPT, WINDOW, sub-queries)`
* INSERT `(VALUES, query, RETURNING)`,
* UPDATE `(SET, WHERE, RETURNING)`,
* DELETE `(WHERE, RETURNING)`,
* LOCK `(IN, NOWAIT)`
- MySQL and MariaDB:
* SELECT `(DISTINCT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, OFFSET, FOR, UNION, LOCK_IN_SHARE_MODE, sub-queries)`
* SELECT `(DISTINCT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, OFFSET, FOR, UNION, LOCK_IN_SHARE_MODE, WINDOW, sub-queries)`
* INSERT `(VALUES, query)`,
* UPDATE `(SET, WHERE)`,
* DELETE `(WHERE, ORDER_BY, LIMIT)`,
Expand Down Expand Up @@ -560,15 +560,12 @@ At the moment Jet dependence only of:

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

## Versioning

[SemVer](http://semver.org/) is used for versioning. For the versions available, take a look at the [releases](https://github.com/go-jet/jet/releases).


For now there is no guarantee that public API will remain backward compatible. Please read new release drafts to get acquaint how to handle possible build breakable API changes.

## License

Copyright 2019 Goran Bjelanovic
Expand Down
4 changes: 3 additions & 1 deletion generator/internal/metadata/column_meta_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,10 @@ func (c ColumnMetaData) getSqlBuilderColumnType() string {
return "Time"
case "time with time zone":
return "Timez"
case "interval":
return "Interval"
case "USER-DEFINED", "enum", "text", "character", "character varying", "bytea", "uuid",
"tsvector", "bit", "bit varying", "money", "json", "jsonb", "xml", "point", "interval", "line", "ARRAY",
"tsvector", "bit", "bit varying", "money", "json", "jsonb", "xml", "point", "line", "ARRAY",
"char", "varchar", "binary", "varbinary",
"tinyblob", "blob", "mediumblob", "longblob", "tinytext", "mediumtext", "longtext": // MySQL
return "String"
Expand Down
3 changes: 2 additions & 1 deletion generator/internal/template/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ func generateGoFiles(dirPath, packageName string, template string, metaDataList
func GenerateTemplate(templateText string, templateData interface{}, dialect jet.Dialect, params ...map[string]interface{}) ([]byte, error) {

t, err := template.New("sqlBuilderTableTemplate").Funcs(template.FuncMap{
"ToGoIdentifier": utils.ToGoIdentifier,
"ToGoIdentifier": utils.ToGoIdentifier,
"ToGoEnumValueIdentifier": utils.ToGoEnumValueIdentifier,
"now": func() string {
return time.Now().Format(time.RFC850)
},
Expand Down
4 changes: 2 additions & 2 deletions generator/internal/template/templates.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion internal/3rdparty/snaker/snaker_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package snaker

import (
"gotest.tools/assert"
"github.com/stretchr/testify/assert"
"testing"
)

Expand Down
3 changes: 1 addition & 2 deletions internal/jet/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ func newAlias(expression Expression, aliasName string) Projection {
}

func (a *alias) fromImpl(subQuery SelectTable) Projection {
column := newColumn(a.alias, "", nil)
column.Parent = &column
column := NewColumnImpl(a.alias, "", nil)
column.subQuery = subQuery

return &column
Expand Down
76 changes: 18 additions & 58 deletions internal/jet/bool_expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,109 +37,69 @@ type boolInterfaceImpl struct {
}

func (b *boolInterfaceImpl) EQ(expression BoolExpression) BoolExpression {
return eq(b.parent, expression)
return Eq(b.parent, expression)
}

func (b *boolInterfaceImpl) NOT_EQ(expression BoolExpression) BoolExpression {
return notEq(b.parent, expression)
return NotEq(b.parent, expression)
}

func (b *boolInterfaceImpl) IS_DISTINCT_FROM(rhs BoolExpression) BoolExpression {
return isDistinctFrom(b.parent, rhs)
return IsDistinctFrom(b.parent, rhs)
}

func (b *boolInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs BoolExpression) BoolExpression {
return isNotDistinctFrom(b.parent, rhs)
return IsNotDistinctFrom(b.parent, rhs)
}

func (b *boolInterfaceImpl) AND(expression BoolExpression) BoolExpression {
return newBinaryBoolOperator(b.parent, expression, "AND")
return newBinaryBoolOperatorExpression(b.parent, expression, "AND")
}

func (b *boolInterfaceImpl) OR(expression BoolExpression) BoolExpression {
return newBinaryBoolOperator(b.parent, expression, "OR")
return newBinaryBoolOperatorExpression(b.parent, expression, "OR")
}

func (b *boolInterfaceImpl) IS_TRUE() BoolExpression {
return newPostifxBoolExpression(b.parent, "IS TRUE")
return newPostfixBoolOperatorExpression(b.parent, "IS TRUE")
}

func (b *boolInterfaceImpl) IS_NOT_TRUE() BoolExpression {
return newPostifxBoolExpression(b.parent, "IS NOT TRUE")
return newPostfixBoolOperatorExpression(b.parent, "IS NOT TRUE")
}

func (b *boolInterfaceImpl) IS_FALSE() BoolExpression {
return newPostifxBoolExpression(b.parent, "IS FALSE")
return newPostfixBoolOperatorExpression(b.parent, "IS FALSE")
}

func (b *boolInterfaceImpl) IS_NOT_FALSE() BoolExpression {
return newPostifxBoolExpression(b.parent, "IS NOT FALSE")
return newPostfixBoolOperatorExpression(b.parent, "IS NOT FALSE")
}

func (b *boolInterfaceImpl) IS_UNKNOWN() BoolExpression {
return newPostifxBoolExpression(b.parent, "IS UNKNOWN")
return newPostfixBoolOperatorExpression(b.parent, "IS UNKNOWN")
}

func (b *boolInterfaceImpl) IS_NOT_UNKNOWN() BoolExpression {
return newPostifxBoolExpression(b.parent, "IS NOT UNKNOWN")
return newPostfixBoolOperatorExpression(b.parent, "IS NOT UNKNOWN")
}

//---------------------------------------------------//
type binaryBoolExpression struct {
expressionInterfaceImpl
boolInterfaceImpl

binaryOpExpression
}

func newBinaryBoolOperator(lhs, rhs Expression, operator string, additionalParams ...Expression) BoolExpression {
binaryBoolExpression := binaryBoolExpression{}

binaryBoolExpression.binaryOpExpression = newBinaryExpression(lhs, rhs, operator, additionalParams...)
binaryBoolExpression.expressionInterfaceImpl.Parent = &binaryBoolExpression
binaryBoolExpression.boolInterfaceImpl.parent = &binaryBoolExpression

return &binaryBoolExpression
func newBinaryBoolOperatorExpression(lhs, rhs Expression, operator string, additionalParams ...Expression) BoolExpression {
return BoolExp(NewBinaryOperatorExpression(lhs, rhs, operator, additionalParams...))
}

//---------------------------------------------------//
type prefixBoolExpression struct {
expressionInterfaceImpl
boolInterfaceImpl

prefixOpExpression
}

func newPrefixBoolOperator(expression Expression, operator string) BoolExpression {
exp := prefixBoolExpression{}
exp.prefixOpExpression = newPrefixExpression(expression, operator)

exp.expressionInterfaceImpl.Parent = &exp
exp.boolInterfaceImpl.parent = &exp

return &exp
func newPrefixBoolOperatorExpression(expression Expression, operator string) BoolExpression {
return BoolExp(newPrefixOperatorExpression(expression, operator))
}

//---------------------------------------------------//
type postfixBoolOpExpression struct {
expressionInterfaceImpl
boolInterfaceImpl

postfixOpExpression
}

func newPostifxBoolExpression(expression Expression, operator string) BoolExpression {
exp := postfixBoolOpExpression{}
exp.postfixOpExpression = newPostfixOpExpression(expression, operator)

exp.expressionInterfaceImpl.Parent = &exp
exp.boolInterfaceImpl.parent = &exp

return &exp
func newPostfixBoolOperatorExpression(expression Expression, operator string) BoolExpression {
return BoolExp(newPostfixOperatorExpression(expression, operator))
}

//---------------------------------------------------//

type boolExpressionWrapper struct {
boolInterfaceImpl
Expression
Expand Down
4 changes: 2 additions & 2 deletions internal/jet/cast.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ func (b *castImpl) AS(castType string) Expression {
cast: string(castType),
}

castExp.expressionInterfaceImpl.Parent = castExp
castExp.ExpressionInterfaceImpl.Parent = castExp

return castExp
}

type castExpression struct {
expressionInterfaceImpl
ExpressionInterfaceImpl

expression Expression
cast string
Expand Down
2 changes: 1 addition & 1 deletion internal/jet/clause_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package jet

import (
"gotest.tools/assert"
"github.com/stretchr/testify/assert"
"testing"
)

Expand Down
53 changes: 38 additions & 15 deletions internal/jet/column.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,70 +18,83 @@ type ColumnExpression interface {
Expression
}

// The base type for real materialized columns.
type columnImpl struct {
expressionInterfaceImpl
// ColumnExpressionImpl is base type for sql columns.
type ColumnExpressionImpl struct {
ExpressionInterfaceImpl

name string
tableName string

subQuery SelectTable
}

func newColumn(name string, tableName string, parent ColumnExpression) columnImpl {
bc := columnImpl{
// NewColumnImpl creates new ColumnExpressionImpl
func NewColumnImpl(name string, tableName string, parent ColumnExpression) ColumnExpressionImpl {
bc := ColumnExpressionImpl{
name: name,
tableName: tableName,
}

bc.expressionInterfaceImpl.Parent = parent
if parent != nil {
bc.ExpressionInterfaceImpl.Parent = parent
} else {
bc.ExpressionInterfaceImpl.Parent = &bc
}

return bc
}

func (c *columnImpl) Name() string {
// Name returns name of the column
func (c *ColumnExpressionImpl) Name() string {
return c.name
}

func (c *columnImpl) TableName() string {
// TableName returns column table name
func (c *ColumnExpressionImpl) TableName() string {
return c.tableName
}

func (c *columnImpl) setTableName(table string) {
func (c *ColumnExpressionImpl) setTableName(table string) {
c.tableName = table
}

func (c *columnImpl) setSubQuery(subQuery SelectTable) {
func (c *ColumnExpressionImpl) setSubQuery(subQuery SelectTable) {
c.subQuery = subQuery
}

func (c *columnImpl) defaultAlias() string {
func (c *ColumnExpressionImpl) defaultAlias() string {
if c.tableName != "" {
return c.tableName + "." + c.name
}

return c.name
}

func (c *columnImpl) serializeForOrderBy(statement StatementType, out *SQLBuilder) {
func (c *ColumnExpressionImpl) fromImpl(subQuery SelectTable) Projection {
newColumn := NewColumnImpl(c.name, c.tableName, nil)
newColumn.setSubQuery(subQuery)

return &newColumn
}

func (c *ColumnExpressionImpl) serializeForOrderBy(statement StatementType, out *SQLBuilder) {
if statement == SetStatementType {
// set Statement (UNION, EXCEPT ...) can reference only select projections in order by clause
out.WriteAlias(c.defaultAlias()) //always quote

return
}

c.serialize(statement, out)
}

func (c columnImpl) serializeForProjection(statement StatementType, out *SQLBuilder) {
func (c ColumnExpressionImpl) serializeForProjection(statement StatementType, out *SQLBuilder) {
c.serialize(statement, out)

out.WriteString("AS")
out.WriteAlias(c.defaultAlias())
}

func (c columnImpl) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
func (c ColumnExpressionImpl) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {

if c.subQuery != nil {
out.WriteIdentifier(c.subQuery.Alias())
Expand Down Expand Up @@ -128,3 +141,13 @@ func (cl ColumnList) TableName() string { return "" }
func (cl ColumnList) setTableName(name string) {}
func (cl ColumnList) setSubQuery(subQuery SelectTable) {}
func (cl ColumnList) defaultAlias() string { return "" }

// SetTableName is utility function to set table name from outside of jet package to avoid making public setTableName
func SetTableName(columnExpression ColumnExpression, tableName string) {
columnExpression.setTableName(tableName)
}

// SetSubQuery is utility function to set table name from outside of jet package to avoid making public setSubQuery
func SetSubQuery(columnExpression ColumnExpression, subQuery SelectTable) {
columnExpression.setSubQuery(subQuery)
}
4 changes: 2 additions & 2 deletions internal/jet/column_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package jet
import "testing"

func TestColumn(t *testing.T) {
column := newColumn("col", "", nil)
column.expressionInterfaceImpl.Parent = &column
column := NewColumnImpl("col", "", nil)
column.ExpressionInterfaceImpl.Parent = &column

assertClauseSerialize(t, column, "col")
column.setTableName("table1")
Expand Down
Loading

0 comments on commit eea776a

Please sign in to comment.