Current date/time functions.

This commit is contained in:
zer0sub 2019-06-03 14:41:39 +02:00
parent 37a55e6ee3
commit 7c98fb508c
8 changed files with 177 additions and 26 deletions

View file

@ -158,7 +158,11 @@ func (q *queryData) finalize() (string, []interface{}) {
return q.buff.String() + ";\n", q.args return q.buff.String() + ";\n", q.args
} }
func (q *queryData) insertArgument(arg interface{}) { func (q *queryData) insertConstantArgument(arg interface{}) {
q.writeString(ArgToString(arg))
}
func (q *queryData) insertPreparedArgument(arg interface{}) {
q.args = append(q.args, arg) q.args = append(q.args, arg)
argPlaceholder := "$" + strconv.Itoa(len(q.args)) argPlaceholder := "$" + strconv.Itoa(len(q.args))

View file

@ -7,6 +7,7 @@ type funcExpressionImpl struct {
name string name string
expressions []expression expressions []expression
noBrackets bool
} }
func ROW(expressions ...expression) expression { func ROW(expressions ...expression) expression {
@ -33,17 +34,40 @@ func (f *funcExpressionImpl) serialize(statement statementType, out *queryData,
return errors.New("Function expressions is nil. ") return errors.New("Function expressions is nil. ")
} }
out.writeString(f.name + "(") addBrackets := !f.noBrackets || len(f.expressions) > 0
if addBrackets {
out.writeString(f.name + "(")
} else {
out.writeString(f.name)
}
err := serializeExpressionList(statement, f.expressions, ", ", out) err := serializeExpressionList(statement, f.expressions, ", ", out)
if err != nil { if err != nil {
return err return err
} }
out.writeString(")")
if addBrackets {
out.writeString(")")
}
return nil return nil
} }
type boolFunc struct {
funcExpressionImpl
boolInterfaceImpl
}
func newBoolFunc(name string, expressions ...expression) BoolExpression {
boolFunc := &boolFunc{}
boolFunc.funcExpressionImpl = *newFunc(name, expressions, boolFunc)
boolFunc.boolInterfaceImpl.parent = boolFunc
return boolFunc
}
type floatFunc struct { type floatFunc struct {
funcExpressionImpl funcExpressionImpl
floatInterfaceImpl floatInterfaceImpl
@ -91,7 +115,7 @@ type dateFunc struct {
dateInterfaceImpl dateInterfaceImpl
} }
func newDateFunc(name string, expressions ...expression) DateExpression { func newDateFunc(name string, expressions ...expression) *dateFunc {
dateFunc := &dateFunc{} dateFunc := &dateFunc{}
dateFunc.funcExpressionImpl = *newFunc(name, expressions, dateFunc) dateFunc.funcExpressionImpl = *newFunc(name, expressions, dateFunc)
@ -100,18 +124,46 @@ func newDateFunc(name string, expressions ...expression) DateExpression {
return dateFunc return dateFunc
} }
type boolFunc struct { type timeFunc struct {
funcExpressionImpl funcExpressionImpl
boolInterfaceImpl timeInterfaceImpl
} }
func newBoolFunc(name string, expressions ...expression) BoolExpression { func newTimeFunc(name string, expressions ...expression) *timeFunc {
boolFunc := &boolFunc{} timeFun := &timeFunc{}
boolFunc.funcExpressionImpl = *newFunc(name, expressions, boolFunc) timeFun.funcExpressionImpl = *newFunc(name, expressions, timeFun)
boolFunc.boolInterfaceImpl.parent = boolFunc timeFun.timeInterfaceImpl.parent = timeFun
return boolFunc return timeFun
}
type timezFunc struct {
funcExpressionImpl
timezInterfaceImpl
}
func newTimezFunc(name string, expressions ...expression) *timezFunc {
timezFun := &timezFunc{}
timezFun.funcExpressionImpl = *newFunc(name, expressions, timezFun)
timezFun.timezInterfaceImpl.parent = timezFun
return timezFun
}
type timestampFunc struct {
funcExpressionImpl
timestampInterfaceImpl
}
func newTimestampFunc(name string, expressions ...expression) *timestampFunc {
timestampFunc := &timestampFunc{}
timestampFunc.funcExpressionImpl = *newFunc(name, expressions, timestampFunc)
timestampFunc.timestampInterfaceImpl.parent = timestampFunc
return timestampFunc
} }
type timestampzFunc struct { type timestampzFunc struct {
@ -119,7 +171,7 @@ type timestampzFunc struct {
timestampzInterfaceImpl timestampzInterfaceImpl
} }
func newTimestampzFunc(name string, expressions ...expression) TimestampzExpression { func newTimestampzFunc(name string, expressions ...expression) *timestampzFunc {
timestampzFunc := &timestampzFunc{} timestampzFunc := &timestampzFunc{}
timestampzFunc.funcExpressionImpl = *newFunc(name, expressions, timestampzFunc) timestampzFunc.funcExpressionImpl = *newFunc(name, expressions, timestampzFunc)
@ -258,6 +310,7 @@ 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...)
//} //}
@ -382,3 +435,71 @@ func TO_NUMBER(floatStr, format StringExpression) FloatExpression {
func TO_TIMESTAMP(timestampzStr, format StringExpression) TimestampzExpression { func TO_TIMESTAMP(timestampzStr, format StringExpression) TimestampzExpression {
return newTimestampzFunc("TO_TIMESTAMP", timestampzStr, format) return newTimestampzFunc("TO_TIMESTAMP", timestampzStr, format)
} }
//----------------- Date/Time Functions and Operators ---------------//
func CURRENT_DATE() DateExpression {
dateFunc := newDateFunc("CURRENT_DATE")
dateFunc.noBrackets = true
return dateFunc
}
func CURRENT_TIME(precision ...int) TimezExpression {
var timezFunc *timezFunc
if len(precision) > 0 {
timezFunc = newTimezFunc("CURRENT_TIME", ConstantLiteral(precision[0]))
} else {
timezFunc = newTimezFunc("CURRENT_TIME")
}
timezFunc.noBrackets = true
return timezFunc
}
func CURRENT_TIMESTAMP(precision ...int) TimestampzExpression {
var timestampzFunc *timestampzFunc
if len(precision) > 0 {
timestampzFunc = newTimestampzFunc("CURRENT_TIMESTAMP", ConstantLiteral(precision[0]))
} else {
timestampzFunc = newTimestampzFunc("CURRENT_TIMESTAMP")
}
timestampzFunc.noBrackets = true
return timestampzFunc
}
func LOCALTIME(precision ...int) TimeExpression {
var timeFunc *timeFunc
if len(precision) > 0 {
timeFunc = newTimeFunc("LOCALTIME", ConstantLiteral(precision[0]))
} else {
timeFunc = newTimeFunc("LOCALTIME")
}
timeFunc.noBrackets = true
return timeFunc
}
func LOCALTIMESTAMP(precision ...int) TimestampExpression {
var timestampFunc *timestampFunc
if len(precision) > 0 {
timestampFunc = newTimestampFunc("LOCALTIMESTAMP", ConstantLiteral(precision[0]))
} else {
timestampFunc = newTimestampFunc("LOCALTIMESTAMP")
}
timestampFunc.noBrackets = true
return timestampFunc
}
func NOW() TimestampzExpression {
return newTimestampzFunc("NOW")
}

View file

@ -5,7 +5,8 @@ import "fmt"
// Representation of an escaped literal // Representation of an escaped literal
type literalExpression struct { type literalExpression struct {
expressionInterfaceImpl expressionInterfaceImpl
value interface{} value interface{}
constant bool
} }
func Literal(value interface{}) *literalExpression { func Literal(value interface{}) *literalExpression {
@ -15,8 +16,19 @@ func Literal(value interface{}) *literalExpression {
return &exp return &exp
} }
func ConstantLiteral(value interface{}) *literalExpression {
exp := Literal(value)
exp.constant = true
return exp
}
func (l literalExpression) serialize(statement statementType, out *queryData, options ...serializeOption) error { func (l literalExpression) serialize(statement statementType, out *queryData, options ...serializeOption) error {
out.insertArgument(l.value) if l.constant {
out.insertConstantArgument(l.value)
} else {
out.insertPreparedArgument(l.value)
}
return nil return nil
} }

View file

@ -174,13 +174,13 @@ func (s *selectStatementImpl) serializeImpl(out *queryData) error {
if s.limit >= 0 { if s.limit >= 0 {
out.nextLine() out.nextLine()
out.writeString("LIMIT") out.writeString("LIMIT")
out.insertArgument(s.limit) out.insertPreparedArgument(s.limit)
} }
if s.offset >= 0 { if s.offset >= 0 {
out.nextLine() out.nextLine()
out.writeString("OFFSET") out.writeString("OFFSET")
out.insertArgument(s.offset) out.insertPreparedArgument(s.offset)
} }
if s.forUpdate { if s.forUpdate {

View file

@ -168,13 +168,13 @@ func (s *setStatementImpl) serializeImpl(out *queryData) error {
if s.limit >= 0 { if s.limit >= 0 {
out.nextLine() out.nextLine()
out.writeString("LIMIT") out.writeString("LIMIT")
out.insertArgument(s.limit) out.insertPreparedArgument(s.limit)
} }
if s.offset >= 0 { if s.offset >= 0 {
out.nextLine() out.nextLine()
out.writeString("OFFSET") out.writeString("OFFSET")
out.insertArgument(s.offset) out.insertPreparedArgument(s.offset)
} }
return nil return nil

View file

@ -6,30 +6,30 @@ import (
func TestTimeExpressionEQ(t *testing.T) { func TestTimeExpressionEQ(t *testing.T) {
assertExpressionSerialize(t, table1ColTime.EQ(table2ColTime), "(table1.colTime = table2.colTime)") assertExpressionSerialize(t, table1ColTime.EQ(table2ColTime), "(table1.colTime = table2.colTime)")
assertExpressionSerialize(t, table1ColTime.EQ(Time(10, 20, 0, 0)), "(table1.colTime = $1)", "10:20:00.000") assertExpressionSerialize(t, table1ColTime.EQ(Time(10, 20, 0, 0)), "(table1.colTime = $1::time without time zone)", "10:20:00.000")
} }
func TestTimeExpressionNOT_EQ(t *testing.T) { func TestTimeExpressionNOT_EQ(t *testing.T) {
assertExpressionSerialize(t, table1ColTime.NOT_EQ(table2ColTime), "(table1.colTime != table2.colTime)") assertExpressionSerialize(t, table1ColTime.NOT_EQ(table2ColTime), "(table1.colTime != table2.colTime)")
assertExpressionSerialize(t, table1ColTime.NOT_EQ(Time(10, 20, 0, 0)), "(table1.colTime != $1)", "10:20:00.000") assertExpressionSerialize(t, table1ColTime.NOT_EQ(Time(10, 20, 0, 0)), "(table1.colTime != $1::time without time zone)", "10:20:00.000")
} }
func TestTimeExpressionLT(t *testing.T) { func TestTimeExpressionLT(t *testing.T) {
assertExpressionSerialize(t, table1ColTime.LT(table2ColTime), "(table1.colTime < table2.colTime)") assertExpressionSerialize(t, table1ColTime.LT(table2ColTime), "(table1.colTime < table2.colTime)")
assertExpressionSerialize(t, table1ColTime.LT(Time(10, 20, 0, 0)), "(table1.colTime < $1)", "10:20:00.000") assertExpressionSerialize(t, table1ColTime.LT(Time(10, 20, 0, 0)), "(table1.colTime < $1::time without time zone)", "10:20:00.000")
} }
func TestTimeExpressionLT_EQ(t *testing.T) { func TestTimeExpressionLT_EQ(t *testing.T) {
assertExpressionSerialize(t, table1ColTime.LT_EQ(table2ColTime), "(table1.colTime <= table2.colTime)") assertExpressionSerialize(t, table1ColTime.LT_EQ(table2ColTime), "(table1.colTime <= table2.colTime)")
assertExpressionSerialize(t, table1ColTime.LT_EQ(Time(10, 20, 0, 0)), "(table1.colTime <= $1)", "10:20:00.000") assertExpressionSerialize(t, table1ColTime.LT_EQ(Time(10, 20, 0, 0)), "(table1.colTime <= $1::time without time zone)", "10:20:00.000")
} }
func TestTimeExpressionGT(t *testing.T) { func TestTimeExpressionGT(t *testing.T) {
assertExpressionSerialize(t, table1ColTime.GT(table2ColTime), "(table1.colTime > table2.colTime)") assertExpressionSerialize(t, table1ColTime.GT(table2ColTime), "(table1.colTime > table2.colTime)")
assertExpressionSerialize(t, table1ColTime.GT(Time(10, 20, 0, 0)), "(table1.colTime > $1)", "10:20:00.000") assertExpressionSerialize(t, table1ColTime.GT(Time(10, 20, 0, 0)), "(table1.colTime > $1::time without time zone)", "10:20:00.000")
} }
func TestTimeExpressionGT_EQ(t *testing.T) { func TestTimeExpressionGT_EQ(t *testing.T) {
assertExpressionSerialize(t, table1ColTime.GT_EQ(table2ColTime), "(table1.colTime >= table2.colTime)") assertExpressionSerialize(t, table1ColTime.GT_EQ(table2ColTime), "(table1.colTime >= table2.colTime)")
assertExpressionSerialize(t, table1ColTime.GT_EQ(Time(10, 20, 0, 0)), "(table1.colTime >= $1)", "10:20:00.000") assertExpressionSerialize(t, table1ColTime.GT_EQ(Time(10, 20, 0, 0)), "(table1.colTime >= $1::time without time zone)", "10:20:00.000")
} }

View file

@ -973,7 +973,7 @@ SELECT payment.payment_id AS "payment.payment_id",
payment.amount AS "payment.amount", payment.amount AS "payment.amount",
payment.payment_date AS "payment.payment_date" payment.payment_date AS "payment.payment_date"
FROM dvds.payment FROM dvds.payment
WHERE payment.payment_date < '2007-02-14 22:16:01.000' WHERE payment.payment_date < '2007-02-14 22:16:01.000'::timestamp without time zone
ORDER BY payment.payment_date ASC; ORDER BY payment.payment_date ASC;
` `

View file

@ -111,7 +111,10 @@ func TestStringOperators(t *testing.T) {
TO_HEX(AllTypes.IntegerPtr), TO_HEX(AllTypes.IntegerPtr),
) )
//fmt.Println(query.Sql()) _, args, _ := query.Sql()
fmt.Println(query.Sql())
fmt.Println(args[15])
fmt.Println(query.DebugSql()) fmt.Println(query.DebugSql())
err := query.Query(db, &struct{}{}) err := query.Query(db, &struct{}{})
@ -284,6 +287,17 @@ func TestTimeOperators(t *testing.T) {
AllTypes.Time.GT_EQ(AllTypes.Time), AllTypes.Time.GT_EQ(AllTypes.Time),
AllTypes.Time.GT_EQ(Time(23, 6, 6, 1)), AllTypes.Time.GT_EQ(Time(23, 6, 6, 1)),
CURRENT_DATE(),
CURRENT_TIME(),
CURRENT_TIME(2),
CURRENT_TIMESTAMP(),
CURRENT_TIMESTAMP(1),
LOCALTIME(),
LOCALTIME(11),
LOCALTIMESTAMP(),
LOCALTIMESTAMP(4),
NOW(),
) )
fmt.Println(query.DebugSql()) fmt.Println(query.DebugSql())