Dialect refactor improvements and clean up.
This commit is contained in:
parent
23fd973699
commit
647ef21aaf
52 changed files with 1097 additions and 671 deletions
|
|
@ -31,7 +31,8 @@ func (c ColumnInfo) SqlBuilderColumnType() string {
|
||||||
return "Timestamp"
|
return "Timestamp"
|
||||||
case "timestamp with time zone":
|
case "timestamp with time zone":
|
||||||
return "Timestampz"
|
return "Timestampz"
|
||||||
case "time without time zone":
|
case "time without time zone",
|
||||||
|
"time": //MySQL
|
||||||
return "Time"
|
return "Time"
|
||||||
case "time with time zone":
|
case "time with time zone":
|
||||||
return "Timez"
|
return "Timez"
|
||||||
|
|
@ -67,7 +68,7 @@ func (c ColumnInfo) GoBaseType() string {
|
||||||
case "bigint":
|
case "bigint":
|
||||||
return "int64"
|
return "int64"
|
||||||
case "date", "timestamp without time zone", "timestamp with time zone", "time with time zone", "time without time zone",
|
case "date", "timestamp without time zone", "timestamp with time zone", "time with time zone", "time without time zone",
|
||||||
"timestamp", "datetime": // MySQL
|
"timestamp", "datetime", "time": // MySQL
|
||||||
return "time.Time"
|
return "time.Time"
|
||||||
case "bytea",
|
case "bytea",
|
||||||
"binary", "varbinary", "tinyblob", "blob", "mediumblob", "longblob": //MySQL
|
"binary", "varbinary", "tinyblob", "blob", "mediumblob", "longblob": //MySQL
|
||||||
|
|
|
||||||
|
|
@ -11,25 +11,25 @@ func TestBoolExpressionEQ(t *testing.T) {
|
||||||
|
|
||||||
func TestBoolExpressionNOT_EQ(t *testing.T) {
|
func TestBoolExpressionNOT_EQ(t *testing.T) {
|
||||||
assertClauseSerialize(t, table1ColBool.NOT_EQ(table2ColBool), "(table1.col_bool != table2.col_bool)")
|
assertClauseSerialize(t, table1ColBool.NOT_EQ(table2ColBool), "(table1.col_bool != table2.col_bool)")
|
||||||
assertClauseSerialize(t, table1ColBool.NOT_EQ(Bool(true)), "(table1.col_bool != TRUE)")
|
assertClauseSerialize(t, table1ColBool.NOT_EQ(Bool(true)), "(table1.col_bool != $1)", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBoolExpressionIS_DISTINCT_FROM(t *testing.T) {
|
func TestBoolExpressionIS_DISTINCT_FROM(t *testing.T) {
|
||||||
assertClauseSerialize(t, table1ColBool.IS_DISTINCT_FROM(table2ColBool), "(table1.col_bool IS DISTINCT FROM table2.col_bool)")
|
assertClauseSerialize(t, table1ColBool.IS_DISTINCT_FROM(table2ColBool), "(table1.col_bool IS DISTINCT FROM table2.col_bool)")
|
||||||
assertClauseSerialize(t, table1ColBool.IS_DISTINCT_FROM(Bool(false)), "(table1.col_bool IS DISTINCT FROM FALSE)")
|
assertClauseSerialize(t, table1ColBool.IS_DISTINCT_FROM(Bool(false)), "(table1.col_bool IS DISTINCT FROM $1)", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBoolExpressionIS_NOT_DISTINCT_FROM(t *testing.T) {
|
func TestBoolExpressionIS_NOT_DISTINCT_FROM(t *testing.T) {
|
||||||
assertClauseSerialize(t, table1ColBool.IS_NOT_DISTINCT_FROM(table2ColBool), "(table1.col_bool IS NOT DISTINCT FROM table2.col_bool)")
|
assertClauseSerialize(t, table1ColBool.IS_NOT_DISTINCT_FROM(table2ColBool), "(table1.col_bool IS NOT DISTINCT FROM table2.col_bool)")
|
||||||
assertClauseSerialize(t, table1ColBool.IS_NOT_DISTINCT_FROM(Bool(false)), "(table1.col_bool IS NOT DISTINCT FROM FALSE)")
|
assertClauseSerialize(t, table1ColBool.IS_NOT_DISTINCT_FROM(Bool(false)), "(table1.col_bool IS NOT DISTINCT FROM $1)", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBoolExpressionIS_TRUE(t *testing.T) {
|
func TestBoolExpressionIS_TRUE(t *testing.T) {
|
||||||
assertClauseSerialize(t, table1ColBool.IS_TRUE(), "table1.col_bool IS TRUE")
|
assertClauseSerialize(t, table1ColBool.IS_TRUE(), "table1.col_bool IS TRUE")
|
||||||
assertClauseSerialize(t, (Int(2).EQ(table1ColInt)).IS_TRUE(),
|
assertClauseSerialize(t, (Int(2).EQ(table1ColInt)).IS_TRUE(),
|
||||||
`(2 = table1.col_int) IS TRUE`)
|
`($1 = table1.col_int) IS TRUE`, int64(2))
|
||||||
assertClauseSerialize(t, (Int(2).EQ(table1ColInt)).IS_TRUE().AND(Int(4).EQ(table2ColInt)),
|
assertClauseSerialize(t, (Int(2).EQ(table1ColInt)).IS_TRUE().AND(Int(4).EQ(table2ColInt)),
|
||||||
`((2 = table1.col_int) IS TRUE AND (4 = table2.col_int))`)
|
`(($1 = table1.col_int) IS TRUE AND ($2 = table2.col_int))`, int64(2), int64(4))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBoolExpressionIS_NOT_TRUE(t *testing.T) {
|
func TestBoolExpressionIS_NOT_TRUE(t *testing.T) {
|
||||||
|
|
@ -55,20 +55,20 @@ func TestBoolExpressionIS_NOT_UNKNOWN(t *testing.T) {
|
||||||
func TestBinaryBoolExpression(t *testing.T) {
|
func TestBinaryBoolExpression(t *testing.T) {
|
||||||
boolExpression := Int(2).EQ(Int(3))
|
boolExpression := Int(2).EQ(Int(3))
|
||||||
|
|
||||||
assertClauseSerialize(t, boolExpression, "(2 = 3)")
|
assertClauseSerialize(t, boolExpression, "($1 = $2)", int64(2), int64(3))
|
||||||
|
|
||||||
assertProjectionSerialize(t, boolExpression, "2 = 3")
|
assertProjectionSerialize(t, boolExpression, "$1 = $2", int64(2), int64(3))
|
||||||
assertProjectionSerialize(t, boolExpression.AS("alias_eq_expression"),
|
assertProjectionSerialize(t, boolExpression.AS("alias_eq_expression"),
|
||||||
`(2 = 3) AS "alias_eq_expression"`)
|
`($1 = $2) AS "alias_eq_expression"`, int64(2), int64(3))
|
||||||
assertClauseSerialize(t, boolExpression.AND(Int(4).EQ(Int(5))),
|
assertClauseSerialize(t, boolExpression.AND(Int(4).EQ(Int(5))),
|
||||||
"((2 = 3) AND (4 = 5))")
|
"(($1 = $2) AND ($3 = $4))", int64(2), int64(3), int64(4), int64(5))
|
||||||
assertClauseSerialize(t, boolExpression.OR(Int(4).EQ(Int(5))),
|
assertClauseSerialize(t, boolExpression.OR(Int(4).EQ(Int(5))),
|
||||||
"((2 = 3) OR (4 = 5))")
|
"(($1 = $2) OR ($3 = $4))", int64(2), int64(3), int64(4), int64(5))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBoolLiteral(t *testing.T) {
|
func TestBoolLiteral(t *testing.T) {
|
||||||
assertClauseSerialize(t, Bool(true), "TRUE", true)
|
assertClauseSerialize(t, Bool(true), "$1", true)
|
||||||
assertClauseSerialize(t, Bool(false), "FALSE", false)
|
assertClauseSerialize(t, Bool(false), "$1", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExists(t *testing.T) {
|
func TestExists(t *testing.T) {
|
||||||
|
|
@ -78,13 +78,13 @@ func TestExists(t *testing.T) {
|
||||||
WHERE(table1Col1.EQ(table2Col3)),
|
WHERE(table1Col1.EQ(table2Col3)),
|
||||||
),
|
),
|
||||||
`(EXISTS (
|
`(EXISTS (
|
||||||
SELECT 1
|
SELECT $1
|
||||||
FROM db.table2
|
FROM db.table2
|
||||||
WHERE table1.col1 = table2.col3
|
WHERE table1.col1 = table2.col3
|
||||||
))`)
|
))`, int64(1))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBoolExp(t *testing.T) {
|
func TestBoolExp(t *testing.T) {
|
||||||
assertClauseSerialize(t, BoolExp(String("true")), "'true'")
|
assertClauseSerialize(t, BoolExp(String("true")), "$1", "true")
|
||||||
assertClauseSerialize(t, BoolExp(String("true")).IS_TRUE(), "'true' IS TRUE")
|
assertClauseSerialize(t, BoolExp(String("true")).IS_TRUE(), "$1 IS TRUE", "true")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ func TestArgToString(t *testing.T) {
|
||||||
assert.Equal(t, argToString(uint(32)), "32")
|
assert.Equal(t, argToString(uint(32)), "32")
|
||||||
assert.Equal(t, argToString(uint32(32)), "32")
|
assert.Equal(t, argToString(uint32(32)), "32")
|
||||||
assert.Equal(t, argToString(uint64(64)), "64")
|
assert.Equal(t, argToString(uint64(64)), "64")
|
||||||
|
assert.Equal(t, argToString(float64(1.11)), "1.11")
|
||||||
|
|
||||||
assert.Equal(t, argToString("john"), "'john'")
|
assert.Equal(t, argToString("john"), "'john'")
|
||||||
assert.Equal(t, argToString([]byte("john")), "'john'")
|
assert.Equal(t, argToString([]byte("john")), "'john'")
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,17 @@
|
||||||
package jet
|
package jet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
var ANSII = NewDialect(DialectParams{ // just for tests
|
var ANSII = NewDialect(DialectParams{ // just for tests
|
||||||
AliasQuoteChar: '"',
|
AliasQuoteChar: '"',
|
||||||
|
IdentifierQuoteChar: '"',
|
||||||
ArgumentPlaceholder: func(ord int) string {
|
ArgumentPlaceholder: func(ord int) string {
|
||||||
return "#"
|
return "$" + strconv.Itoa(ord)
|
||||||
},
|
},
|
||||||
|
SupportsReturning: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
type Dialect interface {
|
type Dialect interface {
|
||||||
|
|
@ -15,7 +22,7 @@ type Dialect interface {
|
||||||
AliasQuoteChar() byte
|
AliasQuoteChar() byte
|
||||||
IdentifierQuoteChar() byte
|
IdentifierQuoteChar() byte
|
||||||
ArgumentPlaceholder() QueryPlaceholderFunc
|
ArgumentPlaceholder() QueryPlaceholderFunc
|
||||||
UpdateAssigment() func(columns []IColumn, values []Clause, out *SqlBuilder) (err error)
|
SetClause() func(columns []IColumn, values []Clause, out *SqlBuilder) (err error)
|
||||||
SupportsReturning() bool
|
SupportsReturning() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,7 +42,7 @@ type DialectParams struct {
|
||||||
AliasQuoteChar byte
|
AliasQuoteChar byte
|
||||||
IdentifierQuoteChar byte
|
IdentifierQuoteChar byte
|
||||||
ArgumentPlaceholder QueryPlaceholderFunc
|
ArgumentPlaceholder QueryPlaceholderFunc
|
||||||
UpdateAssigment func(columns []IColumn, values []Clause, out *SqlBuilder) (err error)
|
SetClause func(columns []IColumn, values []Clause, out *SqlBuilder) (err error)
|
||||||
|
|
||||||
SupportsReturning bool
|
SupportsReturning bool
|
||||||
}
|
}
|
||||||
|
|
@ -49,7 +56,7 @@ func NewDialect(params DialectParams) Dialect {
|
||||||
aliasQuoteChar: params.AliasQuoteChar,
|
aliasQuoteChar: params.AliasQuoteChar,
|
||||||
identifierQuoteChar: params.IdentifierQuoteChar,
|
identifierQuoteChar: params.IdentifierQuoteChar,
|
||||||
argumentPlaceholder: params.ArgumentPlaceholder,
|
argumentPlaceholder: params.ArgumentPlaceholder,
|
||||||
updateAssigment: params.UpdateAssigment,
|
setClause: params.SetClause,
|
||||||
supportsReturning: params.SupportsReturning,
|
supportsReturning: params.SupportsReturning,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -62,7 +69,7 @@ type dialectImpl struct {
|
||||||
aliasQuoteChar byte
|
aliasQuoteChar byte
|
||||||
identifierQuoteChar byte
|
identifierQuoteChar byte
|
||||||
argumentPlaceholder QueryPlaceholderFunc
|
argumentPlaceholder QueryPlaceholderFunc
|
||||||
updateAssigment UpdateAssigmentFunc
|
setClause UpdateAssigmentFunc
|
||||||
|
|
||||||
supportsReturning bool
|
supportsReturning bool
|
||||||
}
|
}
|
||||||
|
|
@ -95,10 +102,40 @@ func (d *dialectImpl) ArgumentPlaceholder() QueryPlaceholderFunc {
|
||||||
return d.argumentPlaceholder
|
return d.argumentPlaceholder
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *dialectImpl) UpdateAssigment() func(columns []IColumn, values []Clause, out *SqlBuilder) (err error) {
|
func (d *dialectImpl) SetClause() func(columns []IColumn, values []Clause, out *SqlBuilder) (err error) {
|
||||||
return d.updateAssigment
|
if d.setClause != nil {
|
||||||
|
return d.setClause
|
||||||
|
}
|
||||||
|
return setClause
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *dialectImpl) SupportsReturning() bool {
|
func (d *dialectImpl) SupportsReturning() bool {
|
||||||
return d.supportsReturning
|
return d.supportsReturning
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setClause(columns []IColumn, values []Clause, out *SqlBuilder) (err error) {
|
||||||
|
|
||||||
|
if len(columns) != len(values) {
|
||||||
|
return errors.New("jet: mismatch in numers of columns and values")
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, column := range columns {
|
||||||
|
if i > 0 {
|
||||||
|
out.WriteString(", ")
|
||||||
|
}
|
||||||
|
|
||||||
|
if column == nil {
|
||||||
|
return errors.New("jet: nil column in columns list")
|
||||||
|
}
|
||||||
|
|
||||||
|
out.WriteString(column.Name())
|
||||||
|
|
||||||
|
out.WriteString(" = ")
|
||||||
|
|
||||||
|
if err = Serialize(values[i], UpdateStatementType, out); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -204,14 +204,13 @@ func CHR(integerExpression IntegerExpression) StringExpression {
|
||||||
return newStringFunc("CHR", integerExpression)
|
return newStringFunc("CHR", integerExpression)
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
func CONCAT(expressions ...Expression) StringExpression {
|
||||||
//func CONCAT(expressions ...Expression) StringExpression {
|
return newStringFunc("CONCAT", expressions...)
|
||||||
// return newStringFunc("CONCAT", expressions...)
|
}
|
||||||
//}
|
|
||||||
//
|
func CONCAT_WS(expressions ...Expression) StringExpression {
|
||||||
//func CONCAT_WS(expressions ...Expression) StringExpression {
|
return newStringFunc("CONCAT_WS", expressions...)
|
||||||
// return newStringFunc("CONCAT_WS", expressions...)
|
}
|
||||||
//}
|
|
||||||
|
|
||||||
// CONVERT converts string to dest_encoding. The original encoding is
|
// CONVERT converts string to dest_encoding. The original encoding is
|
||||||
// specified by src_encoding. The string must be valid in this encoding.
|
// specified by src_encoding. The string must be valid in this encoding.
|
||||||
|
|
@ -243,11 +242,11 @@ func DECODE(data StringExpression, format StringExpression) StringExpression {
|
||||||
return newStringFunc("DECODE", data, format)
|
return newStringFunc("DECODE", data, format)
|
||||||
}
|
}
|
||||||
|
|
||||||
//func FORMAT(formatStr StringExpression, formatArgs ...expressions) StringExpression {
|
func FORMAT(formatStr StringExpression, formatArgs ...Expression) StringExpression {
|
||||||
// args := []expressions{formatStr}
|
args := []Expression{formatStr}
|
||||||
// args = append(args, formatArgs...)
|
args = append(args, formatArgs...)
|
||||||
// return newStringFunc("FORMAT", args...)
|
return newStringFunc("FORMAT", args...)
|
||||||
//}
|
}
|
||||||
|
|
||||||
// INITCAP converts the first letter of each word to upper case
|
// INITCAP converts the first letter of each word to upper case
|
||||||
// and the rest to lower case. Words are sequences of alphanumeric
|
// and the rest to lower case. Words are sequences of alphanumeric
|
||||||
|
|
@ -344,6 +343,14 @@ func TO_HEX(number IntegerExpression) StringExpression {
|
||||||
return newStringFunc("TO_HEX", number)
|
return newStringFunc("TO_HEX", number)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func REGEXP_LIKE(stringExp StringExpression, pattern StringExpression, matchType ...string) BoolExpression {
|
||||||
|
if len(matchType) > 0 {
|
||||||
|
return newBoolFunc("REGEXP_LIKE", stringExp, pattern, String(matchType[0], true))
|
||||||
|
}
|
||||||
|
|
||||||
|
return newBoolFunc("REGEXP_LIKE", stringExp, pattern)
|
||||||
|
}
|
||||||
|
|
||||||
//----------Data Type Formatting Functions ----------------------//
|
//----------Data Type Formatting Functions ----------------------//
|
||||||
|
|
||||||
// TO_CHAR converts expression to string with format
|
// TO_CHAR converts expression to string with format
|
||||||
|
|
@ -425,9 +432,9 @@ func LOCALTIMESTAMP(precision ...int) TimestampExpression {
|
||||||
var timestampFunc *timestampFunc
|
var timestampFunc *timestampFunc
|
||||||
|
|
||||||
if len(precision) > 0 {
|
if len(precision) > 0 {
|
||||||
timestampFunc = newTimestampFunc("LOCALTIMESTAMP", constLiteral(precision[0]))
|
timestampFunc = NewTimestampFunc("LOCALTIMESTAMP", constLiteral(precision[0]))
|
||||||
} else {
|
} else {
|
||||||
timestampFunc = newTimestampFunc("LOCALTIMESTAMP")
|
timestampFunc = NewTimestampFunc("LOCALTIMESTAMP")
|
||||||
}
|
}
|
||||||
|
|
||||||
timestampFunc.noBrackets = true
|
timestampFunc.noBrackets = true
|
||||||
|
|
@ -506,6 +513,12 @@ func (f *funcExpressionImpl) serialize(statement StatementType, out *SqlBuilder,
|
||||||
return errors.New("jet: Function expressions is nil. ")
|
return errors.New("jet: Function expressions is nil. ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if serializeOverride := out.Dialect.SerializeOverride(f.name); serializeOverride != nil {
|
||||||
|
|
||||||
|
serializeOverrideFunc := serializeOverride(f.expressions...)
|
||||||
|
return serializeOverrideFunc(statement, out, options...)
|
||||||
|
}
|
||||||
|
|
||||||
addBrackets := !f.noBrackets || len(f.expressions) > 0
|
addBrackets := !f.noBrackets || len(f.expressions) > 0
|
||||||
|
|
||||||
if addBrackets {
|
if addBrackets {
|
||||||
|
|
@ -629,7 +642,7 @@ type timestampFunc struct {
|
||||||
timestampInterfaceImpl
|
timestampInterfaceImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTimestampFunc(name string, expressions ...Expression) *timestampFunc {
|
func NewTimestampFunc(name string, expressions ...Expression) *timestampFunc {
|
||||||
timestampFunc := ×tampFunc{}
|
timestampFunc := ×tampFunc{}
|
||||||
|
|
||||||
timestampFunc.funcExpressionImpl = *newFunc(name, expressions, timestampFunc)
|
timestampFunc.funcExpressionImpl = *newFunc(name, expressions, timestampFunc)
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,20 @@
|
||||||
package jet
|
package jet
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
// Representation of an escaped literal
|
// Representation of an escaped literal
|
||||||
type literalExpression struct {
|
type LiteralExpression interface {
|
||||||
|
Expression
|
||||||
|
|
||||||
|
Value() interface{}
|
||||||
|
SetConstant(constant bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
type literalExpressionImpl struct {
|
||||||
expressionInterfaceImpl
|
expressionInterfaceImpl
|
||||||
noOpVisitorImpl
|
noOpVisitorImpl
|
||||||
|
|
||||||
|
|
@ -11,8 +22,8 @@ type literalExpression struct {
|
||||||
constant bool
|
constant bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func literal(value interface{}, optionalConstant ...bool) *literalExpression {
|
func literal(value interface{}, optionalConstant ...bool) *literalExpressionImpl {
|
||||||
exp := literalExpression{value: value}
|
exp := literalExpressionImpl{value: value}
|
||||||
|
|
||||||
if len(optionalConstant) > 0 {
|
if len(optionalConstant) > 0 {
|
||||||
exp.constant = optionalConstant[0]
|
exp.constant = optionalConstant[0]
|
||||||
|
|
@ -23,14 +34,14 @@ func literal(value interface{}, optionalConstant ...bool) *literalExpression {
|
||||||
return &exp
|
return &exp
|
||||||
}
|
}
|
||||||
|
|
||||||
func constLiteral(value interface{}) *literalExpression {
|
func constLiteral(value interface{}) *literalExpressionImpl {
|
||||||
exp := literal(value)
|
exp := literal(value)
|
||||||
exp.constant = true
|
exp.constant = true
|
||||||
|
|
||||||
return exp
|
return exp
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l literalExpression) serialize(statement StatementType, out *SqlBuilder, options ...SerializeOption) error {
|
func (l *literalExpressionImpl) serialize(statement StatementType, out *SqlBuilder, options ...SerializeOption) error {
|
||||||
if l.constant {
|
if l.constant {
|
||||||
out.insertConstantArgument(l.value)
|
out.insertConstantArgument(l.value)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -40,29 +51,102 @@ func (l literalExpression) serialize(statement StatementType, out *SqlBuilder, o
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *literalExpressionImpl) Value() interface{} {
|
||||||
|
return l.value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *literalExpressionImpl) SetConstant(constant bool) {
|
||||||
|
l.constant = constant
|
||||||
|
}
|
||||||
|
|
||||||
|
type integerLiteralExpression struct {
|
||||||
|
literalExpressionImpl
|
||||||
|
integerInterfaceImpl
|
||||||
|
}
|
||||||
|
|
||||||
// Int is constructor for integer expressions literals.
|
// Int is constructor for integer expressions literals.
|
||||||
func Int(value int64, constant ...bool) IntegerExpression {
|
func Int(value int64, constant ...bool) IntegerExpression {
|
||||||
return IntExp(literal(value, constant...))
|
numLiteral := &integerLiteralExpression{}
|
||||||
|
|
||||||
|
numLiteral.literalExpressionImpl = *literal(value)
|
||||||
|
if len(constant) > 0 && constant[0] == true {
|
||||||
|
numLiteral.constant = true
|
||||||
|
}
|
||||||
|
|
||||||
|
numLiteral.literalExpressionImpl.parent = numLiteral
|
||||||
|
numLiteral.integerInterfaceImpl.parent = numLiteral
|
||||||
|
|
||||||
|
return numLiteral
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------//
|
||||||
|
type boolLiteralExpression struct {
|
||||||
|
boolInterfaceImpl
|
||||||
|
literalExpressionImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bool creates new bool literal expression
|
// Bool creates new bool literal expression
|
||||||
func Bool(value bool) BoolExpression {
|
func Bool(value bool) BoolExpression {
|
||||||
return BoolExp(literal(value))
|
boolLiteralExpression := boolLiteralExpression{}
|
||||||
|
|
||||||
|
boolLiteralExpression.literalExpressionImpl = *literal(value)
|
||||||
|
boolLiteralExpression.boolInterfaceImpl.parent = &boolLiteralExpression
|
||||||
|
|
||||||
|
return &boolLiteralExpression
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------//
|
||||||
|
type floatLiteral struct {
|
||||||
|
floatInterfaceImpl
|
||||||
|
literalExpressionImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
// Float creates new float literal expression
|
// Float creates new float literal expression
|
||||||
func Float(value float64) FloatExpression {
|
func Float(value float64) FloatExpression {
|
||||||
return FloatExp(literal(value))
|
floatLiteral := floatLiteral{}
|
||||||
|
floatLiteral.literalExpressionImpl = *literal(value)
|
||||||
|
|
||||||
|
floatLiteral.floatInterfaceImpl.parent = &floatLiteral
|
||||||
|
|
||||||
|
return &floatLiteral
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------//
|
||||||
|
type stringLiteral struct {
|
||||||
|
stringInterfaceImpl
|
||||||
|
literalExpressionImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
// String creates new string literal expression
|
// String creates new string literal expression
|
||||||
func String(value string) StringExpression {
|
func String(value string, constant ...bool) StringExpression {
|
||||||
return StringExp(literal(value))
|
stringLiteral := stringLiteral{}
|
||||||
|
stringLiteral.literalExpressionImpl = *literal(value)
|
||||||
|
if len(constant) > 0 && constant[0] == true {
|
||||||
|
stringLiteral.constant = true
|
||||||
|
}
|
||||||
|
|
||||||
|
stringLiteral.stringInterfaceImpl.parent = &stringLiteral
|
||||||
|
|
||||||
|
return &stringLiteral
|
||||||
|
}
|
||||||
|
|
||||||
|
func formatMilliseconds(milliseconds ...int) string {
|
||||||
|
if len(milliseconds) > 0 {
|
||||||
|
if milliseconds[0] < 1000 {
|
||||||
|
return fmt.Sprintf(".%03d", milliseconds[0])
|
||||||
|
} else {
|
||||||
|
return "." + strconv.Itoa(milliseconds[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Time creates new time literal expression
|
// Time creates new time literal expression
|
||||||
func Time(hour, minute, second, milliseconds int) TimeExpression {
|
func Time(hour, minute, second int, milliseconds ...int) TimeExpression {
|
||||||
timeStr := fmt.Sprintf("%02d:%02d:%02d.%03d", hour, minute, second, milliseconds)
|
timeStr := fmt.Sprintf("%02d:%02d:%02d", hour, minute, second)
|
||||||
|
|
||||||
|
timeStr += formatMilliseconds(milliseconds...)
|
||||||
|
|
||||||
return TimeExp(literal(timeStr))
|
return TimeExp(literal(timeStr))
|
||||||
}
|
}
|
||||||
|
|
@ -75,8 +159,10 @@ func Timez(hour, minute, second, milliseconds, timezone int) TimezExpression {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timestamp creates new timestamp literal expression
|
// Timestamp creates new timestamp literal expression
|
||||||
func Timestamp(year, month, day, hour, minute, second, milliseconds int) TimestampExpression {
|
func Timestamp(year int, month time.Month, day, hour, minute, second int, milliseconds ...int) TimestampExpression {
|
||||||
timeStr := fmt.Sprintf("%04d-%02d-%02d %02d:%02d:%02d.%03d", year, month, day, hour, minute, second, milliseconds)
|
timeStr := fmt.Sprintf("%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second)
|
||||||
|
|
||||||
|
timeStr += formatMilliseconds(milliseconds...)
|
||||||
|
|
||||||
return TimestampExp(literal(timeStr))
|
return TimestampExp(literal(timeStr))
|
||||||
}
|
}
|
||||||
|
|
@ -90,7 +176,7 @@ func Timestampz(year, month, day, hour, minute, second, milliseconds, timezone i
|
||||||
}
|
}
|
||||||
|
|
||||||
//Date creates new date expression
|
//Date creates new date expression
|
||||||
func Date(year, month, day int) DateExpression {
|
func Date(year int, month time.Month, day int) DateExpression {
|
||||||
timeStr := fmt.Sprintf("%04d-%02d-%02d", year, month, day)
|
timeStr := fmt.Sprintf("%04d-%02d-%02d", year, month, day)
|
||||||
|
|
||||||
return DateExp(literal(timeStr))
|
return DateExp(literal(timeStr))
|
||||||
|
|
|
||||||
|
|
@ -19,16 +19,17 @@ FROM db.table2;
|
||||||
|
|
||||||
func TestSelectLiterals(t *testing.T) {
|
func TestSelectLiterals(t *testing.T) {
|
||||||
assertStatement(t, SELECT(Int(1), Float(2.2), Bool(false)).FROM(table1), `
|
assertStatement(t, SELECT(Int(1), Float(2.2), Bool(false)).FROM(table1), `
|
||||||
SELECT 1,
|
SELECT $1,
|
||||||
2.2,
|
$2,
|
||||||
FALSE
|
$3
|
||||||
FROM db.table1;
|
FROM db.table1;
|
||||||
`)
|
`, int64(1), 2.2, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSelectDistinct(t *testing.T) {
|
func TestSelectDistinct(t *testing.T) {
|
||||||
assertStatement(t, SELECT(table1ColBool).DISTINCT(), `
|
assertStatement(t, SELECT(table1ColBool).DISTINCT().FROM(table1), `
|
||||||
SELECT DISTINCT table1.col_bool AS "table1.col_bool";
|
SELECT DISTINCT table1.col_bool AS "table1.col_bool"
|
||||||
|
FROM db.table1;
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
package jet
|
package jet
|
||||||
|
|
||||||
|
const (
|
||||||
|
StringConcatOperator = "||"
|
||||||
|
)
|
||||||
|
|
||||||
// StringExpression interface
|
// StringExpression interface
|
||||||
type StringExpression interface {
|
type StringExpression interface {
|
||||||
Expression
|
Expression
|
||||||
|
|
@ -18,8 +22,8 @@ type StringExpression interface {
|
||||||
|
|
||||||
LIKE(pattern StringExpression) BoolExpression
|
LIKE(pattern StringExpression) BoolExpression
|
||||||
NOT_LIKE(pattern StringExpression) BoolExpression
|
NOT_LIKE(pattern StringExpression) BoolExpression
|
||||||
SIMILAR_TO(pattern StringExpression) BoolExpression
|
|
||||||
NOT_SIMILAR_TO(pattern StringExpression) BoolExpression
|
REGEXP_LIKE(pattern StringExpression, matchType ...string) BoolExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
type stringInterfaceImpl struct {
|
type stringInterfaceImpl struct {
|
||||||
|
|
@ -59,7 +63,7 @@ func (s *stringInterfaceImpl) LT_EQ(rhs StringExpression) BoolExpression {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stringInterfaceImpl) CONCAT(rhs Expression) StringExpression {
|
func (s *stringInterfaceImpl) CONCAT(rhs Expression) StringExpression {
|
||||||
return newBinaryStringExpression(s.parent, rhs, "||")
|
return newBinaryStringExpression(s.parent, rhs, StringConcatOperator)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stringInterfaceImpl) LIKE(pattern StringExpression) BoolExpression {
|
func (s *stringInterfaceImpl) LIKE(pattern StringExpression) BoolExpression {
|
||||||
|
|
@ -70,12 +74,8 @@ func (s *stringInterfaceImpl) NOT_LIKE(pattern StringExpression) BoolExpression
|
||||||
return newBinaryBoolOperator(s.parent, pattern, "NOT LIKE")
|
return newBinaryBoolOperator(s.parent, pattern, "NOT LIKE")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stringInterfaceImpl) SIMILAR_TO(pattern StringExpression) BoolExpression {
|
func (s *stringInterfaceImpl) REGEXP_LIKE(pattern StringExpression, matchType ...string) BoolExpression {
|
||||||
return newBinaryBoolOperator(s.parent, pattern, "SIMILAR TO")
|
return REGEXP_LIKE(s.parent, pattern, matchType...)
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stringInterfaceImpl) NOT_SIMILAR_TO(pattern StringExpression) BoolExpression {
|
|
||||||
return newBinaryBoolOperator(s.parent, pattern, "NOT SIMILAR TO")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------//
|
//---------------------------------------------------//
|
||||||
|
|
|
||||||
|
|
@ -66,14 +66,9 @@ func TestStringNOT_LIKE(t *testing.T) {
|
||||||
assertClauseSerialize(t, table3StrCol.NOT_LIKE(String("JOHN")), "(table3.col2 NOT LIKE $1)", "JOHN")
|
assertClauseSerialize(t, table3StrCol.NOT_LIKE(String("JOHN")), "(table3.col2 NOT LIKE $1)", "JOHN")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStringSIMILAR_TO(t *testing.T) {
|
func TestStringREGEXP_LIKE(t *testing.T) {
|
||||||
assertClauseSerialize(t, table3StrCol.SIMILAR_TO(table2ColStr), "(table3.col2 SIMILAR TO table2.col_str)")
|
assertClauseSerialize(t, table3StrCol.REGEXP_LIKE(table2ColStr), "REGEXP_LIKE(table3.col2, table2.col_str)")
|
||||||
assertClauseSerialize(t, table3StrCol.SIMILAR_TO(String("JOHN")), "(table3.col2 SIMILAR TO $1)", "JOHN")
|
assertClauseSerialize(t, table3StrCol.REGEXP_LIKE(String("JOHN"), "c"), "REGEXP_LIKE(table3.col2, $1, 'c')", "JOHN")
|
||||||
}
|
|
||||||
|
|
||||||
func TestStringNOT_SIMILAR_TO(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table3StrCol.NOT_SIMILAR_TO(table2ColStr), "(table3.col2 NOT SIMILAR TO table2.col_str)")
|
|
||||||
assertClauseSerialize(t, table3StrCol.NOT_SIMILAR_TO(String("JOHN")), "(table3.col2 NOT SIMILAR TO $1)", "JOHN")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStringExp(t *testing.T) {
|
func TestStringExp(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -79,12 +79,8 @@ func assertClauseSerialize(t *testing.T, clause Clause, query string, args ...in
|
||||||
|
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
assert.DeepEqual(t, out.DebugSQL(), query)
|
assert.DeepEqual(t, out.Buff.String(), query)
|
||||||
|
assert.DeepEqual(t, out.Args, args)
|
||||||
if len(args) > 0 {
|
|
||||||
assert.DeepEqual(t, out.Args, args)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertClauseSerializeErr(t *testing.T, clause Clause, errString string) {
|
func assertClauseSerializeErr(t *testing.T, clause Clause, errString string) {
|
||||||
|
|
@ -102,22 +98,19 @@ func assertProjectionSerialize(t *testing.T, projection Projection, query string
|
||||||
|
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
assert.DeepEqual(t, out.DebugSQL(), query)
|
assert.DeepEqual(t, out.Buff.String(), query)
|
||||||
|
assert.DeepEqual(t, out.Args, args)
|
||||||
if len(args) > 0 {
|
|
||||||
assert.DeepEqual(t, out.Args, args)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertStatement(t *testing.T, query Statement, expectedQuery string, expectedArgs ...interface{}) {
|
func assertStatement(t *testing.T, query Statement, expectedQuery string, expectedArgs ...interface{}) {
|
||||||
queryStr, err := query.DebugSql()
|
queryStr, args, err := query.Sql()
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
fmt.Println(queryStr)
|
fmt.Println(queryStr)
|
||||||
|
|
||||||
//fmt.Println(queryStr)
|
//fmt.Println(queryStr)
|
||||||
assert.Equal(t, queryStr, expectedQuery)
|
assert.Equal(t, queryStr, expectedQuery)
|
||||||
//assert.DeepEqual(t, args, expectedArgs)
|
assert.DeepEqual(t, args, expectedArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertStatementErr(t *testing.T, stmt Statement, errorStr string) {
|
func assertStatementErr(t *testing.T, stmt Statement, errorStr string) {
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ func (u *updateStatementImpl) Sql(dialect ...Dialect) (query string, args []inte
|
||||||
out.newLine()
|
out.newLine()
|
||||||
out.WriteString("SET")
|
out.WriteString("SET")
|
||||||
|
|
||||||
if err = out.Dialect.UpdateAssigment()(u.columns, u.values, out); err != nil {
|
if err = out.Dialect.SetClause()(u.columns, u.values, out); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ WHERE table1.col_int >= $2;
|
||||||
func TestUpdateWithValues(t *testing.T) {
|
func TestUpdateWithValues(t *testing.T) {
|
||||||
expectedSQL := `
|
expectedSQL := `
|
||||||
UPDATE db.table1
|
UPDATE db.table1
|
||||||
SET (col_int, col_float) = ($1, $2)
|
SET col_int = $1, col_float = $2
|
||||||
WHERE table1.col_int >= $3;
|
WHERE table1.col_int >= $3;
|
||||||
`
|
`
|
||||||
stmt := table1.UPDATE(table1ColInt, table1ColFloat).
|
stmt := table1.UPDATE(table1ColInt, table1ColFloat).
|
||||||
|
|
@ -51,26 +51,7 @@ RETURNING table1.col1 AS "table1.col1";
|
||||||
assertStatement(t, stmt, expectedSQL, int64(2))
|
assertStatement(t, stmt, expectedSQL, int64(2))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateColumnsWithSelect(t *testing.T) {
|
|
||||||
expectedSQL := `
|
|
||||||
UPDATE db.table1
|
|
||||||
SET (col1, col_float) = (
|
|
||||||
SELECT table1.col_float AS "table1.col_float",
|
|
||||||
table2.col3 AS "table2.col3"
|
|
||||||
FROM db.table1
|
|
||||||
)
|
|
||||||
WHERE table1.col1 = $1
|
|
||||||
RETURNING table1.col1 AS "table1.col1";
|
|
||||||
`
|
|
||||||
stmt := table1.UPDATE(table1Col1, table1ColFloat).
|
|
||||||
SET(table1.SELECT(table1ColFloat, table2Col3)).
|
|
||||||
WHERE(table1Col1.EQ(Int(2))).
|
|
||||||
RETURNING(table1Col1)
|
|
||||||
|
|
||||||
assertStatement(t, stmt, expectedSQL, int64(2))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInvalidInputs(t *testing.T) {
|
func TestInvalidInputs(t *testing.T) {
|
||||||
assertStatementErr(t, table1.UPDATE(table1ColInt).SET(1, 2), "jet: WHERE clause not set")
|
assertStatementErr(t, table1.UPDATE(table1ColInt).SET(1), "jet: WHERE clause not set")
|
||||||
assertStatementErr(t, table1.UPDATE(nil).SET(1, 2), "jet: nil column in columns list")
|
assertStatementErr(t, table1.UPDATE(nil).SET(1), "jet: nil column in columns list")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,11 +84,14 @@ func AssertDebugStatementSql(t *testing.T, query jet.Statement, expectedQuery st
|
||||||
_, args, err := query.Sql()
|
_, args, err := query.Sql()
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
//assert.Equal(t, queryStr, expectedQuery)
|
//assert.Equal(t, queryStr, expectedQuery)
|
||||||
assert.DeepEqual(t, args, expectedArgs)
|
if len(expectedArgs) > 0 {
|
||||||
|
assert.DeepEqual(t, args, expectedArgs)
|
||||||
|
}
|
||||||
|
|
||||||
debuqSql, err := query.DebugSql()
|
debuqSql, err := query.DebugSql()
|
||||||
|
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, debuqSql, expectedQuery)
|
assert.Equal(t, debuqSql, expectedQuery)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
package mysql
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestBoolExpressionEQ(t *testing.T) {
|
|
||||||
assertClauseSerializeErr(t, table1ColBool.EQ(nil), "jet: nil rhs")
|
|
||||||
|
|
||||||
assertClauseSerialize(t, table1ColBool.EQ(table2ColBool), "(table1.col_bool = table2.col_bool)")
|
|
||||||
assertClauseSerialize(t, table1ColBool.EQ(Bool(true)), "(table1.col_bool = ?)", true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBoolExpressionNOT_EQ(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColBool.NOT_EQ(table2ColBool), "(table1.col_bool != table2.col_bool)")
|
|
||||||
assertClauseSerialize(t, table1ColBool.NOT_EQ(Bool(true)), "(table1.col_bool != ?)", true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBoolExpressionIS_DISTINCT_FROM(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColBool.IS_DISTINCT_FROM(table2ColBool), "(NOT table1.col_bool <=> table2.col_bool)")
|
|
||||||
assertClauseSerialize(t, table1ColBool.IS_DISTINCT_FROM(Bool(false)), "(NOT table1.col_bool <=> ?)", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBoolExpressionIS_NOT_DISTINCT_FROM(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColBool.IS_NOT_DISTINCT_FROM(table2ColBool), "(table1.col_bool <=> table2.col_bool)")
|
|
||||||
assertClauseSerialize(t, table1ColBool.IS_NOT_DISTINCT_FROM(Bool(false)), "(table1.col_bool <=> ?)", false)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBoolExpressionIS_TRUE(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColBool.IS_TRUE(), "table1.col_bool IS TRUE")
|
|
||||||
assertClauseSerialize(t, (Int(2).EQ(table1ColInt)).IS_TRUE(),
|
|
||||||
`(? = table1.col_int) IS TRUE`, int64(2))
|
|
||||||
assertClauseSerialize(t, (Int(2).EQ(table1ColInt)).IS_TRUE().AND(Int(4).EQ(table2ColInt)),
|
|
||||||
`((? = table1.col_int) IS TRUE AND (? = table2.col_int))`, int64(2), int64(4))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBoolExpressionIS_NOT_TRUE(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColBool.IS_NOT_TRUE(), "table1.col_bool IS NOT TRUE")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBoolExpressionIS_FALSE(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColBool.IS_FALSE(), "table1.col_bool IS FALSE")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBoolExpressionIS_NOT_FALSE(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColBool.IS_NOT_FALSE(), "table1.col_bool IS NOT FALSE")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBoolExpressionIS_UNKNOWN(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColBool.IS_UNKNOWN(), "table1.col_bool IS UNKNOWN")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBoolExpressionIS_NOT_UNKNOWN(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColBool.IS_NOT_UNKNOWN(), "table1.col_bool IS NOT UNKNOWN")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBinaryBoolExpressionAsProjection(t *testing.T) {
|
|
||||||
boolExpression := Int(2).EQ(Int(3))
|
|
||||||
|
|
||||||
assertProjectionSerialize(t, boolExpression, "? = ?", int64(2), int64(3))
|
|
||||||
assertProjectionSerialize(t, boolExpression.AS("alias_eq_expression"),
|
|
||||||
`(? = ?) AS "alias_eq_expression"`, int64(2), int64(3))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBoolLiteral(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, Bool(true), "?", true)
|
|
||||||
assertClauseSerialize(t, Bool(false), "?", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
//func TestExists(t *testing.T) {
|
|
||||||
//
|
|
||||||
// assertClauseSerialize(t, EXISTS(
|
|
||||||
// table2.
|
|
||||||
// SELECT(Int(1)).
|
|
||||||
// WHERE(table1Col1.EQ(table2Col3)),
|
|
||||||
// ),
|
|
||||||
// `(EXISTS (
|
|
||||||
// SELECT ?
|
|
||||||
// FROM db.table2
|
|
||||||
// WHERE table1.col1 = table2.col3
|
|
||||||
//))`, int64(1))
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//func TestBoolExp(t *testing.T) {
|
|
||||||
// assertClauseSerialize(t, BoolExp(String("true")), "?", "true")
|
|
||||||
// assertClauseSerialize(t, BoolExp(String("true")).IS_TRUE(), "? IS TRUE", "true")
|
|
||||||
//}
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
package mysql
|
|
||||||
|
|
||||||
import "github.com/go-jet/jet/internal/jet"
|
|
||||||
|
|
||||||
type Column jet.Column
|
|
||||||
|
|
||||||
type IColumnList jet.IColumnList
|
|
||||||
|
|
||||||
var ColumnList = jet.ColumnList
|
|
||||||
41
mysql/columns.go
Normal file
41
mysql/columns.go
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
package mysql
|
||||||
|
|
||||||
|
import "github.com/go-jet/jet/internal/jet"
|
||||||
|
|
||||||
|
type Column jet.Column
|
||||||
|
|
||||||
|
type IColumnList jet.IColumnList
|
||||||
|
|
||||||
|
var ColumnList = jet.ColumnList
|
||||||
|
|
||||||
|
type ColumnBool jet.ColumnBool
|
||||||
|
|
||||||
|
var BoolColumn = jet.BoolColumn
|
||||||
|
|
||||||
|
type ColumnString jet.ColumnString
|
||||||
|
|
||||||
|
var StringColumn = jet.StringColumn
|
||||||
|
|
||||||
|
type ColumnInteger jet.ColumnInteger
|
||||||
|
|
||||||
|
var IntegerColumn = jet.IntegerColumn
|
||||||
|
|
||||||
|
type ColumnFloat jet.ColumnFloat
|
||||||
|
|
||||||
|
var FloatColumn = jet.FloatColumn
|
||||||
|
|
||||||
|
type ColumnTime jet.ColumnTime
|
||||||
|
|
||||||
|
var TimeColumn = jet.TimeColumn
|
||||||
|
|
||||||
|
type ColumnDate jet.ColumnDate
|
||||||
|
|
||||||
|
var DateColumn = jet.DateColumn
|
||||||
|
|
||||||
|
type ColumnDateTime jet.ColumnTimestamp
|
||||||
|
|
||||||
|
var DateTimeColumn = jet.TimestampColumn
|
||||||
|
|
||||||
|
type ColumnTimestamp jet.ColumnTimestamp
|
||||||
|
|
||||||
|
var TimestampColumn = jet.TimestampColumn
|
||||||
|
|
@ -14,6 +14,7 @@ func NewDialect() jet.Dialect {
|
||||||
serializeOverrides["IS NOT DISTINCT FROM"] = mysql_IS_NOT_DISTINCT_FROM
|
serializeOverrides["IS NOT DISTINCT FROM"] = mysql_IS_NOT_DISTINCT_FROM
|
||||||
serializeOverrides["/"] = mysql_DIVISION
|
serializeOverrides["/"] = mysql_DIVISION
|
||||||
serializeOverrides["#"] = mysql_BIT_XOR
|
serializeOverrides["#"] = mysql_BIT_XOR
|
||||||
|
serializeOverrides[jet.StringConcatOperator] = mysql_CONCAT_operator
|
||||||
|
|
||||||
mySQLDialectParams := jet.DialectParams{
|
mySQLDialectParams := jet.DialectParams{
|
||||||
Name: "MySQL",
|
Name: "MySQL",
|
||||||
|
|
@ -24,36 +25,12 @@ func NewDialect() jet.Dialect {
|
||||||
ArgumentPlaceholder: func(int) string {
|
ArgumentPlaceholder: func(int) string {
|
||||||
return "?"
|
return "?"
|
||||||
},
|
},
|
||||||
UpdateAssigment: mysqlUpdateAssigment,
|
|
||||||
SupportsReturning: false,
|
SupportsReturning: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
return jet.NewDialect(mySQLDialectParams)
|
return jet.NewDialect(mySQLDialectParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
func mysqlUpdateAssigment(columns []jet.IColumn, values []jet.Clause, out *jet.SqlBuilder) (err error) {
|
|
||||||
|
|
||||||
if len(columns) != len(values) {
|
|
||||||
return errors.New("jet: mismatch in numers of columns and values")
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, column := range columns {
|
|
||||||
if i > 0 {
|
|
||||||
out.WriteString(", ")
|
|
||||||
}
|
|
||||||
|
|
||||||
out.WriteString(column.Name())
|
|
||||||
|
|
||||||
out.WriteString(" = ")
|
|
||||||
|
|
||||||
if err = jet.Serialize(values[i], jet.UpdateStatementType, out); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func mysql_BIT_XOR(expressions ...jet.Expression) jet.SerializeFunc {
|
func mysql_BIT_XOR(expressions ...jet.Expression) jet.SerializeFunc {
|
||||||
return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) error {
|
return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) error {
|
||||||
if len(expressions) != 2 {
|
if len(expressions) != 2 {
|
||||||
|
|
@ -76,6 +53,30 @@ func mysql_BIT_XOR(expressions ...jet.Expression) jet.SerializeFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mysql_CONCAT_operator(expressions ...jet.Expression) jet.SerializeFunc {
|
||||||
|
return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) error {
|
||||||
|
if len(expressions) != 2 {
|
||||||
|
return errors.New("jet: invalid number of expressions for operator")
|
||||||
|
}
|
||||||
|
|
||||||
|
out.WriteString("CONCAT(")
|
||||||
|
|
||||||
|
if err := jet.Serialize(expressions[0], statement, out, options...); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
out.WriteString(", ")
|
||||||
|
|
||||||
|
if err := jet.Serialize(expressions[1], statement, out, options...); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
out.WriteString(")")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func mysql_DIVISION(expressions ...jet.Expression) jet.SerializeFunc {
|
func mysql_DIVISION(expressions ...jet.Expression) jet.SerializeFunc {
|
||||||
return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) error {
|
return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) error {
|
||||||
if len(expressions) != 2 {
|
if len(expressions) != 2 {
|
||||||
|
|
@ -126,7 +127,7 @@ func mysql_IS_NOT_DISTINCT_FROM(expressions ...jet.Expression) jet.SerializeFunc
|
||||||
|
|
||||||
func mysql_IS_DISTINCT_FROM(expressions ...jet.Expression) jet.SerializeFunc {
|
func mysql_IS_DISTINCT_FROM(expressions ...jet.Expression) jet.SerializeFunc {
|
||||||
return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) error {
|
return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) error {
|
||||||
out.WriteString("NOT")
|
out.WriteString("NOT(")
|
||||||
|
|
||||||
err := mysql_IS_NOT_DISTINCT_FROM(expressions...)(statement, out, options...)
|
err := mysql_IS_NOT_DISTINCT_FROM(expressions...)(statement, out, options...)
|
||||||
|
|
||||||
|
|
@ -134,6 +135,8 @@ func mysql_IS_DISTINCT_FROM(expressions ...jet.Expression) jet.SerializeFunc {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out.WriteString(")")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
35
mysql/dialect_test.go
Normal file
35
mysql/dialect_test.go
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
package mysql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBoolExpressionIS_DISTINCT_FROM(t *testing.T) {
|
||||||
|
assertClauseSerialize(t, table1ColBool.IS_DISTINCT_FROM(table2ColBool), "(NOT(table1.col_bool <=> table2.col_bool))")
|
||||||
|
assertClauseSerialize(t, table1ColBool.IS_DISTINCT_FROM(Bool(false)), "(NOT(table1.col_bool <=> ?))", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBoolExpressionIS_NOT_DISTINCT_FROM(t *testing.T) {
|
||||||
|
assertClauseSerialize(t, table1ColBool.IS_NOT_DISTINCT_FROM(table2ColBool), "(table1.col_bool <=> table2.col_bool)")
|
||||||
|
assertClauseSerialize(t, table1ColBool.IS_NOT_DISTINCT_FROM(Bool(false)), "(table1.col_bool <=> ?)", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBoolLiteral(t *testing.T) {
|
||||||
|
assertClauseSerialize(t, Bool(true), "?", true)
|
||||||
|
assertClauseSerialize(t, Bool(false), "?", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIntegerExpressionDIV(t *testing.T) {
|
||||||
|
assertClauseSerialize(t, table1ColInt.DIV(table2ColInt), "(table1.col_int DIV table2.col_int)")
|
||||||
|
assertClauseSerialize(t, table1ColInt.DIV(Int(11)), "(table1.col_int DIV ?)", int64(11))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIntExpressionPOW(t *testing.T) {
|
||||||
|
assertClauseSerialize(t, table1ColInt.POW(table2ColInt), "POW(table1.col_int, table2.col_int)")
|
||||||
|
assertClauseSerialize(t, table1ColInt.POW(Int(11)), "POW(table1.col_int, ?)", int64(11))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIntExpressionBIT_XOR(t *testing.T) {
|
||||||
|
assertClauseSerialize(t, table1ColInt.BIT_XOR(table2ColInt), "(table1.col_int ^ table2.col_int)")
|
||||||
|
assertClauseSerialize(t, table1ColInt.BIT_XOR(Int(11)), "(table1.col_int ^ ?)", int64(11))
|
||||||
|
}
|
||||||
|
|
@ -12,10 +12,21 @@ type IntegerExpression jet.IntegerExpression
|
||||||
|
|
||||||
type FloatExpression jet.FloatExpression
|
type FloatExpression jet.FloatExpression
|
||||||
|
|
||||||
|
type TimeExpression jet.TimeExpression
|
||||||
|
|
||||||
type DateExpression jet.DateExpression
|
type DateExpression jet.DateExpression
|
||||||
|
|
||||||
type DateTimeExpression jet.TimestampExpression
|
type DateTimeExpression jet.TimestampExpression
|
||||||
|
|
||||||
type TimestampExpression jet.TimestampExpression
|
type TimestampExpression jet.TimestampExpression
|
||||||
|
|
||||||
type TimeExpression jet.TimeExpression
|
var BoolExp = jet.BoolExp
|
||||||
|
var StringExp = jet.StringExp
|
||||||
|
var IntExp = jet.IntExp
|
||||||
|
var FloatExp = jet.FloatExp
|
||||||
|
var TimeExp = jet.TimeExp
|
||||||
|
var DateExp = jet.DateExp
|
||||||
|
var DateTimeExp = jet.TimestampExp
|
||||||
|
var TimestampExp = jet.TimestampExp
|
||||||
|
|
||||||
|
var RAW = jet.RAW
|
||||||
|
|
|
||||||
122
mysql/functions.go
Normal file
122
mysql/functions.go
Normal file
|
|
@ -0,0 +1,122 @@
|
||||||
|
package mysql
|
||||||
|
|
||||||
|
import "github.com/go-jet/jet/internal/jet"
|
||||||
|
|
||||||
|
// ------------------ Mathematical functions ---------------//
|
||||||
|
|
||||||
|
var POW = jet.POW
|
||||||
|
var LN = jet.LN
|
||||||
|
var LOG = jet.LOG
|
||||||
|
|
||||||
|
var ABSf = jet.ABSf
|
||||||
|
var ABSi = jet.ABSi
|
||||||
|
var POWER = jet.POWER
|
||||||
|
var SQRT = jet.SQRT
|
||||||
|
|
||||||
|
func CBRT(number jet.NumericExpression) jet.FloatExpression {
|
||||||
|
return POWER(number, Float(1.0).DIV(Float(3.0)))
|
||||||
|
}
|
||||||
|
|
||||||
|
var CEIL = jet.CEIL
|
||||||
|
var FLOOR = jet.FLOOR
|
||||||
|
var ROUND = jet.ROUND
|
||||||
|
var SIGN = jet.SIGN
|
||||||
|
var TRUNC = TRUNCATE
|
||||||
|
|
||||||
|
var TRUNCATE = func(floatExpression jet.FloatExpression, precision jet.IntegerExpression) jet.FloatExpression {
|
||||||
|
return jet.NewFloatFunc("TRUNCATE", floatExpression, precision)
|
||||||
|
}
|
||||||
|
|
||||||
|
var MINUSi = jet.MINUSi
|
||||||
|
var MINUSf = jet.MINUSf
|
||||||
|
var BIT_NOT = jet.BIT_NOT
|
||||||
|
|
||||||
|
// ----------------- Aggregate functions -------------------//
|
||||||
|
|
||||||
|
var BIT_AND = jet.BIT_AND
|
||||||
|
var BIT_OR = jet.BIT_OR
|
||||||
|
var BOOL_AND = jet.BOOL_AND
|
||||||
|
var BOOL_OR = jet.BOOL_OR
|
||||||
|
var EVERY = jet.EVERY
|
||||||
|
var MAXi = jet.MAXi
|
||||||
|
var MINi = jet.MINi
|
||||||
|
var SUMi = jet.SUMi
|
||||||
|
|
||||||
|
var SUMf = jet.SUMf
|
||||||
|
var AVG = jet.AVG
|
||||||
|
var MAXf = jet.MAXf
|
||||||
|
var MINf = jet.MINf
|
||||||
|
var COUNT = jet.COUNT
|
||||||
|
|
||||||
|
//--------------------- String functions ------------------//
|
||||||
|
|
||||||
|
var REGEXP_LIKE = jet.REGEXP_LIKE
|
||||||
|
var BIT_LENGTH = jet.BIT_LENGTH
|
||||||
|
var CHAR_LENGTH = jet.CHAR_LENGTH
|
||||||
|
var OCTET_LENGTH = jet.OCTET_LENGTH
|
||||||
|
var LOWER = jet.LOWER
|
||||||
|
var UPPER = jet.UPPER
|
||||||
|
var BTRIM = jet.BTRIM
|
||||||
|
var LTRIM = jet.LTRIM
|
||||||
|
var RTRIM = jet.RTRIM
|
||||||
|
var CHR = jet.CHR
|
||||||
|
var CONCAT = jet.CONCAT
|
||||||
|
var CONCAT_WS = jet.CONCAT_WS
|
||||||
|
var CONVERT = jet.CONVERT
|
||||||
|
var CONVERT_FROM = jet.CONVERT_FROM
|
||||||
|
var CONVERT_TO = jet.CONVERT_TO
|
||||||
|
var ENCODE = jet.ENCODE
|
||||||
|
var DECODE = jet.DECODE
|
||||||
|
var FORMAT = jet.FORMAT
|
||||||
|
var INITCAP = jet.INITCAP
|
||||||
|
var LEFT = jet.LEFT
|
||||||
|
var RIGHT = jet.RIGHT
|
||||||
|
|
||||||
|
func LENGTH(str jet.StringExpression) jet.StringExpression {
|
||||||
|
return jet.LENGTH(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LPAD(str jet.StringExpression, length jet.IntegerExpression, text jet.StringExpression) jet.StringExpression {
|
||||||
|
return jet.LPAD(str, length, text)
|
||||||
|
}
|
||||||
|
func RPAD(str jet.StringExpression, length jet.IntegerExpression, text jet.StringExpression) jet.StringExpression {
|
||||||
|
return jet.RPAD(str, length, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
var MD5 = jet.MD5
|
||||||
|
var REPEAT = jet.REPEAT
|
||||||
|
var REPLACE = jet.REPLACE
|
||||||
|
var REVERSE = jet.REVERSE
|
||||||
|
var STRPOS = jet.STRPOS
|
||||||
|
var SUBSTR = jet.SUBSTR
|
||||||
|
var TO_ASCII = jet.TO_ASCII
|
||||||
|
var TO_HEX = jet.TO_HEX
|
||||||
|
|
||||||
|
//----------Data Type Formatting Functions ----------------------//
|
||||||
|
var TO_CHAR = jet.TO_CHAR
|
||||||
|
var TO_DATE = jet.TO_DATE
|
||||||
|
var TO_NUMBER = jet.TO_NUMBER
|
||||||
|
var TO_TIMESTAMP = jet.TO_TIMESTAMP
|
||||||
|
|
||||||
|
//----------------- Date/Time Functions and Operators ------------//
|
||||||
|
|
||||||
|
var CURRENT_DATE = jet.CURRENT_DATE
|
||||||
|
var CURRENT_TIME = jet.CURRENT_TIME
|
||||||
|
var CURRENT_TIMESTAMP = jet.CURRENT_TIMESTAMP
|
||||||
|
var LOCALTIME = jet.LOCALTIME
|
||||||
|
var LOCALTIMESTAMP = jet.LOCALTIMESTAMP
|
||||||
|
|
||||||
|
func NOW(fsp ...int) DateTimeExpression {
|
||||||
|
if len(fsp) > 0 {
|
||||||
|
return jet.NewTimestampFunc("NOW", Int(int64(fsp[0]), true))
|
||||||
|
}
|
||||||
|
return jet.NewTimestampFunc("NOW")
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------- Conditional Expressions Functions -------------//
|
||||||
|
var COALESCE = jet.COALESCE
|
||||||
|
var NULLIF = jet.NULLIF
|
||||||
|
var GREATEST = jet.GREATEST
|
||||||
|
var LEAST = jet.LEAST
|
||||||
|
var EXISTS = jet.EXISTS
|
||||||
|
var CASE = jet.CASE
|
||||||
|
|
@ -1,107 +0,0 @@
|
||||||
package mysql
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestIntegerExpressionEQ(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColInt.EQ(table2ColInt), "(table1.col_int = table2.col_int)")
|
|
||||||
assertClauseSerialize(t, table1ColInt.EQ(Int(11)), "(table1.col_int = ?)", int64(11))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntegerExpressionNOT_EQ(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColInt.NOT_EQ(table2ColInt), "(table1.col_int != table2.col_int)")
|
|
||||||
assertClauseSerialize(t, table1ColInt.NOT_EQ(Int(11)), "(table1.col_int != ?)", int64(11))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntegerExpressionGT(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColInt.GT(table2ColInt), "(table1.col_int > table2.col_int)")
|
|
||||||
assertClauseSerialize(t, table1ColInt.GT(Int(11)), "(table1.col_int > ?)", int64(11))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntegerExpressionGT_EQ(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColInt.GT_EQ(table2ColInt), "(table1.col_int >= table2.col_int)")
|
|
||||||
assertClauseSerialize(t, table1ColInt.GT_EQ(Int(11)), "(table1.col_int >= ?)", int64(11))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntegerExpressionLT(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColInt.LT(table2ColInt), "(table1.col_int < table2.col_int)")
|
|
||||||
assertClauseSerialize(t, table1ColInt.LT(Int(11)), "(table1.col_int < ?)", int64(11))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntegerExpressionLT_EQ(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColInt.LT_EQ(table2ColInt), "(table1.col_int <= table2.col_int)")
|
|
||||||
assertClauseSerialize(t, table1ColInt.LT_EQ(Int(11)), "(table1.col_int <= ?)", int64(11))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntegerExpressionADD(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColInt.ADD(table2ColInt), "(table1.col_int + table2.col_int)")
|
|
||||||
assertClauseSerialize(t, table1ColInt.ADD(Int(11)), "(table1.col_int + ?)", int64(11))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntegerExpressionSUB(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColInt.SUB(table2ColInt), "(table1.col_int - table2.col_int)")
|
|
||||||
assertClauseSerialize(t, table1ColInt.SUB(Int(11)), "(table1.col_int - ?)", int64(11))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntegerExpressionMUL(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColInt.MUL(table2ColInt), "(table1.col_int * table2.col_int)")
|
|
||||||
assertClauseSerialize(t, table1ColInt.MUL(Int(11)), "(table1.col_int * ?)", int64(11))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntegerExpressionDIV(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColInt.DIV(table2ColInt), "(table1.col_int DIV table2.col_int)")
|
|
||||||
assertClauseSerialize(t, table1ColInt.DIV(Int(11)), "(table1.col_int DIV ?)", int64(11))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntExpressionMOD(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColInt.MOD(table2ColInt), "(table1.col_int % table2.col_int)")
|
|
||||||
assertClauseSerialize(t, table1ColInt.MOD(Int(11)), "(table1.col_int % ?)", int64(11))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntExpressionPOW(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColInt.POW(table2ColInt), "POW(table1.col_int, table2.col_int)")
|
|
||||||
assertClauseSerialize(t, table1ColInt.POW(Int(11)), "POW(table1.col_int, ?)", int64(11))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntExpressionBIT_NOT(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, BIT_NOT(table2ColInt), "(~ table2.col_int)")
|
|
||||||
assertClauseSerialize(t, BIT_NOT(Int(11)), "(~ ?)", int64(11))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntExpressionBIT_AND(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColInt.BIT_AND(table2ColInt), "(table1.col_int & table2.col_int)")
|
|
||||||
assertClauseSerialize(t, table1ColInt.BIT_AND(Int(11)), "(table1.col_int & ?)", int64(11))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntExpressionBIT_OR(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColInt.BIT_OR(table2ColInt), "(table1.col_int | table2.col_int)")
|
|
||||||
assertClauseSerialize(t, table1ColInt.BIT_OR(Int(11)), "(table1.col_int | ?)", int64(11))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntExpressionBIT_XOR(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColInt.BIT_XOR(table2ColInt), "(table1.col_int ^ table2.col_int)")
|
|
||||||
assertClauseSerialize(t, table1ColInt.BIT_XOR(Int(11)), "(table1.col_int ^ ?)", int64(11))
|
|
||||||
}
|
|
||||||
|
|
||||||
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(Int(11)), "(table1.col_int << ?)", int64(11))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntExpressionBIT_SHIFT_RIGHT(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColInt.BIT_SHIFT_RIGHT(table2ColInt), "(table1.col_int >> table2.col_int)")
|
|
||||||
assertClauseSerialize(t, table1ColInt.BIT_SHIFT_RIGHT(Int(11)), "(table1.col_int >> ?)", int64(11))
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
//func TestIntExpressionIntExp(t *testing.T) {
|
|
||||||
// assertClauseSerialize(t, IntExp(table1ColFloat), "table1.col_float")
|
|
||||||
// assertClauseSerialize(t, IntExp(table1ColFloat.ADD(table2ColFloat)).ADD(Int(11)),
|
|
||||||
// "((table1.col_float + table2.col_float) + ?)", int64(11))
|
|
||||||
//}
|
|
||||||
|
|
||||||
func TestIntExpression_MINUSi(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, MINUSi(table2ColInt), "(- table2.col_int)")
|
|
||||||
assertClauseSerialize(t, MINUSi(Int(3)), "(- ?)", int64(3))
|
|
||||||
}
|
|
||||||
13
mysql/literal.go
Normal file
13
mysql/literal.go
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
package mysql
|
||||||
|
|
||||||
|
import "github.com/go-jet/jet/internal/jet"
|
||||||
|
|
||||||
|
var Bool = jet.Bool
|
||||||
|
var Int = jet.Int
|
||||||
|
var Float = jet.Float
|
||||||
|
var String = jet.String
|
||||||
|
|
||||||
|
var Time = jet.Time
|
||||||
|
var Date = jet.Date
|
||||||
|
var DateTime = jet.Timestamp
|
||||||
|
var Timestamp = jet.Timestamp
|
||||||
27
mysql/statements.go
Normal file
27
mysql/statements.go
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
package mysql
|
||||||
|
|
||||||
|
import "github.com/go-jet/jet/internal/jet"
|
||||||
|
|
||||||
|
// ----------------- FUNCTIONS ----------------------//
|
||||||
|
|
||||||
|
var SELECT = jet.SELECT
|
||||||
|
|
||||||
|
type SelectLock jet.SelectLock
|
||||||
|
|
||||||
|
var (
|
||||||
|
UPDATE = jet.NewSelectLock("UPDATE")
|
||||||
|
SHARE = jet.NewSelectLock("SHARE")
|
||||||
|
)
|
||||||
|
|
||||||
|
var UNION = jet.UNION
|
||||||
|
var UNION_ALL = jet.UNION_ALL
|
||||||
|
var INTERSECT = jet.INTERSECT
|
||||||
|
var INTERSECT_ALL = jet.INTERSECT_ALL
|
||||||
|
var EXCEPT = jet.EXCEPT
|
||||||
|
var EXCEPT_ALL = jet.EXCEPT_ALL
|
||||||
|
|
||||||
|
//-----------------literals----------------------//
|
||||||
|
|
||||||
|
var STAR = jet.STAR
|
||||||
|
var NULL = jet.NULL
|
||||||
|
var DEFAULT = jet.DEFAULT
|
||||||
|
|
@ -1,86 +0,0 @@
|
||||||
package mysql
|
|
||||||
|
|
||||||
import "github.com/go-jet/jet/internal/jet"
|
|
||||||
|
|
||||||
type ColumnBool jet.ColumnBool
|
|
||||||
|
|
||||||
var BoolColumn = jet.BoolColumn
|
|
||||||
var Bool = jet.Bool
|
|
||||||
|
|
||||||
type ColumnString jet.ColumnString
|
|
||||||
|
|
||||||
var StringColumn = jet.StringColumn
|
|
||||||
var String = jet.String
|
|
||||||
|
|
||||||
type ColumnInteger jet.ColumnInteger
|
|
||||||
|
|
||||||
var IntegerColumn = jet.IntegerColumn
|
|
||||||
var Int = jet.Int
|
|
||||||
|
|
||||||
type ColumnFloat jet.ColumnFloat
|
|
||||||
|
|
||||||
var FloatColumn = jet.FloatColumn
|
|
||||||
var Float = jet.Float
|
|
||||||
|
|
||||||
type ColumnDate jet.ColumnDate
|
|
||||||
|
|
||||||
var DateColumn = jet.DateColumn
|
|
||||||
var Date = jet.Date
|
|
||||||
|
|
||||||
type ColumnDateTime jet.ColumnTimestamp
|
|
||||||
|
|
||||||
var DateTimeColumn = jet.TimestampColumn
|
|
||||||
var DateTime = jet.Timestamp
|
|
||||||
|
|
||||||
type ColumnTimestamp jet.ColumnTimestamp
|
|
||||||
|
|
||||||
var TimestampColumn = jet.TimestampColumn
|
|
||||||
var Timestamp = jet.Timestamp
|
|
||||||
|
|
||||||
// ----------------- FUNCTIONS ----------------------//
|
|
||||||
|
|
||||||
var ABSf = jet.ABSf
|
|
||||||
var ABSi = jet.ABSi
|
|
||||||
var POWER = jet.POWER
|
|
||||||
var SQRT = jet.SQRT
|
|
||||||
|
|
||||||
func CBRT(number jet.NumericExpression) jet.FloatExpression {
|
|
||||||
return POWER(number, Float(1.0).DIV(Float(3.0)))
|
|
||||||
}
|
|
||||||
|
|
||||||
var CEIL = jet.CEIL
|
|
||||||
var FLOOR = jet.FLOOR
|
|
||||||
var ROUND = jet.ROUND
|
|
||||||
var SIGN = jet.SIGN
|
|
||||||
var TRUNC = TRUNCATE
|
|
||||||
|
|
||||||
var TRUNCATE = func(floatExpression jet.FloatExpression, precision jet.IntegerExpression) jet.FloatExpression {
|
|
||||||
return jet.NewFloatFunc("TRUNCATE", floatExpression, precision)
|
|
||||||
}
|
|
||||||
|
|
||||||
var MINUSi = jet.MINUSi
|
|
||||||
var MINUSf = jet.MINUSf
|
|
||||||
var BIT_NOT = jet.BIT_NOT
|
|
||||||
|
|
||||||
var SUMf = jet.SUMf
|
|
||||||
var AVG = jet.AVG
|
|
||||||
var MAXf = jet.MAXf
|
|
||||||
var MINf = jet.MINf
|
|
||||||
var COUNT = jet.COUNT
|
|
||||||
|
|
||||||
var SELECT = jet.SELECT
|
|
||||||
|
|
||||||
type SelectLock jet.SelectLock
|
|
||||||
|
|
||||||
var (
|
|
||||||
UPDATE = jet.NewSelectLock("UPDATE")
|
|
||||||
SHARE = jet.NewSelectLock("SHARE")
|
|
||||||
)
|
|
||||||
|
|
||||||
var UNION = jet.UNION
|
|
||||||
|
|
||||||
//-----------------literals----------------------//
|
|
||||||
|
|
||||||
var STAR = jet.STAR
|
|
||||||
var NULL = jet.NULL
|
|
||||||
var DEFAULT = jet.DEFAULT
|
|
||||||
|
|
@ -9,6 +9,7 @@ type cast interface {
|
||||||
jet.Cast
|
jet.Cast
|
||||||
// Cast expression AS bool type
|
// Cast expression AS bool type
|
||||||
AS_BOOL() BoolExpression
|
AS_BOOL() BoolExpression
|
||||||
|
|
||||||
// Cast expression AS smallint type
|
// Cast expression AS smallint type
|
||||||
AS_SMALLINT() IntegerExpression
|
AS_SMALLINT() IntegerExpression
|
||||||
// Cast expression AS integer type
|
// Cast expression AS integer type
|
||||||
|
|
@ -16,7 +17,7 @@ type cast interface {
|
||||||
// Cast expression AS bigint type
|
// Cast expression AS bigint type
|
||||||
AS_BIGINT() IntegerExpression
|
AS_BIGINT() IntegerExpression
|
||||||
// Cast expression AS numeric type, using precision and optionally scale
|
// Cast expression AS numeric type, using precision and optionally scale
|
||||||
AS_NUMERIC(precision int, scale ...int) FloatExpression
|
AS_NUMERIC(precisionAndScale ...int) FloatExpression
|
||||||
|
|
||||||
// Cast expression AS real type
|
// Cast expression AS real type
|
||||||
AS_REAL() FloatExpression
|
AS_REAL() FloatExpression
|
||||||
|
|
@ -25,6 +26,8 @@ type cast interface {
|
||||||
// Cast expression AS text type
|
// Cast expression AS text type
|
||||||
AS_TEXT() StringExpression
|
AS_TEXT() StringExpression
|
||||||
|
|
||||||
|
AS_BYTEA() StringExpression
|
||||||
|
|
||||||
// Cast expression AS time with time timezone type
|
// Cast expression AS time with time timezone type
|
||||||
AS_TIMEZ() TimezExpression
|
AS_TIMEZ() TimezExpression
|
||||||
// Cast expression AS timestamp type
|
// Cast expression AS timestamp type
|
||||||
|
|
@ -64,16 +67,17 @@ func (b *castImpl) AS_BIGINT() IntegerExpression {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cast expression AS numeric type, using precision and optionally scale
|
// Cast expression AS numeric type, using precision and optionally scale
|
||||||
func (b *castImpl) AS_NUMERIC(precision int, scale ...int) FloatExpression {
|
func (b *castImpl) AS_NUMERIC(precisionAndScale ...int) FloatExpression {
|
||||||
var castType string
|
var castArgs string
|
||||||
|
|
||||||
if len(scale) > 0 {
|
var argLen = len(precisionAndScale)
|
||||||
castType = fmt.Sprintf("numeric(%d, %d)", precision, scale[0])
|
if argLen >= 2 {
|
||||||
} else {
|
castArgs = fmt.Sprintf("(%d, %d)", precisionAndScale[0], precisionAndScale[1])
|
||||||
castType = fmt.Sprintf("numeric(%d)", precision)
|
} else if argLen == 1 {
|
||||||
|
castArgs = fmt.Sprintf("(%d)", precisionAndScale[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
return jet.FloatExp(b.AS(castType))
|
return jet.FloatExp(b.AS("numeric" + castArgs))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cast expression AS real type
|
// Cast expression AS real type
|
||||||
|
|
@ -91,6 +95,11 @@ func (b *castImpl) AS_TEXT() StringExpression {
|
||||||
return jet.StringExp(b.AS("text"))
|
return jet.StringExp(b.AS("text"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cast expression AS text type
|
||||||
|
func (b *castImpl) AS_BYTEA() StringExpression {
|
||||||
|
return jet.StringExp(b.AS("bytea"))
|
||||||
|
}
|
||||||
|
|
||||||
// Cast expression AS date type
|
// Cast expression AS date type
|
||||||
func (b *castImpl) AS_TIME() jet.TimeExpression {
|
func (b *castImpl) AS_TIME() jet.TimeExpression {
|
||||||
return TimeExp(b.AS("time without time zone"))
|
return TimeExp(b.AS("time without time zone"))
|
||||||
|
|
@ -2,62 +2,44 @@ package postgres
|
||||||
|
|
||||||
import "github.com/go-jet/jet/internal/jet"
|
import "github.com/go-jet/jet/internal/jet"
|
||||||
|
|
||||||
|
type Column jet.Column
|
||||||
|
|
||||||
|
type IColumnList jet.IColumnList
|
||||||
|
|
||||||
|
var ColumnList = jet.ColumnList
|
||||||
|
|
||||||
type ColumnBool jet.ColumnBool
|
type ColumnBool jet.ColumnBool
|
||||||
type BoolExpression jet.BoolExpression
|
|
||||||
|
|
||||||
var BoolColumn = jet.BoolColumn
|
var BoolColumn = jet.BoolColumn
|
||||||
|
|
||||||
type ColumnString jet.ColumnString
|
type ColumnString jet.ColumnString
|
||||||
type StringExpression jet.StringExpression
|
|
||||||
|
|
||||||
var StringColumn = jet.StringColumn
|
var StringColumn = jet.StringColumn
|
||||||
|
|
||||||
type ColumnInteger jet.ColumnInteger
|
type ColumnInteger jet.ColumnInteger
|
||||||
type IntegerExpression jet.IntegerExpression
|
|
||||||
|
|
||||||
var IntegerColumn = jet.IntegerColumn
|
var IntegerColumn = jet.IntegerColumn
|
||||||
|
|
||||||
type ColumnFloat jet.ColumnFloat
|
type ColumnFloat jet.ColumnFloat
|
||||||
type FloatExpression jet.FloatExpression
|
|
||||||
|
|
||||||
var FloatColumn = jet.FloatColumn
|
var FloatColumn = jet.FloatColumn
|
||||||
|
|
||||||
var FloatExp = jet.FloatExp
|
|
||||||
|
|
||||||
type ColumnDate jet.ColumnDate
|
type ColumnDate jet.ColumnDate
|
||||||
type DateExpression jet.DateExpression
|
|
||||||
|
|
||||||
var DateColumn = jet.DateColumn
|
var DateColumn = jet.DateColumn
|
||||||
|
|
||||||
type ColumnDateTime jet.ColumnTimestamp
|
|
||||||
type DateTimeExpression jet.TimestampExpression
|
|
||||||
|
|
||||||
var DateTimeColumn = jet.TimestampColumn
|
|
||||||
|
|
||||||
type TimeExpression jet.TimeExpression
|
|
||||||
type ColumnTime jet.ColumnTime
|
type ColumnTime jet.ColumnTime
|
||||||
|
|
||||||
var TimeColumn = jet.TimeColumn
|
var TimeColumn = jet.TimeColumn
|
||||||
|
|
||||||
var TimeExp = jet.TimeExp
|
|
||||||
|
|
||||||
type TimezExpression jet.TimezExpression
|
|
||||||
type ColumnTimez jet.ColumnTimez
|
type ColumnTimez jet.ColumnTimez
|
||||||
|
|
||||||
var TimezColumn = jet.TimezColumn
|
var TimezColumn = jet.TimezColumn
|
||||||
|
|
||||||
type ColumnTimestamp jet.ColumnTimestamp
|
type ColumnTimestamp jet.ColumnTimestamp
|
||||||
type TimestampExpression jet.TimestampExpression
|
|
||||||
|
|
||||||
var TimestampColumn = jet.TimestampColumn
|
var TimestampColumn = jet.TimestampColumn
|
||||||
|
|
||||||
var TimestampExp = jet.TimestampExp
|
|
||||||
|
|
||||||
type TimestampzExpression jet.TimestampzExpression
|
|
||||||
type ColumnTimestampz jet.ColumnTimestampz
|
type ColumnTimestampz jet.ColumnTimestampz
|
||||||
|
|
||||||
var TimestampzColumn = jet.TimestampzColumn
|
var TimestampzColumn = jet.TimestampzColumn
|
||||||
|
|
||||||
type SelectTable jet.SelectTable
|
|
||||||
|
|
||||||
// ---------------- statements -----------------//
|
|
||||||
|
|
@ -1,24 +1,30 @@
|
||||||
package postgres
|
package postgres
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"github.com/go-jet/jet/internal/jet"
|
"github.com/go-jet/jet/internal/jet"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Dialect = NewDialect()
|
var Dialect = NewDialect()
|
||||||
|
|
||||||
func NewDialect() jet.Dialect {
|
func NewDialect() jet.Dialect {
|
||||||
|
|
||||||
|
serializeOverrides := map[string]jet.SerializeOverride{}
|
||||||
|
serializeOverrides["REGEXP_LIKE"] = postgres_REGEXP_LIKE_function
|
||||||
|
|
||||||
dialectParams := jet.DialectParams{
|
dialectParams := jet.DialectParams{
|
||||||
Name: "PostgreSQL",
|
Name: "PostgreSQL",
|
||||||
PackageName: "postgres",
|
PackageName: "postgres",
|
||||||
CastOverride: castFunc,
|
CastOverride: castFunc,
|
||||||
|
SerializeOverrides: serializeOverrides,
|
||||||
AliasQuoteChar: '"',
|
AliasQuoteChar: '"',
|
||||||
IdentifierQuoteChar: '"',
|
IdentifierQuoteChar: '"',
|
||||||
ArgumentPlaceholder: func(ord int) string {
|
ArgumentPlaceholder: func(ord int) string {
|
||||||
return "$" + strconv.Itoa(ord)
|
return "$" + strconv.Itoa(ord)
|
||||||
},
|
},
|
||||||
UpdateAssigment: postgresUpdateAssigment,
|
SetClause: postgresSetClause,
|
||||||
SupportsReturning: true,
|
SupportsReturning: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,7 +41,7 @@ func castFunc(expression jet.Expression, castType string) jet.SerializeFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func postgresUpdateAssigment(columns []jet.IColumn, values []jet.Clause, out *jet.SqlBuilder) (err error) {
|
func postgresSetClause(columns []jet.IColumn, values []jet.Clause, out *jet.SqlBuilder) (err error) {
|
||||||
if len(columns) > 1 {
|
if len(columns) > 1 {
|
||||||
out.WriteString("(")
|
out.WriteString("(")
|
||||||
}
|
}
|
||||||
|
|
@ -68,3 +74,37 @@ func postgresUpdateAssigment(columns []jet.IColumn, values []jet.Clause, out *je
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func postgres_REGEXP_LIKE_function(expressions ...jet.Expression) jet.SerializeFunc {
|
||||||
|
return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) error {
|
||||||
|
if len(expressions) < 2 {
|
||||||
|
return errors.New("jet: invalid number of expressions for operator")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := jet.Serialize(expressions[0], statement, out, options...); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
caseSensitive := false
|
||||||
|
|
||||||
|
if len(expressions) >= 3 {
|
||||||
|
if stringLiteral, ok := expressions[2].(jet.LiteralExpression); ok {
|
||||||
|
matchType := stringLiteral.Value().(string)
|
||||||
|
|
||||||
|
caseSensitive = !strings.Contains(matchType, "i")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if caseSensitive {
|
||||||
|
out.WriteString("~")
|
||||||
|
} else {
|
||||||
|
out.WriteString("~*")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := jet.Serialize(expressions[1], statement, out, options...); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
15
postgres/dialect_test.go
Normal file
15
postgres/dialect_test.go
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
package postgres
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestString_REGEXP_LIKE_operator(t *testing.T) {
|
||||||
|
assertClauseSerialize(t, table3StrCol.REGEXP_LIKE(table2ColStr), "table3.col2 ~* table2.col_str")
|
||||||
|
assertClauseSerialize(t, table3StrCol.REGEXP_LIKE(String("JOHN"), "c"), "table3.col2 ~ $1", "JOHN")
|
||||||
|
assertClauseSerialize(t, table3StrCol.REGEXP_LIKE(String("JOHN"), "i"), "table3.col2 ~* $1", "JOHN")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestString_REGEXP_LIKE_function(t *testing.T) {
|
||||||
|
assertClauseSerialize(t, REGEXP_LIKE(table3StrCol, table2ColStr), "table3.col2 ~* table2.col_str")
|
||||||
|
assertClauseSerialize(t, REGEXP_LIKE(table3StrCol, String("JOHN"), "c"), "table3.col2 ~ $1", "JOHN")
|
||||||
|
assertClauseSerialize(t, REGEXP_LIKE(table3StrCol, String("JOHN"), "i"), "table3.col2 ~* $1", "JOHN")
|
||||||
|
}
|
||||||
|
|
@ -3,3 +3,34 @@ package postgres
|
||||||
import "github.com/go-jet/jet/internal/jet"
|
import "github.com/go-jet/jet/internal/jet"
|
||||||
|
|
||||||
type Expression jet.Expression
|
type Expression jet.Expression
|
||||||
|
|
||||||
|
type BoolExpression jet.BoolExpression
|
||||||
|
|
||||||
|
type StringExpression jet.StringExpression
|
||||||
|
|
||||||
|
type IntegerExpression jet.IntegerExpression
|
||||||
|
|
||||||
|
type FloatExpression jet.FloatExpression
|
||||||
|
|
||||||
|
type TimeExpression jet.TimeExpression
|
||||||
|
|
||||||
|
type TimezExpression jet.TimezExpression
|
||||||
|
|
||||||
|
type DateExpression jet.DateExpression
|
||||||
|
|
||||||
|
type TimestampExpression jet.TimestampExpression
|
||||||
|
|
||||||
|
type TimestampzExpression jet.TimestampzExpression
|
||||||
|
|
||||||
|
var BoolExp = jet.BoolExp
|
||||||
|
var IntExp = jet.IntExp
|
||||||
|
var FloatExp = jet.FloatExp
|
||||||
|
var TimeExp = jet.TimeExp
|
||||||
|
var TimezExp = jet.TimezExp
|
||||||
|
var DateExp = jet.DateExp
|
||||||
|
var TimestampExp = jet.TimestampExp
|
||||||
|
var TimestampzExp = jet.TimestampzExp
|
||||||
|
|
||||||
|
var RAW = jet.RAW
|
||||||
|
|
||||||
|
var NewEnumValue = jet.NewEnumValue
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ var SUMi = jet.SUMi
|
||||||
|
|
||||||
//--------------------- String functions ------------------//
|
//--------------------- String functions ------------------//
|
||||||
|
|
||||||
|
var REGEXP_LIKE = jet.REGEXP_LIKE
|
||||||
var BIT_LENGTH = jet.BIT_LENGTH
|
var BIT_LENGTH = jet.BIT_LENGTH
|
||||||
var CHAR_LENGTH = jet.CHAR_LENGTH
|
var CHAR_LENGTH = jet.CHAR_LENGTH
|
||||||
var OCTET_LENGTH = jet.OCTET_LENGTH
|
var OCTET_LENGTH = jet.OCTET_LENGTH
|
||||||
|
|
@ -47,11 +48,25 @@ var BTRIM = jet.BTRIM
|
||||||
var LTRIM = jet.LTRIM
|
var LTRIM = jet.LTRIM
|
||||||
var RTRIM = jet.RTRIM
|
var RTRIM = jet.RTRIM
|
||||||
var CHR = jet.CHR
|
var CHR = jet.CHR
|
||||||
|
|
||||||
|
var CONCAT = func(expressions ...Expression) StringExpression {
|
||||||
|
return jet.CONCAT(explicitCasts(expressions...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CONCAT_WS(expressions ...Expression) StringExpression {
|
||||||
|
return jet.CONCAT_WS(explicitCasts(expressions...)...)
|
||||||
|
}
|
||||||
|
|
||||||
var CONVERT = jet.CONVERT
|
var CONVERT = jet.CONVERT
|
||||||
var CONVERT_FROM = jet.CONVERT_FROM
|
var CONVERT_FROM = jet.CONVERT_FROM
|
||||||
var CONVERT_TO = jet.CONVERT_TO
|
var CONVERT_TO = jet.CONVERT_TO
|
||||||
var ENCODE = jet.ENCODE
|
var ENCODE = jet.ENCODE
|
||||||
var DECODE = jet.DECODE
|
var DECODE = jet.DECODE
|
||||||
|
|
||||||
|
func FORMAT(formatStr StringExpression, formatArgs ...Expression) StringExpression {
|
||||||
|
return jet.FORMAT(formatStr, explicitCasts(formatArgs...)...)
|
||||||
|
}
|
||||||
|
|
||||||
var INITCAP = jet.INITCAP
|
var INITCAP = jet.INITCAP
|
||||||
var LEFT = jet.LEFT
|
var LEFT = jet.LEFT
|
||||||
var RIGHT = jet.RIGHT
|
var RIGHT = jet.RIGHT
|
||||||
|
|
@ -91,3 +106,32 @@ var GREATEST = jet.GREATEST
|
||||||
var LEAST = jet.LEAST
|
var LEAST = jet.LEAST
|
||||||
var EXISTS = jet.EXISTS
|
var EXISTS = jet.EXISTS
|
||||||
var CASE = jet.CASE
|
var CASE = jet.CASE
|
||||||
|
|
||||||
|
func explicitCasts(expressions ...Expression) []jet.Expression {
|
||||||
|
ret := []jet.Expression{}
|
||||||
|
|
||||||
|
for _, exp := range expressions {
|
||||||
|
ret = append(ret, explicitCast(exp))
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func explicitCast(expresion Expression) jet.Expression {
|
||||||
|
if _, ok := expresion.(jet.LiteralExpression); !ok {
|
||||||
|
return expresion
|
||||||
|
}
|
||||||
|
|
||||||
|
switch expresion.(type) {
|
||||||
|
case jet.BoolExpression:
|
||||||
|
return CAST(expresion).AS_BOOL()
|
||||||
|
case jet.IntegerExpression:
|
||||||
|
return CAST(expresion).AS_INTEGER()
|
||||||
|
case jet.FloatExpression:
|
||||||
|
return CAST(expresion).AS_NUMERIC()
|
||||||
|
case jet.StringExpression:
|
||||||
|
return CAST(expresion).AS_TEXT()
|
||||||
|
}
|
||||||
|
|
||||||
|
return expresion
|
||||||
|
}
|
||||||
|
|
@ -1,24 +1,32 @@
|
||||||
package postgres
|
package postgres
|
||||||
|
|
||||||
import "github.com/go-jet/jet/internal/jet"
|
import (
|
||||||
|
"github.com/go-jet/jet/internal/jet"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
var Bool = jet.Bool
|
var Bool = jet.Bool
|
||||||
var Int = jet.Int
|
var Int = jet.Int
|
||||||
var Float = jet.Float
|
var Float = jet.Float
|
||||||
var String = jet.String
|
var String = jet.String
|
||||||
var Date = func(year, month, day int) DateExpression {
|
|
||||||
|
var Bytea = func(value string) StringExpression {
|
||||||
|
return CAST(jet.String(value)).AS_BYTEA()
|
||||||
|
}
|
||||||
|
|
||||||
|
var Date = func(year int, month time.Month, day int) DateExpression {
|
||||||
return CAST(jet.Date(year, month, day)).AS_DATE()
|
return CAST(jet.Date(year, month, day)).AS_DATE()
|
||||||
}
|
}
|
||||||
|
|
||||||
var Time = func(hour, minute, second, milliseconds int) TimeExpression {
|
var Time = func(hour, minute, second int, milliseconds ...int) TimeExpression {
|
||||||
return CAST(jet.Time(hour, minute, second, milliseconds)).AS_TIME()
|
return CAST(jet.Time(hour, minute, second, milliseconds...)).AS_TIME()
|
||||||
}
|
}
|
||||||
|
|
||||||
var Timez = func(hour, minute, second, milliseconds int, timezone int) TimezExpression {
|
var Timez = func(hour, minute, second, milliseconds int, timezone int) TimezExpression {
|
||||||
return CAST(jet.Timez(hour, minute, second, milliseconds, timezone)).AS_TIMEZ()
|
return CAST(jet.Timez(hour, minute, second, milliseconds, timezone)).AS_TIMEZ()
|
||||||
}
|
}
|
||||||
|
|
||||||
var Timestamp = func(year, month, day, hour, minute, second, milliseconds int) TimestampExpression {
|
var Timestamp = func(year int, month time.Month, day, hour, minute, second, milliseconds int) TimestampExpression {
|
||||||
return CAST(jet.Timestamp(year, month, day, hour, minute, second, milliseconds)).AS_TIMESTAMP()
|
return CAST(jet.Timestamp(year, month, day, hour, minute, second, milliseconds)).AS_TIMESTAMP()
|
||||||
}
|
}
|
||||||
|
|
||||||
7
postgres/literal_test.go
Normal file
7
postgres/literal_test.go
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
package postgres
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestDateLiteral(t *testing.T) {
|
||||||
|
assertClauseSerialize(t, Date(2019, 8, 6), "$1::DATE", "2019-08-06")
|
||||||
|
}
|
||||||
|
|
@ -4,10 +4,18 @@ import "github.com/go-jet/jet/internal/jet"
|
||||||
|
|
||||||
// --------- Arithmetic operators -------------//
|
// --------- Arithmetic operators -------------//
|
||||||
|
|
||||||
var MINUSi = jet.MINUSi
|
//var MINUSi = jet.MINUSi
|
||||||
var MINUSf = jet.MINUSf
|
var MINUSf = jet.MINUSf
|
||||||
|
|
||||||
//----------- Logical operators ---------------//
|
//----------- Logical operators ---------------//
|
||||||
|
|
||||||
var NOT = jet.NOT
|
var NOT = jet.NOT
|
||||||
var BIT_NOT = jet.BIT_NOT
|
var BIT_NOT = jet.BIT_NOT
|
||||||
|
|
||||||
|
func MINUSi(intExp IntegerExpression) IntegerExpression {
|
||||||
|
if intLit, ok := intExp.(jet.LiteralExpression); ok {
|
||||||
|
intLit.SetConstant(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return intExp
|
||||||
|
}
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
package postgres
|
|
||||||
|
|
||||||
import "github.com/go-jet/jet/internal/jet"
|
|
||||||
|
|
||||||
type Column jet.Column
|
|
||||||
|
|
||||||
type IColumnList jet.IColumnList
|
|
||||||
|
|
||||||
var ColumnList = jet.ColumnList
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
package postgres
|
|
||||||
|
|
||||||
import "github.com/go-jet/jet/internal/jet"
|
|
||||||
|
|
||||||
var NewEnumValue = jet.NewEnumValue
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
package postgres
|
|
||||||
|
|
||||||
import "github.com/go-jet/jet/internal/jet"
|
|
||||||
|
|
||||||
var RAW = jet.RAW
|
|
||||||
|
|
@ -3,6 +3,15 @@ package postgres
|
||||||
import "github.com/go-jet/jet/internal/jet"
|
import "github.com/go-jet/jet/internal/jet"
|
||||||
|
|
||||||
type SelectStatement jet.SelectStatement
|
type SelectStatement jet.SelectStatement
|
||||||
|
type SelectTable jet.SelectTable
|
||||||
|
type SelectLock jet.SelectLock
|
||||||
|
|
||||||
|
var (
|
||||||
|
UPDATE = jet.NewSelectLock("UPDATE")
|
||||||
|
NO_KEY_UPDATE = jet.NewSelectLock("NO KEY UPDATE")
|
||||||
|
SHARE = jet.NewSelectLock("SHARE")
|
||||||
|
KEY_SHARE = jet.NewSelectLock("KEY SHARE")
|
||||||
|
)
|
||||||
|
|
||||||
var SELECT = jet.SELECT
|
var SELECT = jet.SELECT
|
||||||
|
|
||||||
|
|
@ -31,12 +40,3 @@ func toJetSelects(selects ...SelectStatement) []jet.SelectStatement {
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
type SelectLock jet.SelectLock
|
|
||||||
|
|
||||||
var (
|
|
||||||
UPDATE = jet.NewSelectLock("UPDATE")
|
|
||||||
NO_KEY_UPDATE = jet.NewSelectLock("NO KEY UPDATE")
|
|
||||||
SHARE = jet.NewSelectLock("SHARE")
|
|
||||||
KEY_SHARE = jet.NewSelectLock("KEY SHARE")
|
|
||||||
)
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
package postgres
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
var timeVar = Time(10, 20, 0, 0)
|
|
||||||
|
|
||||||
func TestTimeExpressionEQ(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColTime.EQ(table2ColTime), "(table1.col_time = table2.col_time)")
|
|
||||||
assertClauseSerialize(t, table1ColTime.EQ(timeVar), "(table1.col_time = $1::time without time zone)", "10:20:00.000")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimeExpressionNOT_EQ(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColTime.NOT_EQ(table2ColTime), "(table1.col_time != table2.col_time)")
|
|
||||||
assertClauseSerialize(t, table1ColTime.NOT_EQ(timeVar), "(table1.col_time != $1::time without time zone)", "10:20:00.000")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimeExpressionIS_DISTINCT_FROM(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColTime.IS_DISTINCT_FROM(table2ColTime), "(table1.col_time IS DISTINCT FROM table2.col_time)")
|
|
||||||
assertClauseSerialize(t, table1ColTime.IS_DISTINCT_FROM(timeVar), "(table1.col_time IS DISTINCT FROM $1::time without time zone)", "10:20:00.000")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimeExpressionIS_NOT_DISTINCT_FROM(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColTime.IS_NOT_DISTINCT_FROM(table2ColTime), "(table1.col_time IS NOT DISTINCT FROM table2.col_time)")
|
|
||||||
assertClauseSerialize(t, table1ColTime.IS_NOT_DISTINCT_FROM(timeVar), "(table1.col_time IS NOT DISTINCT FROM $1::time without time zone)", "10:20:00.000")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimeExpressionLT(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColTime.LT(table2ColTime), "(table1.col_time < table2.col_time)")
|
|
||||||
assertClauseSerialize(t, table1ColTime.LT(timeVar), "(table1.col_time < $1::time without time zone)", "10:20:00.000")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimeExpressionLT_EQ(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColTime.LT_EQ(table2ColTime), "(table1.col_time <= table2.col_time)")
|
|
||||||
assertClauseSerialize(t, table1ColTime.LT_EQ(timeVar), "(table1.col_time <= $1::time without time zone)", "10:20:00.000")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimeExpressionGT(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColTime.GT(table2ColTime), "(table1.col_time > table2.col_time)")
|
|
||||||
assertClauseSerialize(t, table1ColTime.GT(timeVar), "(table1.col_time > $1::time without time zone)", "10:20:00.000")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimeExpressionGT_EQ(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColTime.GT_EQ(table2ColTime), "(table1.col_time >= table2.col_time)")
|
|
||||||
assertClauseSerialize(t, table1ColTime.GT_EQ(timeVar), "(table1.col_time >= $1::time without time zone)", "10:20:00.000")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimeExp(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, TimeExp(table1ColFloat), "table1.col_float")
|
|
||||||
assertClauseSerialize(t, TimeExp(table1ColFloat).LT(Time(1, 1, 1, 1)),
|
|
||||||
"(table1.col_float < $1::time without time zone)", string("01:01:01.001"))
|
|
||||||
}
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
package postgres
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
var timestamp = Timestamp(2000, 1, 31, 10, 20, 0, 0)
|
|
||||||
|
|
||||||
func TestTimestampExpressionEQ(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColTimestamp.EQ(table2ColTimestamp), "(table1.col_timestamp = table2.col_timestamp)")
|
|
||||||
assertClauseSerialize(t, table1ColTimestamp.EQ(timestamp),
|
|
||||||
"(table1.col_timestamp = $1::timestamp without time zone)", "2000-01-31 10:20:00.000")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimestampExpressionNOT_EQ(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColTimestamp.NOT_EQ(table2ColTimestamp), "(table1.col_timestamp != table2.col_timestamp)")
|
|
||||||
assertClauseSerialize(t, table1ColTimestamp.NOT_EQ(timestamp), "(table1.col_timestamp != $1::timestamp without time zone)", "2000-01-31 10:20:00.000")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimestampExpressionIS_DISTINCT_FROM(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColTimestamp.IS_DISTINCT_FROM(table2ColTimestamp), "(table1.col_timestamp IS DISTINCT FROM table2.col_timestamp)")
|
|
||||||
assertClauseSerialize(t, table1ColTimestamp.IS_DISTINCT_FROM(timestamp), "(table1.col_timestamp IS DISTINCT FROM $1::timestamp without time zone)", "2000-01-31 10:20:00.000")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimestampExpressionIS_NOT_DISTINCT_FROM(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColTimestamp.IS_NOT_DISTINCT_FROM(table2ColTimestamp), "(table1.col_timestamp IS NOT DISTINCT FROM table2.col_timestamp)")
|
|
||||||
assertClauseSerialize(t, table1ColTimestamp.IS_NOT_DISTINCT_FROM(timestamp), "(table1.col_timestamp IS NOT DISTINCT FROM $1::timestamp without time zone)", "2000-01-31 10:20:00.000")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimestampExpressionLT(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColTimestamp.LT(table2ColTimestamp), "(table1.col_timestamp < table2.col_timestamp)")
|
|
||||||
assertClauseSerialize(t, table1ColTimestamp.LT(timestamp), "(table1.col_timestamp < $1::timestamp without time zone)", "2000-01-31 10:20:00.000")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimestampExpressionLT_EQ(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColTimestamp.LT_EQ(table2ColTimestamp), "(table1.col_timestamp <= table2.col_timestamp)")
|
|
||||||
assertClauseSerialize(t, table1ColTimestamp.LT_EQ(timestamp), "(table1.col_timestamp <= $1::timestamp without time zone)", "2000-01-31 10:20:00.000")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimestampExpressionGT(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColTimestamp.GT(table2ColTimestamp), "(table1.col_timestamp > table2.col_timestamp)")
|
|
||||||
assertClauseSerialize(t, table1ColTimestamp.GT(timestamp), "(table1.col_timestamp > $1::timestamp without time zone)", "2000-01-31 10:20:00.000")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimestampExpressionGT_EQ(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, table1ColTimestamp.GT_EQ(table2ColTimestamp), "(table1.col_timestamp >= table2.col_timestamp)")
|
|
||||||
assertClauseSerialize(t, table1ColTimestamp.GT_EQ(timestamp), "(table1.col_timestamp >= $1::timestamp without time zone)", "2000-01-31 10:20:00.000")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimestampExp(t *testing.T) {
|
|
||||||
assertClauseSerialize(t, TimestampExp(table1ColFloat), "table1.col_float")
|
|
||||||
assertClauseSerialize(t, TimestampExp(table1ColFloat).LT(timestamp),
|
|
||||||
"(table1.col_float < $1::timestamp without time zone)", "2000-01-31 10:20:00.000")
|
|
||||||
}
|
|
||||||
|
|
@ -66,6 +66,8 @@ CREATE TABLE `all_types` (
|
||||||
`bit_ptr` bit(10),
|
`bit_ptr` bit(10),
|
||||||
|
|
||||||
-- date and time
|
-- date and time
|
||||||
|
`time` time NOT NULL,
|
||||||
|
`time_ptr` time,
|
||||||
|
|
||||||
`date` date NOT NULL,
|
`date` date NOT NULL,
|
||||||
`date_ptr` date,
|
`date_ptr` date,
|
||||||
|
|
@ -84,8 +86,8 @@ CREATE TABLE `all_types` (
|
||||||
`char` char(20) NOT NULL,
|
`char` char(20) NOT NULL,
|
||||||
`char_ptr` char(20),
|
`char_ptr` char(20),
|
||||||
|
|
||||||
`varchar` varchar(20) NOT NULL,
|
`var_char` varchar(20) NOT NULL,
|
||||||
`varchar_ptr` varchar(20),
|
`var_char_ptr` varchar(20),
|
||||||
|
|
||||||
`binary` binary(20) NOT NULL,
|
`binary` binary(20) NOT NULL,
|
||||||
`binary_ptr` binary(20),
|
`binary_ptr` binary(20),
|
||||||
|
|
@ -117,12 +119,14 @@ INSERT INTO `all_types` VALUES
|
||||||
-3,3,14,14,-150,150,-1600,1600,5000,50000,
|
-3,3,14,14,-150,150,-1600,1600,5000,50000,
|
||||||
-3,3,14,14,-150,150,-1600,1600,50000,50000,
|
-3,3,14,14,-150,150,-1600,1600,50000,50000,
|
||||||
1.11,1.11,2.22,2.22,3.33,3.33,4.44,4.44,5.55,5.55,
|
1.11,1.11,2.22,2.22,3.33,3.33,4.44,4.44,5.55,5.55,
|
||||||
_binary '\0',_binary '\0','2008-07-04','2008-07-04','2011-12-18 13:17:17','2011-12-18 13:17:17','2007-12-31 23:00:01','2007-12-31 23:00:01',2004,2004,'char','char','varchar','varchar',_binary 'binary\0\0\0\0\0\0\0\0\0\0\0\0\0\0',_binary 'binary\0\0\0\0\0\0\0\0\0\0\0\0\0\0',_binary 'varbinary',_binary 'varbinary',_binary 'blob',_binary 'blob','text','text','value1','value1','s1','s2','{\"key1\": \"value1\", \"key2\": \"value2\"}','{\"key1\": \"value1\", \"key2\": \"value2\"}'),
|
_binary '\0',_binary '\0',
|
||||||
|
'10:11:12.33', '10:11:12.33', '2008-07-04','2008-07-04','2011-12-18 13:17:17','2011-12-18 13:17:17','2007-12-31 23:00:01','2007-12-31 23:00:01',2004,2004,'char','char','varchar','varchar',_binary 'binary\0\0\0\0\0\0\0\0\0\0\0\0\0\0',_binary 'binary\0\0\0\0\0\0\0\0\0\0\0\0\0\0',_binary 'varbinary',_binary 'varbinary',_binary 'blob',_binary 'blob','text','text','value1','value1','s1','s2','{\"key1\": \"value1\", \"key2\": \"value2\"}','{\"key1\": \"value1\", \"key2\": \"value2\"}'),
|
||||||
(false, NULL,
|
(false, NULL,
|
||||||
-3,3,14,14,-150,150,-1600,1600,5000,50000,
|
-3,3,14,14,-150,150,-1600,1600,5000,50000,
|
||||||
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
|
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
|
||||||
1.11,NULL,2.22,NULL,3.33,NULL,4.44,NULL,5.55,NULL,
|
1.11,NULL,2.22,NULL,3.33,NULL,4.44,NULL,5.55,NULL,
|
||||||
_binary '\0',NULL,'2008-07-04',NULL,'2011-12-18 13:17:17',NULL,'2007-12-31 23:00:01',NULL,2004,NULL,'char',NULL,'varchar',NULL,_binary 'binary\0\0\0\0\0\0\0\0\0\0\0\0\0\0',NULL,_binary 'varbinary',NULL,_binary 'blob',NULL,'text',NULL,'value1',NULL,'s1',NULL,'{\"key1\": \"value1\", \"key2\": \"value2\"}',NULL);
|
_binary '\0',NULL,
|
||||||
|
'10:11:12.33', NULL, '2008-07-04',NULL,'2011-12-18 13:17:17',NULL,'2007-12-31 23:00:01',NULL,2004,NULL,'char',NULL,'varchar',NULL,_binary 'binary\0\0\0\0\0\0\0\0\0\0\0\0\0\0',NULL,_binary 'varbinary',NULL,_binary 'blob',NULL,'text',NULL,'value1',NULL,'s1',NULL,'{\"key1\": \"value1\", \"key2\": \"value2\"}',NULL);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,10 +30,10 @@ CREATE TABLE test_sample.ALL_TYPES
|
||||||
-- money_ptr money,
|
-- money_ptr money,
|
||||||
-- money money NOT NULL,
|
-- money money NOT NULL,
|
||||||
|
|
||||||
character_varying_ptr character varying(100),
|
var_char_ptr character varying(100),
|
||||||
character_varying character varying(200) NOT NULL,
|
var_char character varying(200) NOT NULL,
|
||||||
character_ptr character(80),
|
char_ptr character(80),
|
||||||
character character(80) NOT NULL,
|
char character(80) NOT NULL,
|
||||||
text_ptr text,
|
text_ptr text,
|
||||||
text text NOT NULL,
|
text text NOT NULL,
|
||||||
|
|
||||||
|
|
@ -99,7 +99,7 @@ CREATE TABLE test_sample.ALL_TYPES
|
||||||
INSERT INTO test_sample.ALL_types(
|
INSERT INTO test_sample.ALL_types(
|
||||||
small_int_ptr, "small_int", integer_ptr, "integer", big_int_ptr, "big_int", decimal_ptr, "decimal", numeric_ptr, "numeric", real_ptr, "real", double_precision_ptr, double_precision, smallserial, serial, bigserial,
|
small_int_ptr, "small_int", integer_ptr, "integer", big_int_ptr, "big_int", decimal_ptr, "decimal", numeric_ptr, "numeric", real_ptr, "real", double_precision_ptr, double_precision, smallserial, serial, bigserial,
|
||||||
-- money_ptr, money,
|
-- money_ptr, money,
|
||||||
character_varying_ptr, character_varying, character_ptr, "character", text_ptr, text,
|
var_char_ptr, var_char, char_ptr, char, text_ptr, text,
|
||||||
bytea_ptr, bytea,
|
bytea_ptr, bytea,
|
||||||
timestampz_ptr, timestampz, timestamp_ptr, "timestamp", date_ptr, date, timez_ptr, timez, time_ptr, "time", interval_ptr, "interval",
|
timestampz_ptr, timestampz, timestamp_ptr, "timestamp", date_ptr, date, timez_ptr, timez, time_ptr, "time", interval_ptr, "interval",
|
||||||
boolean_ptr, "boolean",
|
boolean_ptr, "boolean",
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
package mysql
|
package mysql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"github.com/go-jet/jet/internal/testutils"
|
"github.com/go-jet/jet/internal/testutils"
|
||||||
"github.com/go-jet/jet/tests/.gentestdata/mysql/test_sample/model"
|
"github.com/go-jet/jet/tests/.gentestdata/mysql/test_sample/model"
|
||||||
. "github.com/go-jet/jet/tests/.gentestdata/mysql/test_sample/table"
|
. "github.com/go-jet/jet/tests/.gentestdata/mysql/test_sample/table"
|
||||||
"github.com/go-jet/jet/tests/testdata/common"
|
"github.com/go-jet/jet/tests/testdata/common"
|
||||||
|
"time"
|
||||||
|
|
||||||
. "github.com/go-jet/jet/mysql"
|
. "github.com/go-jet/jet/mysql"
|
||||||
|
|
||||||
|
|
@ -35,6 +37,8 @@ func TestExpressionOperators(t *testing.T) {
|
||||||
AllTypes.SmallIntPtr.IN(AllTypes.SELECT(AllTypes.Integer)).AS("result.in_select"),
|
AllTypes.SmallIntPtr.IN(AllTypes.SELECT(AllTypes.Integer)).AS("result.in_select"),
|
||||||
AllTypes.SmallIntPtr.NOT_IN(Int(11), Int(22), NULL).AS("result.not_in"),
|
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"),
|
AllTypes.SmallIntPtr.NOT_IN(AllTypes.SELECT(AllTypes.Integer)).AS("result.not_in_select"),
|
||||||
|
|
||||||
|
RAW("DATABASE()"),
|
||||||
).LIMIT(2)
|
).LIMIT(2)
|
||||||
|
|
||||||
//fmt.Println(query.Sql())
|
//fmt.Println(query.Sql())
|
||||||
|
|
@ -51,7 +55,8 @@ SELECT all_types.integer IS NULL AS "result.is_null",
|
||||||
(all_types.small_int_ptr NOT IN ((
|
(all_types.small_int_ptr NOT IN ((
|
||||||
SELECT all_types.integer AS "all_types.integer"
|
SELECT all_types.integer AS "all_types.integer"
|
||||||
FROM test_sample.all_types
|
FROM test_sample.all_types
|
||||||
))) AS "result.not_in_select"
|
))) AS "result.not_in_select",
|
||||||
|
DATABASE()
|
||||||
FROM test_sample.all_types
|
FROM test_sample.all_types
|
||||||
LIMIT ?;
|
LIMIT ?;
|
||||||
`, int64(11), int64(22), int64(11), int64(22), int64(2))
|
`, int64(11), int64(22), int64(11), int64(22), int64(2))
|
||||||
|
|
@ -116,8 +121,8 @@ SELECT (all_types.boolean = all_types.boolean_ptr) AS "EQ1",
|
||||||
(all_types.boolean = ?) AS "EQ2",
|
(all_types.boolean = ?) AS "EQ2",
|
||||||
(all_types.boolean != all_types.boolean_ptr) AS "NEq1",
|
(all_types.boolean != all_types.boolean_ptr) AS "NEq1",
|
||||||
(all_types.boolean != ?) AS "NEq2",
|
(all_types.boolean != ?) AS "NEq2",
|
||||||
(NOT all_types.boolean <=> all_types.boolean_ptr) AS "distinct1",
|
(NOT(all_types.boolean <=> all_types.boolean_ptr)) AS "distinct1",
|
||||||
(NOT all_types.boolean <=> ?) AS "distinct2",
|
(NOT(all_types.boolean <=> ?)) AS "distinct2",
|
||||||
(all_types.boolean <=> all_types.boolean_ptr) AS "not_distinct_1",
|
(all_types.boolean <=> all_types.boolean_ptr) AS "not_distinct_1",
|
||||||
(all_types.boolean <=> ?) AS "NOTDISTINCT2",
|
(all_types.boolean <=> ?) AS "NOTDISTINCT2",
|
||||||
all_types.boolean IS TRUE AS "ISTRUE",
|
all_types.boolean IS TRUE AS "ISTRUE",
|
||||||
|
|
@ -208,9 +213,9 @@ func TestFloatOperators(t *testing.T) {
|
||||||
SELECT (all_types.numeric = all_types.numeric) AS "eq1",
|
SELECT (all_types.numeric = all_types.numeric) AS "eq1",
|
||||||
(all_types.decimal = ?) AS "eq2",
|
(all_types.decimal = ?) AS "eq2",
|
||||||
(all_types.real = ?) AS "eq3",
|
(all_types.real = ?) AS "eq3",
|
||||||
(NOT all_types.numeric <=> all_types.numeric) AS "distinct1",
|
(NOT(all_types.numeric <=> all_types.numeric)) AS "distinct1",
|
||||||
(NOT all_types.decimal <=> ?) AS "distinct2",
|
(NOT(all_types.decimal <=> ?)) AS "distinct2",
|
||||||
(NOT all_types.real <=> ?) AS "distinct3",
|
(NOT(all_types.real <=> ?)) AS "distinct3",
|
||||||
(all_types.numeric <=> all_types.numeric) AS "not_distinct1",
|
(all_types.numeric <=> all_types.numeric) AS "not_distinct1",
|
||||||
(all_types.decimal <=> ?) AS "not_distinct2",
|
(all_types.decimal <=> ?) AS "not_distinct2",
|
||||||
(all_types.real <=> ?) AS "not_distinct3",
|
(all_types.real <=> ?) AS "not_distinct3",
|
||||||
|
|
@ -338,8 +343,8 @@ SELECT all_types.big_int AS "all_types.big_int",
|
||||||
(all_types.big_int = ?) AS "eq2",
|
(all_types.big_int = ?) AS "eq2",
|
||||||
(all_types.big_int != all_types.big_int_ptr) AS "neq1",
|
(all_types.big_int != all_types.big_int_ptr) AS "neq1",
|
||||||
(all_types.big_int != ?) AS "neq2",
|
(all_types.big_int != ?) AS "neq2",
|
||||||
(NOT all_types.big_int <=> all_types.big_int) AS "distinct1",
|
(NOT(all_types.big_int <=> all_types.big_int)) AS "distinct1",
|
||||||
(NOT all_types.big_int <=> ?) AS "distinct2",
|
(NOT(all_types.big_int <=> ?)) AS "distinct2",
|
||||||
(all_types.big_int <=> all_types.big_int) AS "not distinct1",
|
(all_types.big_int <=> all_types.big_int) AS "not distinct1",
|
||||||
(all_types.big_int <=> ?) AS "not distinct2",
|
(all_types.big_int <=> ?) AS "not distinct2",
|
||||||
(all_types.big_int < all_types.big_int_ptr) AS "lt1",
|
(all_types.big_int < all_types.big_int_ptr) AS "lt1",
|
||||||
|
|
@ -394,6 +399,319 @@ LIMIT ?;
|
||||||
testutils.AssertJSONFile(t, dest, "./testdata/common/int_operators.json")
|
testutils.AssertJSONFile(t, dest, "./testdata/common/int_operators.json")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStringOperators(t *testing.T) {
|
||||||
|
query := AllTypes.SELECT(
|
||||||
|
AllTypes.Text.EQ(AllTypes.Char),
|
||||||
|
AllTypes.Text.EQ(String("Text")),
|
||||||
|
AllTypes.Text.NOT_EQ(AllTypes.VarCharPtr),
|
||||||
|
AllTypes.Text.NOT_EQ(String("Text")),
|
||||||
|
AllTypes.Text.GT(AllTypes.Text),
|
||||||
|
AllTypes.Text.GT(String("Text")),
|
||||||
|
AllTypes.Text.GT_EQ(AllTypes.TextPtr),
|
||||||
|
AllTypes.Text.GT_EQ(String("Text")),
|
||||||
|
AllTypes.Text.LT(AllTypes.Char),
|
||||||
|
AllTypes.Text.LT(String("Text")),
|
||||||
|
AllTypes.Text.LT_EQ(AllTypes.VarCharPtr),
|
||||||
|
AllTypes.Text.LT_EQ(String("Text")),
|
||||||
|
AllTypes.Text.CONCAT(String("text2")),
|
||||||
|
AllTypes.Text.CONCAT(Int(11)),
|
||||||
|
AllTypes.Text.LIKE(String("abc")),
|
||||||
|
AllTypes.Text.NOT_LIKE(String("_b_")),
|
||||||
|
AllTypes.Text.REGEXP_LIKE(String("aba")),
|
||||||
|
AllTypes.Text.REGEXP_LIKE(String("aba"), "c"),
|
||||||
|
String("ABA").REGEXP_LIKE(String("aba"), "i"),
|
||||||
|
|
||||||
|
BIT_LENGTH(AllTypes.Text),
|
||||||
|
CHAR_LENGTH(AllTypes.Char),
|
||||||
|
OCTET_LENGTH(AllTypes.Text),
|
||||||
|
LOWER(AllTypes.VarCharPtr),
|
||||||
|
UPPER(AllTypes.Char),
|
||||||
|
LTRIM(AllTypes.VarCharPtr),
|
||||||
|
RTRIM(AllTypes.VarCharPtr),
|
||||||
|
CONCAT(String("string1"), Int(1), Float(11.12)),
|
||||||
|
CONCAT_WS(String("string1"), Int(1), Float(11.12)),
|
||||||
|
FORMAT(String("Hello %s, %1$s"), String("World")),
|
||||||
|
LEFT(String("abcde"), Int(2)),
|
||||||
|
RIGHT(String("abcde"), Int(2)),
|
||||||
|
LENGTH(String("jose")),
|
||||||
|
LPAD(String("Hi"), Int(5), String("xy")),
|
||||||
|
RPAD(String("Hi"), Int(5), String("xy")),
|
||||||
|
MD5(AllTypes.VarCharPtr),
|
||||||
|
REPEAT(AllTypes.Text, Int(33)),
|
||||||
|
REPLACE(AllTypes.Char, String("BA"), String("AB")),
|
||||||
|
REVERSE(AllTypes.VarCharPtr),
|
||||||
|
SUBSTR(AllTypes.CharPtr, Int(3)),
|
||||||
|
SUBSTR(AllTypes.CharPtr, Int(3), Int(2)),
|
||||||
|
REGEXP_LIKE(String("ABA"), String("aba")),
|
||||||
|
REGEXP_LIKE(String("ABA"), String("aba"), "i"),
|
||||||
|
REGEXP_LIKE(AllTypes.Text, String("aba"), "i"),
|
||||||
|
)
|
||||||
|
|
||||||
|
//_, args, _ := query.Sql()
|
||||||
|
|
||||||
|
//fmt.Println(query.Sql())
|
||||||
|
//fmt.Println(args[15])
|
||||||
|
|
||||||
|
fmt.Println(query.Sql())
|
||||||
|
|
||||||
|
err := query.Query(db, &struct{}{})
|
||||||
|
|
||||||
|
assert.NilError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var timeT = time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC)
|
||||||
|
|
||||||
|
func TestTimeExpressions(t *testing.T) {
|
||||||
|
|
||||||
|
query := AllTypes.SELECT(
|
||||||
|
Time(timeT.Clock()),
|
||||||
|
|
||||||
|
AllTypes.Time.EQ(AllTypes.Time),
|
||||||
|
AllTypes.Time.EQ(Time(23, 6, 6)),
|
||||||
|
AllTypes.Time.EQ(Time(22, 6, 6, 11)),
|
||||||
|
AllTypes.Time.EQ(Time(21, 6, 6, 11111)),
|
||||||
|
|
||||||
|
AllTypes.TimePtr.NOT_EQ(AllTypes.Time),
|
||||||
|
AllTypes.TimePtr.NOT_EQ(Time(20, 16, 6)),
|
||||||
|
|
||||||
|
AllTypes.Time.IS_DISTINCT_FROM(AllTypes.Time),
|
||||||
|
AllTypes.Time.IS_DISTINCT_FROM(Time(19, 26, 6)),
|
||||||
|
|
||||||
|
AllTypes.Time.IS_NOT_DISTINCT_FROM(AllTypes.Time),
|
||||||
|
AllTypes.Time.IS_NOT_DISTINCT_FROM(Time(18, 36, 6)),
|
||||||
|
|
||||||
|
AllTypes.Time.LT(AllTypes.Time),
|
||||||
|
AllTypes.Time.LT(Time(17, 46, 6)),
|
||||||
|
|
||||||
|
AllTypes.Time.LT_EQ(AllTypes.Time),
|
||||||
|
AllTypes.Time.LT_EQ(Time(16, 56, 56)),
|
||||||
|
|
||||||
|
AllTypes.Time.GT(AllTypes.Time),
|
||||||
|
AllTypes.Time.GT(Time(15, 16, 46)),
|
||||||
|
|
||||||
|
AllTypes.Time.GT_EQ(AllTypes.Time),
|
||||||
|
AllTypes.Time.GT_EQ(Time(14, 26, 36)),
|
||||||
|
|
||||||
|
CURRENT_TIME(),
|
||||||
|
CURRENT_TIME(3),
|
||||||
|
)
|
||||||
|
|
||||||
|
fmt.Println(query.Sql())
|
||||||
|
|
||||||
|
testutils.AssertStatementSql(t, query, `
|
||||||
|
SELECT ?,
|
||||||
|
all_types.time = all_types.time,
|
||||||
|
all_types.time = ?,
|
||||||
|
all_types.time = ?,
|
||||||
|
all_types.time = ?,
|
||||||
|
all_types.time_ptr != all_types.time,
|
||||||
|
all_types.time_ptr != ?,
|
||||||
|
NOT(all_types.time <=> all_types.time),
|
||||||
|
NOT(all_types.time <=> ?),
|
||||||
|
all_types.time <=> all_types.time,
|
||||||
|
all_types.time <=> ?,
|
||||||
|
all_types.time < all_types.time,
|
||||||
|
all_types.time < ?,
|
||||||
|
all_types.time <= all_types.time,
|
||||||
|
all_types.time <= ?,
|
||||||
|
all_types.time > all_types.time,
|
||||||
|
all_types.time > ?,
|
||||||
|
all_types.time >= all_types.time,
|
||||||
|
all_types.time >= ?,
|
||||||
|
CURRENT_TIME,
|
||||||
|
CURRENT_TIME(3)
|
||||||
|
FROM test_sample.all_types;
|
||||||
|
`, "20:34:58", "23:06:06", "22:06:06.011", "21:06:06.11111", "20:16:06",
|
||||||
|
"19:26:06", "18:36:06", "17:46:06", "16:56:56", "15:16:46", "14:26:36")
|
||||||
|
|
||||||
|
err := query.Query(db, &struct{}{})
|
||||||
|
|
||||||
|
assert.NilError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDateExpressions(t *testing.T) {
|
||||||
|
query := AllTypes.SELECT(
|
||||||
|
Date(timeT.Date()),
|
||||||
|
|
||||||
|
AllTypes.Date.EQ(AllTypes.Date),
|
||||||
|
AllTypes.Date.EQ(Date(2019, 6, 6)),
|
||||||
|
|
||||||
|
AllTypes.DatePtr.NOT_EQ(AllTypes.Date),
|
||||||
|
AllTypes.DatePtr.NOT_EQ(Date(2019, 1, 6)),
|
||||||
|
|
||||||
|
AllTypes.Date.IS_DISTINCT_FROM(AllTypes.Date),
|
||||||
|
AllTypes.Date.IS_DISTINCT_FROM(Date(2019, 2, 6)),
|
||||||
|
|
||||||
|
AllTypes.Date.IS_NOT_DISTINCT_FROM(AllTypes.Date),
|
||||||
|
AllTypes.Date.IS_NOT_DISTINCT_FROM(Date(2019, 3, 6)),
|
||||||
|
|
||||||
|
AllTypes.Date.LT(AllTypes.Date),
|
||||||
|
AllTypes.Date.LT(Date(2019, 4, 6)),
|
||||||
|
|
||||||
|
AllTypes.Date.LT_EQ(AllTypes.Date),
|
||||||
|
AllTypes.Date.LT_EQ(Date(2019, 5, 5)),
|
||||||
|
|
||||||
|
AllTypes.Date.GT(AllTypes.Date),
|
||||||
|
AllTypes.Date.GT(Date(2019, 1, 4)),
|
||||||
|
|
||||||
|
AllTypes.Date.GT_EQ(AllTypes.Date),
|
||||||
|
AllTypes.Date.GT_EQ(Date(2019, 2, 3)),
|
||||||
|
|
||||||
|
CURRENT_DATE(),
|
||||||
|
)
|
||||||
|
|
||||||
|
//fmt.Println(query.Sql())
|
||||||
|
|
||||||
|
testutils.AssertStatementSql(t, query, `
|
||||||
|
SELECT ?,
|
||||||
|
all_types.date = all_types.date,
|
||||||
|
all_types.date = ?,
|
||||||
|
all_types.date_ptr != all_types.date,
|
||||||
|
all_types.date_ptr != ?,
|
||||||
|
NOT(all_types.date <=> all_types.date),
|
||||||
|
NOT(all_types.date <=> ?),
|
||||||
|
all_types.date <=> all_types.date,
|
||||||
|
all_types.date <=> ?,
|
||||||
|
all_types.date < all_types.date,
|
||||||
|
all_types.date < ?,
|
||||||
|
all_types.date <= all_types.date,
|
||||||
|
all_types.date <= ?,
|
||||||
|
all_types.date > all_types.date,
|
||||||
|
all_types.date > ?,
|
||||||
|
all_types.date >= all_types.date,
|
||||||
|
all_types.date >= ?,
|
||||||
|
CURRENT_DATE
|
||||||
|
FROM test_sample.all_types;
|
||||||
|
`)
|
||||||
|
|
||||||
|
err := query.Query(db, &struct{}{})
|
||||||
|
|
||||||
|
assert.NilError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDateTimeExpressions(t *testing.T) {
|
||||||
|
|
||||||
|
var dateTime = DateTime(2019, 6, 6, 10, 2, 46)
|
||||||
|
|
||||||
|
query := AllTypes.SELECT(
|
||||||
|
AllTypes.DateTime.EQ(AllTypes.DateTime),
|
||||||
|
AllTypes.DateTime.EQ(dateTime),
|
||||||
|
|
||||||
|
AllTypes.DateTimePtr.NOT_EQ(AllTypes.DateTime),
|
||||||
|
AllTypes.DateTimePtr.NOT_EQ(DateTime(2019, 6, 6, 10, 2, 46, 1000)),
|
||||||
|
|
||||||
|
AllTypes.DateTime.IS_DISTINCT_FROM(AllTypes.DateTime),
|
||||||
|
AllTypes.DateTime.IS_DISTINCT_FROM(dateTime),
|
||||||
|
|
||||||
|
AllTypes.DateTime.IS_NOT_DISTINCT_FROM(AllTypes.DateTime),
|
||||||
|
AllTypes.DateTime.IS_NOT_DISTINCT_FROM(dateTime),
|
||||||
|
|
||||||
|
AllTypes.DateTime.LT(AllTypes.DateTime),
|
||||||
|
AllTypes.DateTime.LT(dateTime),
|
||||||
|
|
||||||
|
AllTypes.DateTime.LT_EQ(AllTypes.DateTime),
|
||||||
|
AllTypes.DateTime.LT_EQ(dateTime),
|
||||||
|
|
||||||
|
AllTypes.DateTime.GT(AllTypes.DateTime),
|
||||||
|
AllTypes.DateTime.GT(dateTime),
|
||||||
|
|
||||||
|
AllTypes.DateTime.GT_EQ(AllTypes.DateTime),
|
||||||
|
AllTypes.DateTime.GT_EQ(dateTime),
|
||||||
|
|
||||||
|
NOW(),
|
||||||
|
NOW(1),
|
||||||
|
)
|
||||||
|
|
||||||
|
fmt.Println(query.DebugSql())
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, query, `
|
||||||
|
SELECT all_types.date_time = all_types.date_time,
|
||||||
|
all_types.date_time = '2019-06-06 10:02:46',
|
||||||
|
all_types.date_time_ptr != all_types.date_time,
|
||||||
|
all_types.date_time_ptr != '2019-06-06 10:02:46.1000',
|
||||||
|
NOT(all_types.date_time <=> all_types.date_time),
|
||||||
|
NOT(all_types.date_time <=> '2019-06-06 10:02:46'),
|
||||||
|
all_types.date_time <=> all_types.date_time,
|
||||||
|
all_types.date_time <=> '2019-06-06 10:02:46',
|
||||||
|
all_types.date_time < all_types.date_time,
|
||||||
|
all_types.date_time < '2019-06-06 10:02:46',
|
||||||
|
all_types.date_time <= all_types.date_time,
|
||||||
|
all_types.date_time <= '2019-06-06 10:02:46',
|
||||||
|
all_types.date_time > all_types.date_time,
|
||||||
|
all_types.date_time > '2019-06-06 10:02:46',
|
||||||
|
all_types.date_time >= all_types.date_time,
|
||||||
|
all_types.date_time >= '2019-06-06 10:02:46',
|
||||||
|
NOW(),
|
||||||
|
NOW(1)
|
||||||
|
FROM test_sample.all_types;
|
||||||
|
`)
|
||||||
|
|
||||||
|
err := query.Query(db, &struct{}{})
|
||||||
|
|
||||||
|
assert.NilError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTimestampExpressions(t *testing.T) {
|
||||||
|
|
||||||
|
var timestamp = Timestamp(2019, 6, 6, 10, 2, 46)
|
||||||
|
|
||||||
|
query := AllTypes.SELECT(
|
||||||
|
AllTypes.Timestamp.EQ(AllTypes.Timestamp),
|
||||||
|
AllTypes.Timestamp.EQ(timestamp),
|
||||||
|
|
||||||
|
AllTypes.TimestampPtr.NOT_EQ(AllTypes.Timestamp),
|
||||||
|
AllTypes.TimestampPtr.NOT_EQ(Timestamp(2019, 6, 6, 10, 2, 46, 1000)),
|
||||||
|
|
||||||
|
AllTypes.Timestamp.IS_DISTINCT_FROM(AllTypes.Timestamp),
|
||||||
|
AllTypes.Timestamp.IS_DISTINCT_FROM(timestamp),
|
||||||
|
|
||||||
|
AllTypes.Timestamp.IS_NOT_DISTINCT_FROM(AllTypes.Timestamp),
|
||||||
|
AllTypes.Timestamp.IS_NOT_DISTINCT_FROM(timestamp),
|
||||||
|
|
||||||
|
AllTypes.Timestamp.LT(AllTypes.Timestamp),
|
||||||
|
AllTypes.Timestamp.LT(timestamp),
|
||||||
|
|
||||||
|
AllTypes.Timestamp.LT_EQ(AllTypes.Timestamp),
|
||||||
|
AllTypes.Timestamp.LT_EQ(timestamp),
|
||||||
|
|
||||||
|
AllTypes.Timestamp.GT(AllTypes.Timestamp),
|
||||||
|
AllTypes.Timestamp.GT(timestamp),
|
||||||
|
|
||||||
|
AllTypes.Timestamp.GT_EQ(AllTypes.Timestamp),
|
||||||
|
AllTypes.Timestamp.GT_EQ(timestamp),
|
||||||
|
|
||||||
|
CURRENT_TIMESTAMP(),
|
||||||
|
CURRENT_TIMESTAMP(2),
|
||||||
|
)
|
||||||
|
|
||||||
|
fmt.Println(query.DebugSql())
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, query, `
|
||||||
|
SELECT all_types.timestamp = all_types.timestamp,
|
||||||
|
all_types.timestamp = '2019-06-06 10:02:46',
|
||||||
|
all_types.timestamp_ptr != all_types.timestamp,
|
||||||
|
all_types.timestamp_ptr != '2019-06-06 10:02:46.1000',
|
||||||
|
NOT(all_types.timestamp <=> all_types.timestamp),
|
||||||
|
NOT(all_types.timestamp <=> '2019-06-06 10:02:46'),
|
||||||
|
all_types.timestamp <=> all_types.timestamp,
|
||||||
|
all_types.timestamp <=> '2019-06-06 10:02:46',
|
||||||
|
all_types.timestamp < all_types.timestamp,
|
||||||
|
all_types.timestamp < '2019-06-06 10:02:46',
|
||||||
|
all_types.timestamp <= all_types.timestamp,
|
||||||
|
all_types.timestamp <= '2019-06-06 10:02:46',
|
||||||
|
all_types.timestamp > all_types.timestamp,
|
||||||
|
all_types.timestamp > '2019-06-06 10:02:46',
|
||||||
|
all_types.timestamp >= all_types.timestamp,
|
||||||
|
all_types.timestamp >= '2019-06-06 10:02:46',
|
||||||
|
CURRENT_TIMESTAMP,
|
||||||
|
CURRENT_TIMESTAMP(2)
|
||||||
|
FROM test_sample.all_types;
|
||||||
|
`)
|
||||||
|
err := query.Query(db, &struct{}{})
|
||||||
|
|
||||||
|
assert.NilError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
var allTypesJson = `
|
var allTypesJson = `
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
|
@ -431,6 +749,8 @@ var allTypesJson = `
|
||||||
"RealPtr": 5.55,
|
"RealPtr": 5.55,
|
||||||
"Bit": "\u0000\u0003",
|
"Bit": "\u0000\u0003",
|
||||||
"BitPtr": "\u0000\u0003",
|
"BitPtr": "\u0000\u0003",
|
||||||
|
"Time": "0000-01-01T10:11:12Z",
|
||||||
|
"TimePtr": "0000-01-01T10:11:12Z",
|
||||||
"Date": "2008-07-04T00:00:00Z",
|
"Date": "2008-07-04T00:00:00Z",
|
||||||
"DatePtr": "2008-07-04T00:00:00Z",
|
"DatePtr": "2008-07-04T00:00:00Z",
|
||||||
"DateTime": "2011-12-18T13:17:17Z",
|
"DateTime": "2011-12-18T13:17:17Z",
|
||||||
|
|
@ -441,8 +761,8 @@ var allTypesJson = `
|
||||||
"YearPtr": 2004,
|
"YearPtr": 2004,
|
||||||
"Char": "char",
|
"Char": "char",
|
||||||
"CharPtr": "char",
|
"CharPtr": "char",
|
||||||
"Varchar": "varchar",
|
"VarChar": "varchar",
|
||||||
"VarcharPtr": "varchar",
|
"VarCharPtr": "varchar",
|
||||||
"Binary": "YmluYXJ5AAAAAAAAAAAAAAAAAAA=",
|
"Binary": "YmluYXJ5AAAAAAAAAAAAAAAAAAA=",
|
||||||
"BinaryPtr": "YmluYXJ5AAAAAAAAAAAAAAAAAAA=",
|
"BinaryPtr": "YmluYXJ5AAAAAAAAAAAAAAAAAAA=",
|
||||||
"VarBinary": "dmFyYmluYXJ5",
|
"VarBinary": "dmFyYmluYXJ5",
|
||||||
|
|
@ -493,6 +813,8 @@ var allTypesJson = `
|
||||||
"RealPtr": null,
|
"RealPtr": null,
|
||||||
"Bit": "\u0000\u0003",
|
"Bit": "\u0000\u0003",
|
||||||
"BitPtr": null,
|
"BitPtr": null,
|
||||||
|
"Time": "0000-01-01T10:11:12Z",
|
||||||
|
"TimePtr": null,
|
||||||
"Date": "2008-07-04T00:00:00Z",
|
"Date": "2008-07-04T00:00:00Z",
|
||||||
"DatePtr": null,
|
"DatePtr": null,
|
||||||
"DateTime": "2011-12-18T13:17:17Z",
|
"DateTime": "2011-12-18T13:17:17Z",
|
||||||
|
|
@ -503,8 +825,8 @@ var allTypesJson = `
|
||||||
"YearPtr": null,
|
"YearPtr": null,
|
||||||
"Char": "char",
|
"Char": "char",
|
||||||
"CharPtr": null,
|
"CharPtr": null,
|
||||||
"Varchar": "varchar",
|
"VarChar": "varchar",
|
||||||
"VarcharPtr": null,
|
"VarCharPtr": null,
|
||||||
"Binary": "YmluYXJ5AAAAAAAAAAAAAAAAAAA=",
|
"Binary": "YmluYXJ5AAAAAAAAAAAAAAAAAAA=",
|
||||||
"BinaryPtr": null,
|
"BinaryPtr": null,
|
||||||
"VarBinary": "dmFyYmluYXJ5",
|
"VarBinary": "dmFyYmluYXJ5",
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,7 @@ func TestExpressionCast(t *testing.T) {
|
||||||
postgres.CAST(String("111")).AS_BIGINT(),
|
postgres.CAST(String("111")).AS_BIGINT(),
|
||||||
postgres.CAST(String("11.23")).AS_NUMERIC(30, 10),
|
postgres.CAST(String("11.23")).AS_NUMERIC(30, 10),
|
||||||
postgres.CAST(String("11.23")).AS_NUMERIC(30),
|
postgres.CAST(String("11.23")).AS_NUMERIC(30),
|
||||||
|
postgres.CAST(String("11.23")).AS_NUMERIC(),
|
||||||
postgres.CAST(String("11.23")).AS_REAL(),
|
postgres.CAST(String("11.23")).AS_REAL(),
|
||||||
postgres.CAST(String("11.23")).AS_DOUBLE(),
|
postgres.CAST(String("11.23")).AS_DOUBLE(),
|
||||||
postgres.CAST(Int(234)).AS_TEXT(),
|
postgres.CAST(Int(234)).AS_TEXT(),
|
||||||
|
|
@ -162,45 +163,56 @@ func TestExpressionCast(t *testing.T) {
|
||||||
|
|
||||||
func TestStringOperators(t *testing.T) {
|
func TestStringOperators(t *testing.T) {
|
||||||
query := AllTypes.SELECT(
|
query := AllTypes.SELECT(
|
||||||
AllTypes.Text.EQ(AllTypes.Character),
|
AllTypes.Text.EQ(AllTypes.Char),
|
||||||
AllTypes.Text.EQ(String("Text")),
|
AllTypes.Text.EQ(String("Text")),
|
||||||
AllTypes.Text.NOT_EQ(AllTypes.CharacterVaryingPtr),
|
AllTypes.Text.NOT_EQ(AllTypes.VarCharPtr),
|
||||||
AllTypes.Text.NOT_EQ(String("Text")),
|
AllTypes.Text.NOT_EQ(String("Text")),
|
||||||
AllTypes.Text.GT(AllTypes.Text),
|
AllTypes.Text.GT(AllTypes.Text),
|
||||||
AllTypes.Text.GT(String("Text")),
|
AllTypes.Text.GT(String("Text")),
|
||||||
AllTypes.Text.GT_EQ(AllTypes.TextPtr),
|
AllTypes.Text.GT_EQ(AllTypes.TextPtr),
|
||||||
AllTypes.Text.GT_EQ(String("Text")),
|
AllTypes.Text.GT_EQ(String("Text")),
|
||||||
AllTypes.Text.LT(AllTypes.Character),
|
AllTypes.Text.LT(AllTypes.Char),
|
||||||
AllTypes.Text.LT(String("Text")),
|
AllTypes.Text.LT(String("Text")),
|
||||||
AllTypes.Text.LT_EQ(AllTypes.CharacterVaryingPtr),
|
AllTypes.Text.LT_EQ(AllTypes.VarChar),
|
||||||
AllTypes.Text.LT_EQ(String("Text")),
|
AllTypes.Text.LT_EQ(String("Text")),
|
||||||
AllTypes.Text.CONCAT(String("text2")),
|
AllTypes.Text.CONCAT(String("text2")),
|
||||||
AllTypes.Text.CONCAT(Int(11)),
|
AllTypes.Text.CONCAT(Int(11)),
|
||||||
AllTypes.Text.LIKE(String("abc")),
|
AllTypes.Text.LIKE(String("abc")),
|
||||||
AllTypes.Text.NOT_LIKE(String("_b_")),
|
AllTypes.Text.NOT_LIKE(String("_b_")),
|
||||||
AllTypes.Text.SIMILAR_TO(String("%(b|d)%")),
|
AllTypes.Text.REGEXP_LIKE(String("aba")),
|
||||||
AllTypes.Text.NOT_SIMILAR_TO(String("(b|c)%")),
|
AllTypes.Text.REGEXP_LIKE(String("aba"), "c"),
|
||||||
|
AllTypes.Text.REGEXP_LIKE(String("aba"), "i"),
|
||||||
|
|
||||||
BIT_LENGTH(AllTypes.Text),
|
BIT_LENGTH(String("length")),
|
||||||
CHAR_LENGTH(AllTypes.Character),
|
CHAR_LENGTH(AllTypes.Char),
|
||||||
|
CHAR_LENGTH(String("length")),
|
||||||
OCTET_LENGTH(AllTypes.Text),
|
OCTET_LENGTH(AllTypes.Text),
|
||||||
LOWER(AllTypes.CharacterVaryingPtr),
|
OCTET_LENGTH(String("length")),
|
||||||
UPPER(AllTypes.Character),
|
LOWER(AllTypes.VarCharPtr),
|
||||||
BTRIM(AllTypes.CharacterVarying),
|
LOWER(String("length")),
|
||||||
BTRIM(AllTypes.CharacterVarying, String("AA")),
|
UPPER(AllTypes.Char),
|
||||||
LTRIM(AllTypes.CharacterVarying),
|
UPPER(String("upper")),
|
||||||
LTRIM(AllTypes.CharacterVarying, String("A")),
|
BTRIM(AllTypes.VarChar),
|
||||||
RTRIM(AllTypes.CharacterVarying),
|
BTRIM(String("btrim")),
|
||||||
RTRIM(AllTypes.CharacterVarying, String("B")),
|
BTRIM(AllTypes.VarChar, String("AA")),
|
||||||
|
BTRIM(String("btrim"), String("AA")),
|
||||||
|
LTRIM(AllTypes.VarChar),
|
||||||
|
LTRIM(String("ltrim")),
|
||||||
|
LTRIM(AllTypes.VarChar, String("A")),
|
||||||
|
LTRIM(String("Ltrim"), String("A")),
|
||||||
|
RTRIM(String("rtrim")),
|
||||||
|
RTRIM(AllTypes.VarChar, String("B")),
|
||||||
CHR(Int(65)),
|
CHR(Int(65)),
|
||||||
//CONCAT(String("string1"), Int(1), Float(11.12)),
|
CONCAT(AllTypes.VarCharPtr, AllTypes.VarCharPtr, String("aaa"), Int(1)),
|
||||||
//CONCAT_WS(String("string1"), Int(1), Float(11.12)),
|
CONCAT(Bool(false), Int(1), Float(22.2), String("test test")),
|
||||||
CONVERT(String("text_in_utf8"), String("UTF8"), String("LATIN1")),
|
CONCAT_WS(String("string1"), Int(1), Float(11.22), String("bytea"), Bool(false)), //Float(11.12)),
|
||||||
|
CONVERT(String("bytea"), String("UTF8"), String("LATIN1")),
|
||||||
|
CONVERT(AllTypes.Bytea, String("UTF8"), String("LATIN1")),
|
||||||
CONVERT_FROM(String("text_in_utf8"), String("UTF8")),
|
CONVERT_FROM(String("text_in_utf8"), String("UTF8")),
|
||||||
CONVERT_TO(String("text_in_utf8"), String("UTF8")),
|
CONVERT_TO(String("text_in_utf8"), String("UTF8")),
|
||||||
ENCODE(String("123\000\001"), String("base64")),
|
ENCODE(String("123\000\001"), String("base64")),
|
||||||
DECODE(String("MTIzAAE="), String("base64")),
|
DECODE(String("MTIzAAE="), String("base64")),
|
||||||
//FORMAT(String("Hello %s, %1$s"), String("World")),
|
FORMAT(String("Hello %s, %1$s"), String("World")),
|
||||||
INITCAP(String("hi THOMAS")),
|
INITCAP(String("hi THOMAS")),
|
||||||
LEFT(String("abcde"), Int(2)),
|
LEFT(String("abcde"), Int(2)),
|
||||||
RIGHT(String("abcde"), Int(2)),
|
RIGHT(String("abcde"), Int(2)),
|
||||||
|
|
@ -210,13 +222,13 @@ func TestStringOperators(t *testing.T) {
|
||||||
LPAD(String("Hi"), Int(5), String("xy")),
|
LPAD(String("Hi"), Int(5), String("xy")),
|
||||||
RPAD(String("Hi"), Int(5)),
|
RPAD(String("Hi"), Int(5)),
|
||||||
RPAD(String("Hi"), Int(5), String("xy")),
|
RPAD(String("Hi"), Int(5), String("xy")),
|
||||||
MD5(AllTypes.CharacterVarying),
|
MD5(AllTypes.VarChar),
|
||||||
REPEAT(AllTypes.Text, Int(33)),
|
REPEAT(AllTypes.Text, Int(33)),
|
||||||
REPLACE(AllTypes.Character, String("BA"), String("AB")),
|
REPLACE(AllTypes.Char, String("BA"), String("AB")),
|
||||||
REVERSE(AllTypes.CharacterVarying),
|
REVERSE(AllTypes.VarChar),
|
||||||
STRPOS(AllTypes.Text, String("A")),
|
STRPOS(AllTypes.Text, String("A")),
|
||||||
SUBSTR(AllTypes.CharacterPtr, Int(3)),
|
SUBSTR(AllTypes.Char, Int(3)),
|
||||||
SUBSTR(AllTypes.CharacterPtr, Int(3), Int(2)),
|
SUBSTR(AllTypes.CharPtr, Int(3), Int(2)),
|
||||||
TO_HEX(AllTypes.IntegerPtr),
|
TO_HEX(AllTypes.IntegerPtr),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -224,7 +236,7 @@ func TestStringOperators(t *testing.T) {
|
||||||
|
|
||||||
//fmt.Println(query.Sql())
|
//fmt.Println(query.Sql())
|
||||||
//fmt.Println(args[15])
|
//fmt.Println(args[15])
|
||||||
//fmt.Println(query.DebugSql())
|
fmt.Println(query.Sql())
|
||||||
|
|
||||||
err := query.Query(db, &struct{}{})
|
err := query.Query(db, &struct{}{})
|
||||||
|
|
||||||
|
|
@ -459,7 +471,7 @@ func TestIntegerOperators(t *testing.T) {
|
||||||
AllTypes.SmallInt.BIT_XOR(Int(11)).AS("bit xor 2"),
|
AllTypes.SmallInt.BIT_XOR(Int(11)).AS("bit xor 2"),
|
||||||
|
|
||||||
BIT_NOT(MINUSi(AllTypes.SmallInt)).AS("bit_not_1"),
|
BIT_NOT(MINUSi(AllTypes.SmallInt)).AS("bit_not_1"),
|
||||||
BIT_NOT(MINUSi(Int(11, true))).AS("bit_not_2"),
|
BIT_NOT(MINUSi(Int(11))).AS("bit_not_2"),
|
||||||
|
|
||||||
AllTypes.SmallInt.BIT_SHIFT_LEFT(AllTypes.SmallInt.DIV(Int(2))).AS("bit shift left 1"),
|
AllTypes.SmallInt.BIT_SHIFT_LEFT(AllTypes.SmallInt.DIV(Int(2))).AS("bit shift left 1"),
|
||||||
AllTypes.SmallInt.BIT_SHIFT_LEFT(Int(4)).AS("bit shift left 2"),
|
AllTypes.SmallInt.BIT_SHIFT_LEFT(Int(4)).AS("bit shift left 2"),
|
||||||
|
|
@ -513,8 +525,8 @@ SELECT all_types.big_int AS "all_types.big_int",
|
||||||
(all_types.small_int | $16) AS "bit or 2",
|
(all_types.small_int | $16) AS "bit or 2",
|
||||||
(all_types.small_int # all_types.small_int) AS "bit xor 1",
|
(all_types.small_int # all_types.small_int) AS "bit xor 1",
|
||||||
(all_types.small_int # $17) AS "bit xor 2",
|
(all_types.small_int # $17) AS "bit xor 2",
|
||||||
(~ (- all_types.small_int)) AS "bit_not_1",
|
(~ all_types.small_int) AS "bit_not_1",
|
||||||
(~ (- 11)) AS "bit_not_2",
|
(~ 11) AS "bit_not_2",
|
||||||
(all_types.small_int << (all_types.small_int / $18)) AS "bit shift left 1",
|
(all_types.small_int << (all_types.small_int / $18)) AS "bit shift left 1",
|
||||||
(all_types.small_int << $19) AS "bit shift left 2",
|
(all_types.small_int << $19) AS "bit shift left 2",
|
||||||
(all_types.small_int >> (all_types.small_int / $20)) AS "bit shift right 1",
|
(all_types.small_int >> (all_types.small_int / $20)) AS "bit shift right 1",
|
||||||
|
|
@ -539,7 +551,7 @@ LIMIT $22;
|
||||||
testutils.AssertJSONFile(t, dest, "./testdata/common/int_operators.json")
|
testutils.AssertJSONFile(t, dest, "./testdata/common/int_operators.json")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTimeOperators(t *testing.T) {
|
func TestTimeExpression(t *testing.T) {
|
||||||
query := AllTypes.SELECT(
|
query := AllTypes.SELECT(
|
||||||
AllTypes.Time.EQ(AllTypes.Time),
|
AllTypes.Time.EQ(AllTypes.Time),
|
||||||
AllTypes.Time.EQ(Time(23, 6, 6, 1)),
|
AllTypes.Time.EQ(Time(23, 6, 6, 1)),
|
||||||
|
|
@ -799,10 +811,10 @@ var allTypesRow0 = model.AllTypes{
|
||||||
Bigserial: 1,
|
Bigserial: 1,
|
||||||
//MoneyPtr: nil,
|
//MoneyPtr: nil,
|
||||||
//Money:
|
//Money:
|
||||||
CharacterVaryingPtr: StringPtr("ABBA"),
|
VarCharPtr: StringPtr("ABBA"),
|
||||||
CharacterVarying: "ABBA",
|
VarChar: "ABBA",
|
||||||
CharacterPtr: StringPtr("JOHN "),
|
CharPtr: StringPtr("JOHN "),
|
||||||
Character: "JOHN ",
|
Char: "JOHN ",
|
||||||
TextPtr: StringPtr("Some text"),
|
TextPtr: StringPtr("Some text"),
|
||||||
Text: "Some text",
|
Text: "Some text",
|
||||||
ByteaPtr: ByteArrayPtr([]byte("bytea")),
|
ByteaPtr: ByteArrayPtr([]byte("bytea")),
|
||||||
|
|
@ -865,10 +877,10 @@ var allTypesRow1 = model.AllTypes{
|
||||||
Bigserial: 2,
|
Bigserial: 2,
|
||||||
//MoneyPtr: nil,
|
//MoneyPtr: nil,
|
||||||
//Money:
|
//Money:
|
||||||
CharacterVaryingPtr: nil,
|
VarCharPtr: nil,
|
||||||
CharacterVarying: "ABBA",
|
VarChar: "ABBA",
|
||||||
CharacterPtr: nil,
|
CharPtr: nil,
|
||||||
Character: "JOHN ",
|
Char: "JOHN ",
|
||||||
TextPtr: nil,
|
TextPtr: nil,
|
||||||
Text: "Some text",
|
Text: "Some text",
|
||||||
ByteaPtr: nil,
|
ByteaPtr: nil,
|
||||||
|
|
|
||||||
|
|
@ -1273,8 +1273,6 @@ func TestAllSetOperators(t *testing.T) {
|
||||||
UNION_ALL,
|
UNION_ALL,
|
||||||
INTERSECT,
|
INTERSECT,
|
||||||
INTERSECT_ALL,
|
INTERSECT_ALL,
|
||||||
//EXCEPT,
|
|
||||||
//EXCEPT_ALL,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedDestLen := []int{
|
expectedDestLen := []int{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue