Expression casting between builtin types.
This commit is contained in:
parent
fcd3596780
commit
37a55e6ee3
8 changed files with 294 additions and 47 deletions
154
sqlbuilder/cast.go
Normal file
154
sqlbuilder/cast.go
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
package sqlbuilder
|
||||
|
||||
type cast struct {
|
||||
expression expression
|
||||
castType string
|
||||
}
|
||||
|
||||
func newCast(expression expression, castType string) cast {
|
||||
return cast{
|
||||
expression: expression,
|
||||
castType: castType,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *cast) serialize(statement statementType, out *queryData, options ...serializeOption) error {
|
||||
err := b.expression.serialize(statement, out, options...)
|
||||
out.writeString("::" + b.castType)
|
||||
return err
|
||||
}
|
||||
|
||||
type boolCast struct {
|
||||
expressionInterfaceImpl
|
||||
boolInterfaceImpl
|
||||
cast
|
||||
}
|
||||
|
||||
func newBoolCast(expression expression) BoolExpression {
|
||||
boolCast := &boolCast{cast: newCast(expression, "boolean")}
|
||||
|
||||
boolCast.boolInterfaceImpl.parent = boolCast
|
||||
boolCast.expressionInterfaceImpl.parent = boolCast
|
||||
|
||||
return boolCast
|
||||
}
|
||||
|
||||
type integerCast struct {
|
||||
expressionInterfaceImpl
|
||||
integerInterfaceImpl
|
||||
cast
|
||||
}
|
||||
|
||||
func newIntegerCast(expression expression) IntegerExpression {
|
||||
integerCast := &integerCast{cast: newCast(expression, "integer")}
|
||||
|
||||
integerCast.integerInterfaceImpl.parent = integerCast
|
||||
integerCast.expressionInterfaceImpl.parent = integerCast
|
||||
|
||||
return integerCast
|
||||
}
|
||||
|
||||
type floatCast struct {
|
||||
expressionInterfaceImpl
|
||||
floatInterfaceImpl
|
||||
cast
|
||||
}
|
||||
|
||||
func newDoubleCast(expression expression) FloatExpression {
|
||||
floatCast := &floatCast{cast: newCast(expression, "double precision")}
|
||||
|
||||
floatCast.floatInterfaceImpl.parent = floatCast
|
||||
floatCast.expressionInterfaceImpl.parent = floatCast
|
||||
|
||||
return floatCast
|
||||
}
|
||||
|
||||
type textCast struct {
|
||||
expressionInterfaceImpl
|
||||
stringInterfaceImpl
|
||||
cast
|
||||
}
|
||||
|
||||
func newTextCast(expression expression) StringExpression {
|
||||
textCast := &textCast{cast: newCast(expression, "text")}
|
||||
|
||||
textCast.stringInterfaceImpl.parent = textCast
|
||||
textCast.expressionInterfaceImpl.parent = textCast
|
||||
|
||||
return textCast
|
||||
}
|
||||
|
||||
type dateCast struct {
|
||||
expressionInterfaceImpl
|
||||
dateInterfaceImpl
|
||||
cast
|
||||
}
|
||||
|
||||
func newDateCast(expression expression) DateExpression {
|
||||
dateCast := &dateCast{cast: newCast(expression, "date")}
|
||||
|
||||
dateCast.dateInterfaceImpl.parent = dateCast
|
||||
dateCast.expressionInterfaceImpl.parent = dateCast
|
||||
|
||||
return dateCast
|
||||
}
|
||||
|
||||
type timeCast struct {
|
||||
expressionInterfaceImpl
|
||||
timeInterfaceImpl
|
||||
cast
|
||||
}
|
||||
|
||||
func newTimeCast(expression expression) TimeExpression {
|
||||
timeCast := &timeCast{cast: newCast(expression, "time without time zone")}
|
||||
|
||||
timeCast.timeInterfaceImpl.parent = timeCast
|
||||
timeCast.expressionInterfaceImpl.parent = timeCast
|
||||
|
||||
return timeCast
|
||||
}
|
||||
|
||||
type timezCast struct {
|
||||
expressionInterfaceImpl
|
||||
timezInterfaceImpl
|
||||
cast
|
||||
}
|
||||
|
||||
func newTimezCast(expression expression) TimezExpression {
|
||||
timezCast := &timezCast{cast: newCast(expression, "time with time zone")}
|
||||
|
||||
timezCast.timezInterfaceImpl.parent = timezCast
|
||||
timezCast.expressionInterfaceImpl.parent = timezCast
|
||||
|
||||
return timezCast
|
||||
}
|
||||
|
||||
type timestampCast struct {
|
||||
expressionInterfaceImpl
|
||||
timestampInterfaceImpl
|
||||
cast
|
||||
}
|
||||
|
||||
func newTimestampCast(expression expression) TimestampExpression {
|
||||
timestampCast := ×tampCast{cast: newCast(expression, "timestamp without time zone")}
|
||||
|
||||
timestampCast.timestampInterfaceImpl.parent = timestampCast
|
||||
timestampCast.expressionInterfaceImpl.parent = timestampCast
|
||||
|
||||
return timestampCast
|
||||
}
|
||||
|
||||
type timestampzCast struct {
|
||||
expressionInterfaceImpl
|
||||
timestampzInterfaceImpl
|
||||
cast
|
||||
}
|
||||
|
||||
func newTimestampzCast(expression expression) TimestampzExpression {
|
||||
timestampzCast := ×tampzCast{cast: newCast(expression, "timestamp with time zone")}
|
||||
|
||||
timestampzCast.timestampzInterfaceImpl.parent = timestampzCast
|
||||
timestampzCast.expressionInterfaceImpl.parent = timestampzCast
|
||||
|
||||
return timestampzCast
|
||||
}
|
||||
|
|
@ -139,11 +139,11 @@ func (q *queryData) write(data []byte) {
|
|||
}
|
||||
|
||||
func isPreSeparator(b byte) bool {
|
||||
return b == ' ' || b == '.' || b == ',' || b == '(' || b == '\n'
|
||||
return b == ' ' || b == '.' || b == ',' || b == '(' || b == '\n' || b == ':'
|
||||
}
|
||||
|
||||
func isPostSeparator(b byte) bool {
|
||||
return b == ' ' || b == '.' || b == ',' || b == ')' || b == '\n'
|
||||
return b == ' ' || b == '.' || b == ',' || b == ')' || b == '\n' || b == ':'
|
||||
}
|
||||
|
||||
func (q *queryData) writeString(str string) {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,16 @@ type expression interface {
|
|||
|
||||
ASC() orderByClause
|
||||
DESC() orderByClause
|
||||
|
||||
CAST_TO_BOOL() BoolExpression
|
||||
CAST_TO_INTEGER() IntegerExpression
|
||||
CAST_TO_DOUBLE() FloatExpression
|
||||
CAST_TO_TEXT() StringExpression
|
||||
CAST_TO_DATE() DateExpression
|
||||
CAST_TO_TIME() TimeExpression
|
||||
CAST_TO_TIMEZ() TimezExpression
|
||||
CAST_TO_TIMESTAMP() TimestampExpression
|
||||
CAST_TO_TIMESTAMPZ() TimestampzExpression
|
||||
}
|
||||
|
||||
type expressionInterfaceImpl struct {
|
||||
|
|
@ -55,6 +65,42 @@ func (e *expressionInterfaceImpl) DESC() orderByClause {
|
|||
return &orderByClauseImpl{expression: e.parent, ascent: false}
|
||||
}
|
||||
|
||||
func (e *expressionInterfaceImpl) CAST_TO_BOOL() BoolExpression {
|
||||
return newBoolCast(e.parent)
|
||||
}
|
||||
|
||||
func (e *expressionInterfaceImpl) CAST_TO_INTEGER() IntegerExpression {
|
||||
return newIntegerCast(e.parent)
|
||||
}
|
||||
|
||||
func (e *expressionInterfaceImpl) CAST_TO_DOUBLE() FloatExpression {
|
||||
return newDoubleCast(e.parent)
|
||||
}
|
||||
|
||||
func (e *expressionInterfaceImpl) CAST_TO_TEXT() StringExpression {
|
||||
return newTextCast(e.parent)
|
||||
}
|
||||
|
||||
func (e *expressionInterfaceImpl) CAST_TO_DATE() DateExpression {
|
||||
return newDateCast(e.parent)
|
||||
}
|
||||
|
||||
func (e *expressionInterfaceImpl) CAST_TO_TIME() TimeExpression {
|
||||
return newTimeCast(e.parent)
|
||||
}
|
||||
|
||||
func (e *expressionInterfaceImpl) CAST_TO_TIMEZ() TimezExpression {
|
||||
return newTimezCast(e.parent)
|
||||
}
|
||||
|
||||
func (e *expressionInterfaceImpl) CAST_TO_TIMESTAMP() TimestampExpression {
|
||||
return newTimestampCast(e.parent)
|
||||
}
|
||||
|
||||
func (e *expressionInterfaceImpl) CAST_TO_TIMESTAMPZ() TimestampzExpression {
|
||||
return newTimestampzCast(e.parent)
|
||||
}
|
||||
|
||||
func (e *expressionInterfaceImpl) serializeForGroupBy(statement statementType, out *queryData) error {
|
||||
return e.parent.serialize(statement, out, NO_WRAP)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,3 +23,40 @@ func TestExpressionIS_NOT_DISTINCT_FROM(t *testing.T) {
|
|||
assertExpressionSerialize(t, table2Col3.IS_NOT_DISTINCT_FROM(table2Col4), "(table2.col3 IS NOT DISTINCT FROM table2.col4)")
|
||||
assertExpressionSerialize(t, table2Col3.ADD(table2Col3).IS_NOT_DISTINCT_FROM(Int(23)), "((table2.col3 + table2.col3) IS NOT DISTINCT FROM $1)", int64(23))
|
||||
}
|
||||
|
||||
func TestExpressionCAST_TO_BOOL(t *testing.T) {
|
||||
assertExpressionSerialize(t, table2Col3.CAST_TO_BOOL(), "table2.col3::boolean")
|
||||
assertExpressionSerialize(t, table2Col3.ADD(table2Col3).CAST_TO_BOOL(), "(table2.col3 + table2.col3)::boolean")
|
||||
}
|
||||
|
||||
func TestExpressionCAST_TO_INTEGER(t *testing.T) {
|
||||
assertExpressionSerialize(t, table2Col3.CAST_TO_INTEGER(), "table2.col3::integer")
|
||||
}
|
||||
|
||||
func TestExpressionCAST_TO_DOUBLE(t *testing.T) {
|
||||
assertExpressionSerialize(t, table2Col3.CAST_TO_DOUBLE(), "table2.col3::double precision")
|
||||
}
|
||||
|
||||
func TestExpressionCAST_TO_TEXT(t *testing.T) {
|
||||
assertExpressionSerialize(t, table2Col3.CAST_TO_TEXT(), "table2.col3::text")
|
||||
}
|
||||
|
||||
func TestExpressionCAST_TO_DATE(t *testing.T) {
|
||||
assertExpressionSerialize(t, table2Col3.CAST_TO_DATE(), "table2.col3::date")
|
||||
}
|
||||
|
||||
func TestExpressionCAST_TO_TIME(t *testing.T) {
|
||||
assertExpressionSerialize(t, table2Col3.CAST_TO_TIME(), "table2.col3::time without time zone")
|
||||
}
|
||||
|
||||
func TestExpressionCAST_TO_TIMEZ(t *testing.T) {
|
||||
assertExpressionSerialize(t, table2Col3.CAST_TO_TIMEZ(), "table2.col3::time with time zone")
|
||||
}
|
||||
|
||||
func TestExpressionCAST_TO_TIMESTAMP(t *testing.T) {
|
||||
assertExpressionSerialize(t, table2Col3.CAST_TO_TIMESTAMP(), "table2.col3::timestamp without time zone")
|
||||
}
|
||||
|
||||
func TestExpressionCAST_TO_TIMESTAMPZ(t *testing.T) {
|
||||
assertExpressionSerialize(t, table2Col3.CAST_TO_TIMESTAMPZ(), "table2.col3::timestamp with time zone")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,14 +88,14 @@ type timeLiteral struct {
|
|||
literalExpression
|
||||
}
|
||||
|
||||
func Time(hour, minute, second, milliseconds int) timeExpression {
|
||||
func Time(hour, minute, second, milliseconds int) TimeExpression {
|
||||
timeLiteral := timeLiteral{}
|
||||
timeStr := fmt.Sprintf("%02d:%02d:%02d.%03d", hour, minute, second, milliseconds)
|
||||
timeLiteral.literalExpression = *Literal(timeStr)
|
||||
|
||||
timeLiteral.timeInterfaceImpl.parent = &timeLiteral
|
||||
|
||||
return &timeLiteral
|
||||
return timeLiteral.CAST_TO_TIME()
|
||||
}
|
||||
|
||||
//---------------------------------------------------//
|
||||
|
|
@ -104,14 +104,14 @@ type timezLiteral struct {
|
|||
literalExpression
|
||||
}
|
||||
|
||||
func Timez(hour, minute, second, milliseconds, timezone int) timezExpression {
|
||||
func Timez(hour, minute, second, milliseconds, timezone int) TimezExpression {
|
||||
timezLiteral := timezLiteral{}
|
||||
timeStr := fmt.Sprintf("%02d:%02d:%02d.%03d %+03d", hour, minute, second, milliseconds, timezone)
|
||||
timezLiteral.literalExpression = *Literal(timeStr)
|
||||
|
||||
timezLiteral.timezInterfaceImpl.parent = &timezLiteral
|
||||
|
||||
return &timezLiteral
|
||||
return timezLiteral.CAST_TO_TIMEZ()
|
||||
}
|
||||
|
||||
//---------------------------------------------------//
|
||||
|
|
@ -127,7 +127,7 @@ func Timestamp(year, month, day, hour, minute, second, milliseconds int) Timesta
|
|||
|
||||
timestampLiteral.timestampInterfaceImpl.parent = ×tampLiteral
|
||||
|
||||
return ×tampLiteral
|
||||
return timestampLiteral.CAST_TO_TIMESTAMP()
|
||||
}
|
||||
|
||||
//---------------------------------------------------//
|
||||
|
|
@ -145,7 +145,7 @@ func Timestampz(year, month, day, hour, minute, second, milliseconds, timezone i
|
|||
|
||||
timestampzLiteral.timestampzInterfaceImpl.parent = ×tampzLiteral
|
||||
|
||||
return ×tampzLiteral
|
||||
return timestampzLiteral.CAST_TO_TIMESTAMPZ()
|
||||
}
|
||||
|
||||
//---------------------------------------------------//
|
||||
|
|
@ -161,5 +161,5 @@ func Date(year, month, day int) DateExpression {
|
|||
dateLiteral.literalExpression = *Literal(timeStr)
|
||||
dateLiteral.dateInterfaceImpl.parent = &dateLiteral
|
||||
|
||||
return &dateLiteral
|
||||
return dateLiteral.CAST_TO_DATE()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,52 +1,52 @@
|
|||
package sqlbuilder
|
||||
|
||||
type timeExpression interface {
|
||||
type TimeExpression interface {
|
||||
expression
|
||||
|
||||
EQ(rhs timeExpression) BoolExpression
|
||||
NOT_EQ(rhs timeExpression) BoolExpression
|
||||
IS_DISTINCT_FROM(rhs timeExpression) BoolExpression
|
||||
IS_NOT_DISTINCT_FROM(rhs timeExpression) BoolExpression
|
||||
EQ(rhs TimeExpression) BoolExpression
|
||||
NOT_EQ(rhs TimeExpression) BoolExpression
|
||||
IS_DISTINCT_FROM(rhs TimeExpression) BoolExpression
|
||||
IS_NOT_DISTINCT_FROM(rhs TimeExpression) BoolExpression
|
||||
|
||||
LT(rhs timeExpression) BoolExpression
|
||||
LT_EQ(rhs timeExpression) BoolExpression
|
||||
GT(rhs timeExpression) BoolExpression
|
||||
GT_EQ(rhs timeExpression) BoolExpression
|
||||
LT(rhs TimeExpression) BoolExpression
|
||||
LT_EQ(rhs TimeExpression) BoolExpression
|
||||
GT(rhs TimeExpression) BoolExpression
|
||||
GT_EQ(rhs TimeExpression) BoolExpression
|
||||
}
|
||||
|
||||
type timeInterfaceImpl struct {
|
||||
parent timeExpression
|
||||
parent TimeExpression
|
||||
}
|
||||
|
||||
func (t *timeInterfaceImpl) EQ(rhs timeExpression) BoolExpression {
|
||||
func (t *timeInterfaceImpl) EQ(rhs TimeExpression) BoolExpression {
|
||||
return EQ(t.parent, rhs)
|
||||
}
|
||||
|
||||
func (t *timeInterfaceImpl) NOT_EQ(rhs timeExpression) BoolExpression {
|
||||
func (t *timeInterfaceImpl) NOT_EQ(rhs TimeExpression) BoolExpression {
|
||||
return NOT_EQ(t.parent, rhs)
|
||||
}
|
||||
|
||||
func (t *timeInterfaceImpl) IS_DISTINCT_FROM(rhs timeExpression) BoolExpression {
|
||||
func (t *timeInterfaceImpl) IS_DISTINCT_FROM(rhs TimeExpression) BoolExpression {
|
||||
return IS_DISTINCT_FROM(t.parent, rhs)
|
||||
}
|
||||
|
||||
func (t *timeInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs timeExpression) BoolExpression {
|
||||
func (t *timeInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs TimeExpression) BoolExpression {
|
||||
return IS_NOT_DISTINCT_FROM(t.parent, rhs)
|
||||
}
|
||||
|
||||
func (t *timeInterfaceImpl) LT(rhs timeExpression) BoolExpression {
|
||||
func (t *timeInterfaceImpl) LT(rhs TimeExpression) BoolExpression {
|
||||
return LT(t.parent, rhs)
|
||||
}
|
||||
|
||||
func (t *timeInterfaceImpl) LT_EQ(rhs timeExpression) BoolExpression {
|
||||
func (t *timeInterfaceImpl) LT_EQ(rhs TimeExpression) BoolExpression {
|
||||
return LT_EQ(t.parent, rhs)
|
||||
}
|
||||
|
||||
func (t *timeInterfaceImpl) GT(rhs timeExpression) BoolExpression {
|
||||
func (t *timeInterfaceImpl) GT(rhs TimeExpression) BoolExpression {
|
||||
return GT(t.parent, rhs)
|
||||
}
|
||||
|
||||
func (t *timeInterfaceImpl) GT_EQ(rhs timeExpression) BoolExpression {
|
||||
func (t *timeInterfaceImpl) GT_EQ(rhs TimeExpression) BoolExpression {
|
||||
return GT_EQ(t.parent, rhs)
|
||||
}
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ type prefixTimeExpression struct {
|
|||
prefixOpExpression
|
||||
}
|
||||
|
||||
func newPrefixTimeExpression(operator string, expression expression) timeExpression {
|
||||
func newPrefixTimeExpression(operator string, expression expression) TimeExpression {
|
||||
timeExpr := prefixTimeExpression{}
|
||||
timeExpr.prefixOpExpression = newPrefixExpression(expression, operator)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,52 +1,52 @@
|
|||
package sqlbuilder
|
||||
|
||||
type timezExpression interface {
|
||||
type TimezExpression interface {
|
||||
expression
|
||||
|
||||
EQ(rhs timezExpression) BoolExpression
|
||||
NOT_EQ(rhs timezExpression) BoolExpression
|
||||
IS_DISTINCT_FROM(rhs timezExpression) BoolExpression
|
||||
IS_NOT_DISTINCT_FROM(rhs timezExpression) BoolExpression
|
||||
EQ(rhs TimezExpression) BoolExpression
|
||||
NOT_EQ(rhs TimezExpression) BoolExpression
|
||||
IS_DISTINCT_FROM(rhs TimezExpression) BoolExpression
|
||||
IS_NOT_DISTINCT_FROM(rhs TimezExpression) BoolExpression
|
||||
|
||||
LT(rhs timezExpression) BoolExpression
|
||||
LT_EQ(rhs timezExpression) BoolExpression
|
||||
GT(rhs timezExpression) BoolExpression
|
||||
GT_EQ(rhs timezExpression) BoolExpression
|
||||
LT(rhs TimezExpression) BoolExpression
|
||||
LT_EQ(rhs TimezExpression) BoolExpression
|
||||
GT(rhs TimezExpression) BoolExpression
|
||||
GT_EQ(rhs TimezExpression) BoolExpression
|
||||
}
|
||||
|
||||
type timezInterfaceImpl struct {
|
||||
parent timezExpression
|
||||
parent TimezExpression
|
||||
}
|
||||
|
||||
func (t *timezInterfaceImpl) EQ(rhs timezExpression) BoolExpression {
|
||||
func (t *timezInterfaceImpl) EQ(rhs TimezExpression) BoolExpression {
|
||||
return EQ(t.parent, rhs)
|
||||
}
|
||||
|
||||
func (t *timezInterfaceImpl) NOT_EQ(rhs timezExpression) BoolExpression {
|
||||
func (t *timezInterfaceImpl) NOT_EQ(rhs TimezExpression) BoolExpression {
|
||||
return NOT_EQ(t.parent, rhs)
|
||||
}
|
||||
|
||||
func (t *timezInterfaceImpl) IS_DISTINCT_FROM(rhs timezExpression) BoolExpression {
|
||||
func (t *timezInterfaceImpl) IS_DISTINCT_FROM(rhs TimezExpression) BoolExpression {
|
||||
return IS_DISTINCT_FROM(t.parent, rhs)
|
||||
}
|
||||
|
||||
func (t *timezInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs timezExpression) BoolExpression {
|
||||
func (t *timezInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs TimezExpression) BoolExpression {
|
||||
return IS_NOT_DISTINCT_FROM(t.parent, rhs)
|
||||
}
|
||||
|
||||
func (t *timezInterfaceImpl) LT(rhs timezExpression) BoolExpression {
|
||||
func (t *timezInterfaceImpl) LT(rhs TimezExpression) BoolExpression {
|
||||
return LT(t.parent, rhs)
|
||||
}
|
||||
|
||||
func (t *timezInterfaceImpl) LT_EQ(rhs timezExpression) BoolExpression {
|
||||
func (t *timezInterfaceImpl) LT_EQ(rhs TimezExpression) BoolExpression {
|
||||
return LT_EQ(t.parent, rhs)
|
||||
}
|
||||
|
||||
func (t *timezInterfaceImpl) GT(rhs timezExpression) BoolExpression {
|
||||
func (t *timezInterfaceImpl) GT(rhs TimezExpression) BoolExpression {
|
||||
return GT(t.parent, rhs)
|
||||
}
|
||||
|
||||
func (t *timezInterfaceImpl) GT_EQ(rhs timezExpression) BoolExpression {
|
||||
func (t *timezInterfaceImpl) GT_EQ(rhs TimezExpression) BoolExpression {
|
||||
return GT_EQ(t.parent, rhs)
|
||||
}
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ type prefixTimezExpression struct {
|
|||
prefixOpExpression
|
||||
}
|
||||
|
||||
func newPrefixTimezExpression(operator string, expression expression) timezExpression {
|
||||
func newPrefixTimezExpression(operator string, expression expression) TimezExpression {
|
||||
timeExpr := prefixTimezExpression{}
|
||||
timeExpr.prefixOpExpression = newPrefixExpression(expression, operator)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue