Encode json values implicitly in the sql queries according the golang json package spec.
This commit is contained in:
parent
9616bb5cfe
commit
17646ca99c
54 changed files with 1446 additions and 744 deletions
|
|
@ -18,10 +18,45 @@ func (a *alias) fromImpl(subQuery SelectTable) Projection {
|
|||
// Generated columns have default aliasing.
|
||||
tableName, columnName := extractTableAndColumnName(a.alias)
|
||||
|
||||
column := NewColumnImpl(columnName, tableName, nil)
|
||||
column.subQuery = subQuery
|
||||
newDummyColumn := newDummyColumnForExpression(a.expression, columnName)
|
||||
newDummyColumn.setTableName(tableName)
|
||||
newDummyColumn.setSubQuery(subQuery)
|
||||
|
||||
return &column
|
||||
return newDummyColumn
|
||||
}
|
||||
|
||||
// This function is used to create dummy columns when exporting sub-query columns using subQuery.AllColumns()
|
||||
// In most case we don't care about type of the column, except when sub-query columns are used as SELECT_JSON projection.
|
||||
// We need to know type to encode value for json unmarshal. At the moment only bool, time and blob columns are of interest,
|
||||
// so we don't have to support every column type.
|
||||
func newDummyColumnForExpression(exp Expression, name string) ColumnExpression {
|
||||
|
||||
switch exp.(type) {
|
||||
case BoolExpression:
|
||||
return BoolColumn(name)
|
||||
case IntegerExpression:
|
||||
return IntegerColumn(name)
|
||||
case FloatExpression:
|
||||
return FloatColumn(name)
|
||||
case BlobExpression:
|
||||
return BlobColumn(name)
|
||||
case DateExpression:
|
||||
return DateColumn(name)
|
||||
case TimeExpression:
|
||||
return TimeColumn(name)
|
||||
case TimezExpression:
|
||||
return TimezColumn(name)
|
||||
case TimestampExpression:
|
||||
return TimestampColumn(name)
|
||||
case TimestampzExpression:
|
||||
return TimestampzColumn(name)
|
||||
case IntervalExpression:
|
||||
return IntervalColumn(name)
|
||||
case StringExpression:
|
||||
return StringColumn(name)
|
||||
}
|
||||
|
||||
return StringColumn(name)
|
||||
}
|
||||
|
||||
func (a *alias) serializeForProjection(statement StatementType, out *SQLBuilder) {
|
||||
|
|
@ -31,7 +66,14 @@ func (a *alias) serializeForProjection(statement StatementType, out *SQLBuilder)
|
|||
out.WriteAlias(a.alias)
|
||||
}
|
||||
|
||||
func (a *alias) serializeForJsonObj(statement StatementType, out *SQLBuilder) {
|
||||
func (a *alias) serializeForJsonObjEntry(statement StatementType, out *SQLBuilder) {
|
||||
out.WriteJsonObjKey(a.alias)
|
||||
a.expression.serialize(statement, out)
|
||||
a.expression.serializeForJsonValue(statement, out)
|
||||
}
|
||||
|
||||
func (a *alias) serializeForRowToJsonProjection(statement StatementType, out *SQLBuilder) {
|
||||
a.expression.serializeForJsonValue(statement, out)
|
||||
|
||||
out.WriteString("AS")
|
||||
out.WriteAlias(a.alias)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,71 +28,72 @@ type blobInterfaceImpl struct {
|
|||
parent BlobExpression
|
||||
}
|
||||
|
||||
func (s *blobInterfaceImpl) isStringOrBlob() {}
|
||||
func (b *blobInterfaceImpl) isStringOrBlob() {}
|
||||
|
||||
func (s *blobInterfaceImpl) EQ(rhs BlobExpression) BoolExpression {
|
||||
return Eq(s.parent, rhs)
|
||||
func (b *blobInterfaceImpl) EQ(rhs BlobExpression) BoolExpression {
|
||||
return Eq(b.parent, rhs)
|
||||
}
|
||||
|
||||
func (s *blobInterfaceImpl) NOT_EQ(rhs BlobExpression) BoolExpression {
|
||||
return NotEq(s.parent, rhs)
|
||||
func (b *blobInterfaceImpl) NOT_EQ(rhs BlobExpression) BoolExpression {
|
||||
return NotEq(b.parent, rhs)
|
||||
}
|
||||
|
||||
func (s *blobInterfaceImpl) IS_DISTINCT_FROM(rhs BlobExpression) BoolExpression {
|
||||
return IsDistinctFrom(s.parent, rhs)
|
||||
func (b *blobInterfaceImpl) IS_DISTINCT_FROM(rhs BlobExpression) BoolExpression {
|
||||
return IsDistinctFrom(b.parent, rhs)
|
||||
}
|
||||
|
||||
func (s *blobInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs BlobExpression) BoolExpression {
|
||||
return IsNotDistinctFrom(s.parent, rhs)
|
||||
func (b *blobInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs BlobExpression) BoolExpression {
|
||||
return IsNotDistinctFrom(b.parent, rhs)
|
||||
}
|
||||
|
||||
func (s *blobInterfaceImpl) GT(rhs BlobExpression) BoolExpression {
|
||||
return Gt(s.parent, rhs)
|
||||
func (b *blobInterfaceImpl) GT(rhs BlobExpression) BoolExpression {
|
||||
return Gt(b.parent, rhs)
|
||||
}
|
||||
|
||||
func (s *blobInterfaceImpl) GT_EQ(rhs BlobExpression) BoolExpression {
|
||||
return GtEq(s.parent, rhs)
|
||||
func (b *blobInterfaceImpl) GT_EQ(rhs BlobExpression) BoolExpression {
|
||||
return GtEq(b.parent, rhs)
|
||||
}
|
||||
|
||||
func (s *blobInterfaceImpl) LT(rhs BlobExpression) BoolExpression {
|
||||
return Lt(s.parent, rhs)
|
||||
func (b *blobInterfaceImpl) LT(rhs BlobExpression) BoolExpression {
|
||||
return Lt(b.parent, rhs)
|
||||
}
|
||||
|
||||
func (s *blobInterfaceImpl) LT_EQ(rhs BlobExpression) BoolExpression {
|
||||
return LtEq(s.parent, rhs)
|
||||
func (b *blobInterfaceImpl) LT_EQ(rhs BlobExpression) BoolExpression {
|
||||
return LtEq(b.parent, rhs)
|
||||
}
|
||||
|
||||
func (s *blobInterfaceImpl) BETWEEN(min, max BlobExpression) BoolExpression {
|
||||
return NewBetweenOperatorExpression(s.parent, min, max, false)
|
||||
func (b *blobInterfaceImpl) BETWEEN(min, max BlobExpression) BoolExpression {
|
||||
return NewBetweenOperatorExpression(b.parent, min, max, false)
|
||||
}
|
||||
|
||||
func (s *blobInterfaceImpl) NOT_BETWEEN(min, max BlobExpression) BoolExpression {
|
||||
return NewBetweenOperatorExpression(s.parent, min, max, true)
|
||||
func (b *blobInterfaceImpl) NOT_BETWEEN(min, max BlobExpression) BoolExpression {
|
||||
return NewBetweenOperatorExpression(b.parent, min, max, true)
|
||||
}
|
||||
|
||||
func (s *blobInterfaceImpl) CONCAT(rhs BlobExpression) BlobExpression {
|
||||
return BlobExp(newBinaryStringOperatorExpression(s.parent, rhs, StringConcatOperator))
|
||||
func (b *blobInterfaceImpl) CONCAT(rhs BlobExpression) BlobExpression {
|
||||
return BlobExp(newBinaryStringOperatorExpression(b.parent, rhs, StringConcatOperator))
|
||||
}
|
||||
|
||||
func (s *blobInterfaceImpl) LIKE(pattern BlobExpression) BoolExpression {
|
||||
return newBinaryBoolOperatorExpression(s.parent, pattern, "LIKE")
|
||||
func (b *blobInterfaceImpl) LIKE(pattern BlobExpression) BoolExpression {
|
||||
return newBinaryBoolOperatorExpression(b.parent, pattern, "LIKE")
|
||||
}
|
||||
|
||||
func (s *blobInterfaceImpl) NOT_LIKE(pattern BlobExpression) BoolExpression {
|
||||
return newBinaryBoolOperatorExpression(s.parent, pattern, "NOT LIKE")
|
||||
func (b *blobInterfaceImpl) NOT_LIKE(pattern BlobExpression) BoolExpression {
|
||||
return newBinaryBoolOperatorExpression(b.parent, pattern, "NOT LIKE")
|
||||
}
|
||||
|
||||
//---------------------------------------------------//
|
||||
|
||||
type blobExpressionWrapper struct {
|
||||
blobInterfaceImpl
|
||||
Expression
|
||||
blobInterfaceImpl
|
||||
}
|
||||
|
||||
func newBlobExpressionWrap(expression Expression) BlobExpression {
|
||||
blobExpressionWrap := blobExpressionWrapper{Expression: expression}
|
||||
blobExpressionWrap.blobInterfaceImpl.parent = &blobExpressionWrap
|
||||
return &blobExpressionWrap
|
||||
blobExpressionWrap := &blobExpressionWrapper{Expression: expression}
|
||||
blobExpressionWrap.blobInterfaceImpl.parent = blobExpressionWrap
|
||||
expression.setParent(blobExpressionWrap)
|
||||
return blobExpressionWrap
|
||||
}
|
||||
|
||||
// BlobExp is blob expression wrapper around arbitrary expression.
|
||||
|
|
|
|||
|
|
@ -102,9 +102,10 @@ type boolExpressionWrapper struct {
|
|||
}
|
||||
|
||||
func newBoolExpressionWrap(expression Expression) BoolExpression {
|
||||
boolExpressionWrap := boolExpressionWrapper{Expression: expression}
|
||||
boolExpressionWrap.boolInterfaceImpl.parent = &boolExpressionWrap
|
||||
return &boolExpressionWrap
|
||||
boolExpressionWrap := &boolExpressionWrapper{Expression: expression}
|
||||
boolExpressionWrap.boolInterfaceImpl.parent = boolExpressionWrap
|
||||
expression.setParent(boolExpressionWrap)
|
||||
return boolExpressionWrap
|
||||
}
|
||||
|
||||
// BoolExp is bool expression wrapper around arbitrary expression.
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ type ClauseSelect struct {
|
|||
DistinctOnColumns []ColumnExpression
|
||||
ProjectionList []Projection
|
||||
|
||||
IsForRowToJson bool
|
||||
|
||||
// MySQL only
|
||||
OptimizerHints optimizerHints
|
||||
}
|
||||
|
|
@ -70,7 +72,13 @@ func (s *ClauseSelect) Serialize(statementType StatementType, out *SQLBuilder, o
|
|||
out.WriteByte(')')
|
||||
}
|
||||
|
||||
out.WriteProjections(statementType, s.ProjectionList)
|
||||
if s.IsForRowToJson {
|
||||
out.IncreaseIdent()
|
||||
out.WriteRowToJsonProjections(statementType, s.ProjectionList)
|
||||
out.DecreaseIdent()
|
||||
} else {
|
||||
out.WriteProjections(statementType, s.ProjectionList)
|
||||
}
|
||||
}
|
||||
|
||||
// ClauseFrom struct
|
||||
|
|
|
|||
|
|
@ -39,19 +39,19 @@ type ColumnExpressionImpl struct {
|
|||
}
|
||||
|
||||
// NewColumnImpl creates new ColumnExpressionImpl
|
||||
func NewColumnImpl(name string, tableName string, parent ColumnExpression) ColumnExpressionImpl {
|
||||
bc := ColumnExpressionImpl{
|
||||
func NewColumnImpl(name string, tableName string, parent ColumnExpression) *ColumnExpressionImpl {
|
||||
newColumn := &ColumnExpressionImpl{
|
||||
name: name,
|
||||
tableName: tableName,
|
||||
}
|
||||
|
||||
if parent != nil {
|
||||
bc.ExpressionInterfaceImpl.Parent = parent
|
||||
newColumn.ExpressionInterfaceImpl.Parent = parent
|
||||
} else {
|
||||
bc.ExpressionInterfaceImpl.Parent = &bc
|
||||
newColumn.ExpressionInterfaceImpl.Parent = newColumn
|
||||
}
|
||||
|
||||
return bc
|
||||
return newColumn
|
||||
}
|
||||
|
||||
// Name returns name of the column
|
||||
|
|
@ -80,13 +80,6 @@ func (c *ColumnExpressionImpl) defaultAlias() string {
|
|||
return c.name
|
||||
}
|
||||
|
||||
func (c *ColumnExpressionImpl) fromImpl(subQuery SelectTable) Projection {
|
||||
newColumn := NewColumnImpl(c.name, c.tableName, nil)
|
||||
newColumn.setSubQuery(subQuery)
|
||||
|
||||
return &newColumn
|
||||
}
|
||||
|
||||
func (c *ColumnExpressionImpl) serializeForOrderBy(statement StatementType, out *SQLBuilder) {
|
||||
if statement == SetStatementType {
|
||||
// set Statement (UNION, EXCEPT ...) can reference only select projections in order by clause
|
||||
|
|
@ -97,24 +90,28 @@ func (c *ColumnExpressionImpl) serializeForOrderBy(statement StatementType, out
|
|||
c.serialize(statement, out)
|
||||
}
|
||||
|
||||
func (c ColumnExpressionImpl) serializeForProjection(statement StatementType, out *SQLBuilder) {
|
||||
func (c *ColumnExpressionImpl) serializeForProjection(statement StatementType, out *SQLBuilder) {
|
||||
c.serialize(statement, out)
|
||||
|
||||
out.WriteString("AS")
|
||||
|
||||
if statement.IsSelectJSON() {
|
||||
out.WriteAlias(snaker.SnakeToCamel(c.name, false))
|
||||
} else {
|
||||
out.WriteAlias(c.defaultAlias())
|
||||
}
|
||||
out.WriteAlias(c.defaultAlias())
|
||||
}
|
||||
|
||||
func (c ColumnExpressionImpl) serializeForJsonObj(statement StatementType, out *SQLBuilder) {
|
||||
func (c *ColumnExpressionImpl) serializeForJsonObjEntry(statement StatementType, out *SQLBuilder) {
|
||||
out.WriteJsonObjKey(snaker.SnakeToCamel(c.name, false))
|
||||
c.serialize(statement, out)
|
||||
c.Parent.serializeForJsonValue(statement, out)
|
||||
}
|
||||
|
||||
func (c ColumnExpressionImpl) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
func (c *ColumnExpressionImpl) serializeForRowToJsonProjection(statement StatementType, out *SQLBuilder) {
|
||||
c.Parent.serializeForJsonValue(statement, out)
|
||||
|
||||
out.WriteString("AS")
|
||||
|
||||
out.WriteAlias(snaker.SnakeToCamel(c.name, false))
|
||||
}
|
||||
|
||||
func (c *ColumnExpressionImpl) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
|
||||
if c.subQuery != nil {
|
||||
out.WriteIdentifier(c.subQuery.Alias())
|
||||
|
|
|
|||
|
|
@ -78,12 +78,18 @@ func (cl ColumnList) serializeForProjection(statement StatementType, out *SQLBui
|
|||
SerializeProjectionList(statement, projections, out)
|
||||
}
|
||||
|
||||
func (cl ColumnList) serializeForJsonObj(statement StatementType, out *SQLBuilder) {
|
||||
func (cl ColumnList) serializeForJsonObjEntry(statement StatementType, out *SQLBuilder) {
|
||||
projections := ColumnListToProjectionList(cl)
|
||||
|
||||
SerializeProjectionListJsonObj(statement, projections, out)
|
||||
}
|
||||
|
||||
func (cl ColumnList) serializeForRowToJsonProjection(statement StatementType, out *SQLBuilder) {
|
||||
projections := ColumnListToProjectionList(cl)
|
||||
|
||||
out.WriteRowToJsonProjections(statement, projections)
|
||||
}
|
||||
|
||||
// dummy column interface implementation
|
||||
|
||||
// Name is placeholder for ColumnList to implement Column interface
|
||||
|
|
|
|||
|
|
@ -4,11 +4,10 @@ import "testing"
|
|||
|
||||
func TestColumn(t *testing.T) {
|
||||
column := NewColumnImpl("col", "", nil)
|
||||
column.ExpressionInterfaceImpl.Parent = &column
|
||||
|
||||
assertClauseSerialize(t, column, "col")
|
||||
column.setTableName("table1")
|
||||
assertClauseSerialize(t, column, "table1.col")
|
||||
assertProjectionSerialize(t, &column, `table1.col AS "table1.col"`)
|
||||
assertProjectionSerialize(t, column, `table1.col AS "table1.col"`)
|
||||
assertProjectionSerialize(t, column.AS("alias1"), `table1.col AS "alias1"`)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,11 @@ type ColumnBool interface {
|
|||
|
||||
type boolColumnImpl struct {
|
||||
boolInterfaceImpl
|
||||
ColumnExpressionImpl
|
||||
*ColumnExpressionImpl
|
||||
}
|
||||
|
||||
func (i *boolColumnImpl) fromImpl(subQuery SelectTable) Projection {
|
||||
return i.From(subQuery)
|
||||
}
|
||||
|
||||
func (i *boolColumnImpl) From(subQuery SelectTable) ColumnBool {
|
||||
|
|
@ -51,7 +55,11 @@ type ColumnFloat interface {
|
|||
|
||||
type floatColumnImpl struct {
|
||||
floatInterfaceImpl
|
||||
ColumnExpressionImpl
|
||||
*ColumnExpressionImpl
|
||||
}
|
||||
|
||||
func (i *floatColumnImpl) fromImpl(subQuery SelectTable) Projection {
|
||||
return i.From(subQuery)
|
||||
}
|
||||
|
||||
func (i *floatColumnImpl) From(subQuery SelectTable) ColumnFloat {
|
||||
|
|
@ -92,7 +100,11 @@ type ColumnInteger interface {
|
|||
type integerColumnImpl struct {
|
||||
integerInterfaceImpl
|
||||
|
||||
ColumnExpressionImpl
|
||||
*ColumnExpressionImpl
|
||||
}
|
||||
|
||||
func (i *integerColumnImpl) fromImpl(subQuery SelectTable) Projection {
|
||||
return i.From(subQuery)
|
||||
}
|
||||
|
||||
func (i *integerColumnImpl) From(subQuery SelectTable) ColumnInteger {
|
||||
|
|
@ -134,7 +146,11 @@ type ColumnString interface {
|
|||
type stringColumnImpl struct {
|
||||
stringInterfaceImpl
|
||||
|
||||
ColumnExpressionImpl
|
||||
*ColumnExpressionImpl
|
||||
}
|
||||
|
||||
func (i *stringColumnImpl) fromImpl(subQuery SelectTable) Projection {
|
||||
return i.From(subQuery)
|
||||
}
|
||||
|
||||
func (i *stringColumnImpl) From(subQuery SelectTable) ColumnString {
|
||||
|
|
@ -175,7 +191,11 @@ type ColumnBlob interface {
|
|||
type blobColumnImpl struct {
|
||||
blobInterfaceImpl
|
||||
|
||||
ColumnExpressionImpl
|
||||
*ColumnExpressionImpl
|
||||
}
|
||||
|
||||
func (i *blobColumnImpl) fromImpl(subQuery SelectTable) Projection {
|
||||
return i.From(subQuery)
|
||||
}
|
||||
|
||||
func (i *blobColumnImpl) From(subQuery SelectTable) ColumnBlob {
|
||||
|
|
@ -215,7 +235,11 @@ type ColumnTime interface {
|
|||
|
||||
type timeColumnImpl struct {
|
||||
timeInterfaceImpl
|
||||
ColumnExpressionImpl
|
||||
*ColumnExpressionImpl
|
||||
}
|
||||
|
||||
func (i *timeColumnImpl) fromImpl(subQuery SelectTable) Projection {
|
||||
return i.From(subQuery)
|
||||
}
|
||||
|
||||
func (i *timeColumnImpl) From(subQuery SelectTable) ColumnTime {
|
||||
|
|
@ -254,7 +278,11 @@ type ColumnTimez interface {
|
|||
|
||||
type timezColumnImpl struct {
|
||||
timezInterfaceImpl
|
||||
ColumnExpressionImpl
|
||||
*ColumnExpressionImpl
|
||||
}
|
||||
|
||||
func (i *timezColumnImpl) fromImpl(subQuery SelectTable) Projection {
|
||||
return i.From(subQuery)
|
||||
}
|
||||
|
||||
func (i *timezColumnImpl) From(subQuery SelectTable) ColumnTimez {
|
||||
|
|
@ -294,7 +322,11 @@ type ColumnTimestamp interface {
|
|||
|
||||
type timestampColumnImpl struct {
|
||||
timestampInterfaceImpl
|
||||
ColumnExpressionImpl
|
||||
*ColumnExpressionImpl
|
||||
}
|
||||
|
||||
func (i *timestampColumnImpl) fromImpl(subQuery SelectTable) Projection {
|
||||
return i.From(subQuery)
|
||||
}
|
||||
|
||||
func (i *timestampColumnImpl) From(subQuery SelectTable) ColumnTimestamp {
|
||||
|
|
@ -334,7 +366,11 @@ type ColumnTimestampz interface {
|
|||
|
||||
type timestampzColumnImpl struct {
|
||||
timestampzInterfaceImpl
|
||||
ColumnExpressionImpl
|
||||
*ColumnExpressionImpl
|
||||
}
|
||||
|
||||
func (i *timestampzColumnImpl) fromImpl(subQuery SelectTable) Projection {
|
||||
return i.From(subQuery)
|
||||
}
|
||||
|
||||
func (i *timestampzColumnImpl) From(subQuery SelectTable) ColumnTimestampz {
|
||||
|
|
@ -374,7 +410,11 @@ type ColumnDate interface {
|
|||
|
||||
type dateColumnImpl struct {
|
||||
dateInterfaceImpl
|
||||
ColumnExpressionImpl
|
||||
*ColumnExpressionImpl
|
||||
}
|
||||
|
||||
func (i *dateColumnImpl) fromImpl(subQuery SelectTable) Projection {
|
||||
return i.From(subQuery)
|
||||
}
|
||||
|
||||
func (i *dateColumnImpl) From(subQuery SelectTable) ColumnDate {
|
||||
|
|
@ -402,6 +442,51 @@ func DateColumn(name string) ColumnDate {
|
|||
|
||||
//------------------------------------------------------//
|
||||
|
||||
// ColumnInterval is interface of PostgreSQL interval columns.
|
||||
type ColumnInterval interface {
|
||||
IntervalExpression
|
||||
Column
|
||||
|
||||
From(subQuery SelectTable) ColumnInterval
|
||||
SET(intervalExp IntervalExpression) ColumnAssigment
|
||||
}
|
||||
|
||||
//------------------------------------------------------//
|
||||
|
||||
type intervalColumnImpl struct {
|
||||
*ColumnExpressionImpl
|
||||
intervalInterfaceImpl
|
||||
}
|
||||
|
||||
func (i *intervalColumnImpl) SET(intervalExp IntervalExpression) ColumnAssigment {
|
||||
return columnAssigmentImpl{
|
||||
column: i,
|
||||
expression: intervalExp,
|
||||
}
|
||||
}
|
||||
|
||||
func (i *intervalColumnImpl) fromImpl(subQuery SelectTable) Projection {
|
||||
return i.From(subQuery)
|
||||
}
|
||||
|
||||
func (i *intervalColumnImpl) From(subQuery SelectTable) ColumnInterval {
|
||||
newIntervalColumn := IntervalColumn(i.name)
|
||||
newIntervalColumn.setTableName(i.tableName)
|
||||
newIntervalColumn.setSubQuery(subQuery)
|
||||
|
||||
return newIntervalColumn
|
||||
}
|
||||
|
||||
// IntervalColumn creates named interval column.
|
||||
func IntervalColumn(name string) ColumnInterval {
|
||||
intervalColumn := &intervalColumnImpl{}
|
||||
intervalColumn.ColumnExpressionImpl = NewColumnImpl(name, "", intervalColumn)
|
||||
intervalColumn.intervalInterfaceImpl.parent = intervalColumn
|
||||
return intervalColumn
|
||||
}
|
||||
|
||||
//------------------------------------------------------//
|
||||
|
||||
// ColumnRange is interface for range columns which can be int range, string range
|
||||
// timestamp range or date range.
|
||||
type ColumnRange[T Expression] interface {
|
||||
|
|
@ -414,7 +499,11 @@ type ColumnRange[T Expression] interface {
|
|||
|
||||
type rangeColumnImpl[T Expression] struct {
|
||||
rangeInterfaceImpl[T]
|
||||
ColumnExpressionImpl
|
||||
*ColumnExpressionImpl
|
||||
}
|
||||
|
||||
func (i *rangeColumnImpl[T]) fromImpl(subQuery SelectTable) Projection {
|
||||
return i.From(subQuery)
|
||||
}
|
||||
|
||||
func (i *rangeColumnImpl[T]) From(subQuery SelectTable) ColumnRange[T] {
|
||||
|
|
|
|||
|
|
@ -80,9 +80,10 @@ type dateExpressionWrapper struct {
|
|||
}
|
||||
|
||||
func newDateExpressionWrap(expression Expression) DateExpression {
|
||||
dateExpressionWrap := dateExpressionWrapper{Expression: expression}
|
||||
dateExpressionWrap.dateInterfaceImpl.parent = &dateExpressionWrap
|
||||
return &dateExpressionWrap
|
||||
dateExpressionWrap := &dateExpressionWrapper{Expression: expression}
|
||||
dateExpressionWrap.dateInterfaceImpl.parent = dateExpressionWrap
|
||||
expression.setParent(dateExpressionWrap)
|
||||
return dateExpressionWrap
|
||||
}
|
||||
|
||||
// DateExp is date expression wrapper around arbitrary expression.
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
package jet
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDateArithmetic(t *testing.T) {
|
||||
timestamp := Timestamp(2000, 1, 1, 0, 0, 0)
|
||||
assertClauseDebugSerialize(t, table1ColDate.ADD(NewInterval(String("1 HOUR"))).EQ(timestamp),
|
||||
"((table1.col_date + INTERVAL '1 HOUR') = '2000-01-01 00:00:00')")
|
||||
assertClauseDebugSerialize(t, table1ColDate.SUB(NewInterval(String("1 HOUR"))).EQ(timestamp),
|
||||
"((table1.col_date - INTERVAL '1 HOUR') = '2000-01-01 00:00:00')")
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@ type Dialect interface {
|
|||
IsReservedWord(name string) bool
|
||||
SerializeOrderBy() func(expression Expression, ascending, nullsFirst *bool) SerializerFunc
|
||||
ValuesDefaultColumnName(index int) string
|
||||
JsonValueEncode(expr Expression) Expression
|
||||
}
|
||||
|
||||
// SerializerFunc func
|
||||
|
|
@ -41,6 +42,7 @@ type DialectParams struct {
|
|||
ReservedWords []string
|
||||
SerializeOrderBy func(expression Expression, ascending, nullsFirst *bool) SerializerFunc
|
||||
ValuesDefaultColumnName func(index int) string
|
||||
JsonValueEncode func(expr Expression) Expression
|
||||
}
|
||||
|
||||
// NewDialect creates new dialect with params
|
||||
|
|
@ -57,6 +59,7 @@ func NewDialect(params DialectParams) Dialect {
|
|||
reservedWords: arrayOfStringsToMapOfStrings(params.ReservedWords),
|
||||
serializeOrderBy: params.SerializeOrderBy,
|
||||
valuesDefaultColumnName: params.ValuesDefaultColumnName,
|
||||
jsonValueEncode: params.JsonValueEncode,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -72,6 +75,7 @@ type dialectImpl struct {
|
|||
reservedWords map[string]bool
|
||||
serializeOrderBy func(expression Expression, ascending, nullsFirst *bool) SerializerFunc
|
||||
valuesDefaultColumnName func(index int) string
|
||||
jsonValueEncode func(expr Expression) Expression
|
||||
}
|
||||
|
||||
func (d *dialectImpl) Name() string {
|
||||
|
|
@ -125,6 +129,10 @@ func (d *dialectImpl) ValuesDefaultColumnName(index int) string {
|
|||
return d.valuesDefaultColumnName(index)
|
||||
}
|
||||
|
||||
func (d *dialectImpl) JsonValueEncode(expr Expression) Expression {
|
||||
return d.jsonValueEncode(expr)
|
||||
}
|
||||
|
||||
func arrayOfStringsToMapOfStrings(arr []string) map[string]bool {
|
||||
ret := map[string]bool{}
|
||||
for _, elem := range arr {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ type Expression interface {
|
|||
GroupByClause
|
||||
OrderByClause
|
||||
|
||||
serializeForJsonValue(statement StatementType, out *SQLBuilder)
|
||||
setParent(parent Expression)
|
||||
|
||||
// IS_NULL tests expression whether it is a NULL value.
|
||||
IS_NULL() BoolExpression
|
||||
// IS_NOT_NULL tests expression whether it is a non-NULL value.
|
||||
|
|
@ -34,6 +37,10 @@ type ExpressionInterfaceImpl struct {
|
|||
Parent Expression
|
||||
}
|
||||
|
||||
func (e *ExpressionInterfaceImpl) setParent(parent Expression) {
|
||||
e.Parent = parent
|
||||
}
|
||||
|
||||
func (e *ExpressionInterfaceImpl) fromImpl(subQuery SelectTable) Projection {
|
||||
panic(fmt.Sprintf("jet: can't export unaliased expression subQuery: %s, expression: %s",
|
||||
subQuery.Alias(), serializeToDefaultDebugString(e.Parent)))
|
||||
|
|
@ -89,16 +96,21 @@ func (e *ExpressionInterfaceImpl) serializeForGroupBy(statement StatementType, o
|
|||
}
|
||||
|
||||
func (e *ExpressionInterfaceImpl) serializeForProjection(statement StatementType, out *SQLBuilder) {
|
||||
if statement.IsSelectJSON() {
|
||||
panic("jet: expression need to be aliased when used as SELECT JSON projection.")
|
||||
}
|
||||
e.Parent.serialize(statement, out, NoWrap)
|
||||
}
|
||||
|
||||
func (e *ExpressionInterfaceImpl) serializeForJsonObj(statement StatementType, out *SQLBuilder) {
|
||||
func (e *ExpressionInterfaceImpl) serializeForJsonObjEntry(statement StatementType, out *SQLBuilder) {
|
||||
panic("jet: expression need to be aliased when used as SELECT JSON projection.")
|
||||
}
|
||||
|
||||
func (e *ExpressionInterfaceImpl) serializeForRowToJsonProjection(statement StatementType, out *SQLBuilder) {
|
||||
panic("jet: expression need to be aliased when used as SELECT JSON projection.")
|
||||
}
|
||||
|
||||
func (e *ExpressionInterfaceImpl) serializeForJsonValue(statement StatementType, out *SQLBuilder) {
|
||||
out.Dialect.JsonValueEncode(e.Parent).serialize(statement, out)
|
||||
}
|
||||
|
||||
func (e *ExpressionInterfaceImpl) serializeForOrderBy(statement StatementType, out *SQLBuilder) {
|
||||
e.Parent.serialize(statement, out, NoWrap)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,9 +102,10 @@ type floatExpressionWrapper struct {
|
|||
}
|
||||
|
||||
func newFloatExpressionWrap(expression Expression) FloatExpression {
|
||||
floatExpressionWrap := floatExpressionWrapper{Expression: expression}
|
||||
floatExpressionWrap.floatInterfaceImpl.parent = &floatExpressionWrap
|
||||
return &floatExpressionWrap
|
||||
floatExpressionWrap := &floatExpressionWrapper{Expression: expression}
|
||||
floatExpressionWrap.floatInterfaceImpl.parent = floatExpressionWrap
|
||||
expression.setParent(floatExpressionWrap)
|
||||
return floatExpressionWrap
|
||||
}
|
||||
|
||||
// FloatExp is date expression wrapper around arbitrary expression.
|
||||
|
|
|
|||
|
|
@ -141,11 +141,11 @@ type integerExpressionWrapper struct {
|
|||
}
|
||||
|
||||
func newIntExpressionWrap(expression Expression) IntegerExpression {
|
||||
intExpressionWrap := integerExpressionWrapper{Expression: expression}
|
||||
intExpressionWrap := &integerExpressionWrapper{Expression: expression}
|
||||
intExpressionWrap.integerInterfaceImpl.parent = intExpressionWrap
|
||||
expression.setParent(intExpressionWrap)
|
||||
|
||||
intExpressionWrap.integerInterfaceImpl.parent = &intExpressionWrap
|
||||
|
||||
return &intExpressionWrap
|
||||
return intExpressionWrap
|
||||
}
|
||||
|
||||
// IntExp is int expression wrapper around arbitrary expression.
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
package jet
|
||||
|
||||
// Interval is internal common representation of sql interval
|
||||
type Interval interface {
|
||||
Serializer
|
||||
IsInterval
|
||||
}
|
||||
|
||||
// IsInterval interface
|
||||
type IsInterval interface {
|
||||
isInterval()
|
||||
}
|
||||
|
||||
// IsIntervalImpl is implementation of IsInterval interface
|
||||
type IsIntervalImpl struct{}
|
||||
|
||||
func (i *IsIntervalImpl) isInterval() {}
|
||||
|
||||
// NewInterval creates new interval from serializer
|
||||
func NewInterval(s Serializer) *IntervalImpl {
|
||||
newInterval := &IntervalImpl{
|
||||
Value: s,
|
||||
}
|
||||
|
||||
return newInterval
|
||||
}
|
||||
|
||||
// IntervalImpl is implementation of Interval type
|
||||
type IntervalImpl struct {
|
||||
Value Serializer
|
||||
IsIntervalImpl
|
||||
}
|
||||
|
||||
func (i IntervalImpl) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
out.WriteString("INTERVAL")
|
||||
i.Value.serialize(statement, out, FallTrough(options)...)
|
||||
}
|
||||
112
internal/jet/interval_expression.go
Normal file
112
internal/jet/interval_expression.go
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
package jet
|
||||
|
||||
// IntervalExpression interface
|
||||
type IntervalExpression interface {
|
||||
Expression
|
||||
isInterval()
|
||||
|
||||
EQ(rhs IntervalExpression) BoolExpression
|
||||
NOT_EQ(rhs IntervalExpression) BoolExpression
|
||||
IS_DISTINCT_FROM(rhs IntervalExpression) BoolExpression
|
||||
IS_NOT_DISTINCT_FROM(rhs IntervalExpression) BoolExpression
|
||||
|
||||
LT(rhs IntervalExpression) BoolExpression
|
||||
LT_EQ(rhs IntervalExpression) BoolExpression
|
||||
GT(rhs IntervalExpression) BoolExpression
|
||||
GT_EQ(rhs IntervalExpression) BoolExpression
|
||||
BETWEEN(min, max IntervalExpression) BoolExpression
|
||||
NOT_BETWEEN(min, max IntervalExpression) BoolExpression
|
||||
|
||||
ADD(rhs IntervalExpression) IntervalExpression
|
||||
SUB(rhs IntervalExpression) IntervalExpression
|
||||
|
||||
MUL(rhs NumericExpression) IntervalExpression
|
||||
DIV(rhs NumericExpression) IntervalExpression
|
||||
}
|
||||
|
||||
type intervalInterfaceImpl struct {
|
||||
parent IntervalExpression
|
||||
}
|
||||
|
||||
func (i *intervalInterfaceImpl) isInterval() {}
|
||||
|
||||
func (i *intervalInterfaceImpl) EQ(rhs IntervalExpression) BoolExpression {
|
||||
return Eq(i.parent, rhs)
|
||||
}
|
||||
|
||||
func (i *intervalInterfaceImpl) NOT_EQ(rhs IntervalExpression) BoolExpression {
|
||||
return NotEq(i.parent, rhs)
|
||||
}
|
||||
|
||||
func (i *intervalInterfaceImpl) IS_DISTINCT_FROM(rhs IntervalExpression) BoolExpression {
|
||||
return IsDistinctFrom(i.parent, rhs)
|
||||
}
|
||||
|
||||
func (i *intervalInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs IntervalExpression) BoolExpression {
|
||||
return IsNotDistinctFrom(i.parent, rhs)
|
||||
}
|
||||
|
||||
func (i *intervalInterfaceImpl) LT(rhs IntervalExpression) BoolExpression {
|
||||
return Lt(i.parent, rhs)
|
||||
}
|
||||
|
||||
func (i *intervalInterfaceImpl) LT_EQ(rhs IntervalExpression) BoolExpression {
|
||||
return LtEq(i.parent, rhs)
|
||||
}
|
||||
|
||||
func (i *intervalInterfaceImpl) GT(rhs IntervalExpression) BoolExpression {
|
||||
return Gt(i.parent, rhs)
|
||||
}
|
||||
|
||||
func (i *intervalInterfaceImpl) GT_EQ(rhs IntervalExpression) BoolExpression {
|
||||
return GtEq(i.parent, rhs)
|
||||
}
|
||||
|
||||
func (i *intervalInterfaceImpl) BETWEEN(min, max IntervalExpression) BoolExpression {
|
||||
return NewBetweenOperatorExpression(i.parent, min, max, false)
|
||||
}
|
||||
|
||||
func (i *intervalInterfaceImpl) NOT_BETWEEN(min, max IntervalExpression) BoolExpression {
|
||||
return NewBetweenOperatorExpression(i.parent, min, max, true)
|
||||
}
|
||||
|
||||
func (i *intervalInterfaceImpl) ADD(rhs IntervalExpression) IntervalExpression {
|
||||
return IntervalExp(Add(i.parent, rhs))
|
||||
}
|
||||
|
||||
func (i *intervalInterfaceImpl) SUB(rhs IntervalExpression) IntervalExpression {
|
||||
return IntervalExp(Sub(i.parent, rhs))
|
||||
}
|
||||
|
||||
func (i *intervalInterfaceImpl) MUL(rhs NumericExpression) IntervalExpression {
|
||||
return IntervalExp(Mul(i.parent, rhs))
|
||||
}
|
||||
|
||||
func (i *intervalInterfaceImpl) DIV(rhs NumericExpression) IntervalExpression {
|
||||
return IntervalExp(Div(i.parent, rhs))
|
||||
}
|
||||
|
||||
type intervalWrapper struct {
|
||||
intervalInterfaceImpl
|
||||
Expression
|
||||
}
|
||||
|
||||
func newIntervalExpressionWrap(expression Expression) IntervalExpression {
|
||||
intervalWrap := &intervalWrapper{Expression: expression}
|
||||
intervalWrap.intervalInterfaceImpl.parent = intervalWrap
|
||||
expression.setParent(intervalWrap)
|
||||
return intervalWrap
|
||||
}
|
||||
|
||||
// IntervalExp is interval expression wrapper around arbitrary expression.
|
||||
// Allows go compiler to see any expression as interval expression.
|
||||
// Does not add sql cast to generated sql builder output.
|
||||
func IntervalExp(expression Expression) IntervalExpression {
|
||||
return newIntervalExpressionWrap(expression)
|
||||
}
|
||||
|
||||
// Interval interface
|
||||
type Interval interface {
|
||||
Serializer
|
||||
isInterval()
|
||||
}
|
||||
|
|
@ -412,17 +412,6 @@ func Raw(raw string, namedArgs ...map[string]interface{}) Expression {
|
|||
return rawExp
|
||||
}
|
||||
|
||||
// RawWithParent is a Raw constructor used for construction dialect specific expression
|
||||
func RawWithParent(raw string, parent ...Expression) Expression {
|
||||
rawExp := &rawExpression{
|
||||
Raw: raw,
|
||||
noWrap: true,
|
||||
}
|
||||
rawExp.ExpressionInterfaceImpl.Parent = OptionalOrDefaultExpression(rawExp, parent...)
|
||||
|
||||
return rawExp
|
||||
}
|
||||
|
||||
// RawBool helper that for raw string boolean expressions
|
||||
func RawBool(raw string, namedArgs ...map[string]interface{}) BoolExpression {
|
||||
return BoolExp(Raw(raw, namedArgs...))
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ package jet
|
|||
// Projection is interface for all projection types. Types that can be part of, for instance SELECT clause.
|
||||
type Projection interface {
|
||||
serializeForProjection(statement StatementType, out *SQLBuilder)
|
||||
serializeForJsonObj(statement StatementType, out *SQLBuilder)
|
||||
serializeForJsonObjEntry(statement StatementType, out *SQLBuilder)
|
||||
serializeForRowToJsonProjection(statement StatementType, out *SQLBuilder)
|
||||
fromImpl(subQuery SelectTable) Projection
|
||||
}
|
||||
|
||||
|
|
@ -29,7 +30,7 @@ func (pl ProjectionList) serializeForProjection(statement StatementType, out *SQ
|
|||
SerializeProjectionList(statement, pl, out)
|
||||
}
|
||||
|
||||
func (pl ProjectionList) serializeForJsonObj(statement StatementType, out *SQLBuilder) {
|
||||
func (pl ProjectionList) serializeForJsonObjEntry(statement StatementType, out *SQLBuilder) {
|
||||
SerializeProjectionListJsonObj(statement, pl, out)
|
||||
}
|
||||
|
||||
|
|
@ -85,9 +86,17 @@ func (pl ProjectionList) Except(toExclude ...Column) ProjectionList {
|
|||
return ret
|
||||
}
|
||||
|
||||
// JsonProjectionList redefines []Projection so projections can be serialized as json object key/values
|
||||
type JsonProjectionList []Projection
|
||||
|
||||
func (j JsonProjectionList) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
SerializeProjectionListJsonObj(statement, j, out)
|
||||
func (pl ProjectionList) serializeForRowToJsonProjection(statement StatementType, out *SQLBuilder) {
|
||||
out.WriteRowToJsonProjections(statement, pl)
|
||||
}
|
||||
|
||||
// JsonObjProjectionList redefines []Projection so projections can be serialized as json object key/values
|
||||
type JsonObjProjectionList []Projection
|
||||
|
||||
func (j JsonObjProjectionList) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
out.IncreaseIdent()
|
||||
out.NewLine()
|
||||
SerializeProjectionListJsonObj(statement, j, out)
|
||||
out.DecreaseIdent()
|
||||
out.NewLine()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,9 +118,10 @@ type rangeExpressionWrapper[T Expression] struct {
|
|||
}
|
||||
|
||||
func newRangeExpressionWrap[T Expression](expression Expression) Range[T] {
|
||||
rangeExpressionWrap := rangeExpressionWrapper[T]{Expression: expression}
|
||||
rangeExpressionWrap.rangeInterfaceImpl.parent = &rangeExpressionWrap
|
||||
return &rangeExpressionWrap
|
||||
rangeExpressionWrap := &rangeExpressionWrapper[T]{Expression: expression}
|
||||
rangeExpressionWrap.rangeInterfaceImpl.parent = rangeExpressionWrap
|
||||
expression.setParent(rangeExpressionWrap)
|
||||
return rangeExpressionWrap
|
||||
}
|
||||
|
||||
// RangeExp is range expression wrapper around arbitrary expression.
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ type RowExpression interface {
|
|||
}
|
||||
|
||||
type rowInterfaceImpl struct {
|
||||
parent Expression
|
||||
dialect Dialect
|
||||
elemCount int
|
||||
parent Expression
|
||||
dialect Dialect
|
||||
expressions []Expression
|
||||
}
|
||||
|
||||
func (n *rowInterfaceImpl) EQ(rhs RowExpression) BoolExpression {
|
||||
|
|
@ -57,9 +57,8 @@ func (n *rowInterfaceImpl) LT_EQ(rhs RowExpression) BoolExpression {
|
|||
func (n *rowInterfaceImpl) projections() ProjectionList {
|
||||
var ret ProjectionList
|
||||
|
||||
for i := 0; i < n.elemCount; i++ {
|
||||
rowColumn := NewColumnImpl(n.dialect.ValuesDefaultColumnName(i), "", nil)
|
||||
ret = append(ret, &rowColumn)
|
||||
for i, expression := range n.expressions {
|
||||
ret = append(ret, newDummyColumnForExpression(expression, n.dialect.ValuesDefaultColumnName(i)))
|
||||
}
|
||||
|
||||
return ret
|
||||
|
|
@ -77,7 +76,7 @@ func newRowExpression(name string, dialect Dialect, expressions ...Expression) R
|
|||
|
||||
ret.Expression = NewFunc(name, expressions, ret)
|
||||
ret.dialect = dialect
|
||||
ret.elemCount = len(expressions)
|
||||
ret.expressions = expressions
|
||||
|
||||
return ret
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,10 +22,6 @@ func (s SerializeOption) WithFallTrough(options []SerializeOption) []SerializeOp
|
|||
// StatementType is type of the SQL statement
|
||||
type StatementType string
|
||||
|
||||
func (s StatementType) IsSelectJSON() bool {
|
||||
return s == SelectJsonObjStatementType || s == SelectJsonArrStatementType
|
||||
}
|
||||
|
||||
// Statement types
|
||||
const (
|
||||
SelectStatementType StatementType = "SELECT"
|
||||
|
|
|
|||
|
|
@ -61,6 +61,16 @@ func (s *SQLBuilder) WriteProjections(statement StatementType, projections []Pro
|
|||
s.DecreaseIdent()
|
||||
}
|
||||
|
||||
func (s *SQLBuilder) WriteRowToJsonProjections(statement StatementType, projections []Projection) {
|
||||
for i, projection := range projections {
|
||||
if i > 0 {
|
||||
s.WriteString(",")
|
||||
s.NewLine()
|
||||
}
|
||||
projection.serializeForRowToJsonProjection(statement, s)
|
||||
}
|
||||
}
|
||||
|
||||
// NewLine adds new line to output SQL
|
||||
func (s *SQLBuilder) NewLine() {
|
||||
s.write([]byte{'\n'})
|
||||
|
|
|
|||
|
|
@ -257,12 +257,13 @@ type expressionStatementImpl struct {
|
|||
}
|
||||
|
||||
func (s *expressionStatementImpl) serializeForProjection(statement StatementType, out *SQLBuilder) {
|
||||
if statement.IsSelectJSON() {
|
||||
panic("jet: SELECT JSON statements need to be aliased when used as a projection.")
|
||||
}
|
||||
s.serialize(statement, out)
|
||||
}
|
||||
|
||||
func (e *expressionStatementImpl) serializeForRowToJsonProjection(statement StatementType, out *SQLBuilder) {
|
||||
panic("jet: SELECT JSON statements need to be aliased when used as a projection.")
|
||||
}
|
||||
|
||||
// NewStatementImpl creates new statementImpl
|
||||
func NewStatementImpl(Dialect Dialect, statementType StatementType, parent SerializerStatement, clauses ...Clause) SerializerStatement {
|
||||
return &statementImpl{
|
||||
|
|
|
|||
|
|
@ -105,9 +105,10 @@ type stringExpressionWrapper struct {
|
|||
}
|
||||
|
||||
func newStringExpressionWrap(expression Expression) StringExpression {
|
||||
stringExpressionWrap := stringExpressionWrapper{Expression: expression}
|
||||
stringExpressionWrap.stringInterfaceImpl.parent = &stringExpressionWrap
|
||||
return &stringExpressionWrap
|
||||
stringExpressionWrap := &stringExpressionWrapper{Expression: expression}
|
||||
stringExpressionWrap.stringInterfaceImpl.parent = stringExpressionWrap
|
||||
expression.setParent(stringExpressionWrap)
|
||||
return stringExpressionWrap
|
||||
}
|
||||
|
||||
// StringExp is string expression wrapper around arbitrary expression.
|
||||
|
|
|
|||
|
|
@ -75,14 +75,15 @@ func (t *timeInterfaceImpl) SUB(rhs Interval) TimeExpression {
|
|||
//---------------------------------------------------//
|
||||
|
||||
type timeExpressionWrapper struct {
|
||||
timeInterfaceImpl
|
||||
Expression
|
||||
timeInterfaceImpl
|
||||
}
|
||||
|
||||
func newTimeExpressionWrap(expression Expression) TimeExpression {
|
||||
timeExpressionWrap := timeExpressionWrapper{Expression: expression}
|
||||
timeExpressionWrap.timeInterfaceImpl.parent = &timeExpressionWrap
|
||||
return &timeExpressionWrap
|
||||
timeExpressionWrap := &timeExpressionWrapper{Expression: expression}
|
||||
timeExpressionWrap.timeInterfaceImpl.parent = timeExpressionWrap
|
||||
expression.setParent(timeExpressionWrap)
|
||||
return timeExpressionWrap
|
||||
}
|
||||
|
||||
// TimeExp is time expression wrapper around arbitrary expression.
|
||||
|
|
|
|||
|
|
@ -52,11 +52,3 @@ func TestTimeExp(t *testing.T) {
|
|||
assertClauseSerialize(t, TimeExp(table1ColFloat).LT(Time(1, 1, 1, 1*time.Millisecond)),
|
||||
"(table1.col_float < $1)", string("01:01:01.001"))
|
||||
}
|
||||
|
||||
func TestTimeArithmetic(t *testing.T) {
|
||||
time := Time(10, 20, 3)
|
||||
assertClauseDebugSerialize(t, table1ColTime.ADD(NewInterval(String("1 HOUR"))).EQ(time),
|
||||
"((table1.col_time + INTERVAL '1 HOUR') = '10:20:03')")
|
||||
assertClauseDebugSerialize(t, table1ColTime.SUB(NewInterval(String("1 HOUR"))).EQ(time),
|
||||
"((table1.col_time - INTERVAL '1 HOUR') = '10:20:03')")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,9 +80,10 @@ type timestampExpressionWrapper struct {
|
|||
}
|
||||
|
||||
func newTimestampExpressionWrap(expression Expression) TimestampExpression {
|
||||
timestampExpressionWrap := timestampExpressionWrapper{Expression: expression}
|
||||
timestampExpressionWrap.timestampInterfaceImpl.parent = ×tampExpressionWrap
|
||||
return ×tampExpressionWrap
|
||||
timestampExpressionWrap := ×tampExpressionWrapper{Expression: expression}
|
||||
timestampExpressionWrap.timestampInterfaceImpl.parent = timestampExpressionWrap
|
||||
expression.setParent(timestampExpressionWrap)
|
||||
return timestampExpressionWrap
|
||||
}
|
||||
|
||||
// TimestampExp is timestamp expression wrapper around arbitrary expression.
|
||||
|
|
|
|||
|
|
@ -53,11 +53,3 @@ func TestTimestampExp(t *testing.T) {
|
|||
assertClauseSerialize(t, TimestampExp(table1ColFloat).LT(timestamp),
|
||||
"(table1.col_float < $1)", "2000-01-31 10:20:00.003")
|
||||
}
|
||||
|
||||
func TestTimestampArithmetic(t *testing.T) {
|
||||
timestamp := Timestamp(2000, 1, 1, 0, 0, 0)
|
||||
assertClauseDebugSerialize(t, table1ColTimestamp.ADD(NewInterval(String("1 HOUR"))).EQ(timestamp),
|
||||
"((table1.col_timestamp + INTERVAL '1 HOUR') = '2000-01-01 00:00:00')")
|
||||
assertClauseDebugSerialize(t, table1ColTimestamp.SUB(NewInterval(String("1 HOUR"))).EQ(timestamp),
|
||||
"((table1.col_timestamp - INTERVAL '1 HOUR') = '2000-01-01 00:00:00')")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,9 +80,10 @@ type timestampzExpressionWrapper struct {
|
|||
}
|
||||
|
||||
func newTimestampzExpressionWrap(expression Expression) TimestampzExpression {
|
||||
timestampzExpressionWrap := timestampzExpressionWrapper{Expression: expression}
|
||||
timestampzExpressionWrap.timestampzInterfaceImpl.parent = ×tampzExpressionWrap
|
||||
return ×tampzExpressionWrap
|
||||
timestampzExpressionWrap := ×tampzExpressionWrapper{Expression: expression}
|
||||
timestampzExpressionWrap.timestampzInterfaceImpl.parent = timestampzExpressionWrap
|
||||
expression.setParent(timestampzExpressionWrap)
|
||||
return timestampzExpressionWrap
|
||||
}
|
||||
|
||||
// TimestampzExp is timestamp with time zone expression wrapper around arbitrary expression.
|
||||
|
|
|
|||
|
|
@ -53,11 +53,3 @@ func TestTimestampzExp(t *testing.T) {
|
|||
assertClauseSerialize(t, TimestampzExp(table1ColFloat).LT(timestampz),
|
||||
"(table1.col_float < $1)", "2000-01-31 10:20:05.000023 +200")
|
||||
}
|
||||
|
||||
func TestTimestampzArithmetic(t *testing.T) {
|
||||
timestampz := Timestampz(2000, 1, 1, 0, 0, 0, 100, "UTC")
|
||||
assertClauseDebugSerialize(t, table1ColTimestampz.ADD(NewInterval(String("1 HOUR"))).EQ(timestampz),
|
||||
"((table1.col_timestampz + INTERVAL '1 HOUR') = '2000-01-01 00:00:00.0000001 UTC')")
|
||||
assertClauseDebugSerialize(t, table1ColTimestampz.SUB(NewInterval(String("1 HOUR"))).EQ(timestampz),
|
||||
"((table1.col_timestampz - INTERVAL '1 HOUR') = '2000-01-01 00:00:00.0000001 UTC')")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,14 +75,15 @@ func (t *timezInterfaceImpl) SUB(rhs Interval) TimezExpression {
|
|||
//---------------------------------------------------//
|
||||
|
||||
type timezExpressionWrapper struct {
|
||||
timezInterfaceImpl
|
||||
Expression
|
||||
timezInterfaceImpl
|
||||
}
|
||||
|
||||
func newTimezExpressionWrap(expression Expression) TimezExpression {
|
||||
timezExpressionWrap := timezExpressionWrapper{Expression: expression}
|
||||
timezExpressionWrap.timezInterfaceImpl.parent = &timezExpressionWrap
|
||||
return &timezExpressionWrap
|
||||
timezExpressionWrap := &timezExpressionWrapper{Expression: expression}
|
||||
timezExpressionWrap.timezInterfaceImpl.parent = timezExpressionWrap
|
||||
expression.setParent(timezExpressionWrap)
|
||||
return timezExpressionWrap
|
||||
}
|
||||
|
||||
// TimezExp is time with time zone expression wrapper around arbitrary expression.
|
||||
|
|
|
|||
|
|
@ -51,11 +51,3 @@ func TestTimezExp(t *testing.T) {
|
|||
assertClauseSerialize(t, TimezExp(table1ColFloat).LT(Timez(1, 1, 1, 1, "+4:00")),
|
||||
"(table1.col_float < $1)", string("01:01:01.000000001 +4:00"))
|
||||
}
|
||||
|
||||
func TestTimezArithmetic(t *testing.T) {
|
||||
timez := Timez(0, 0, 0, 100, "UTC")
|
||||
assertClauseDebugSerialize(t, table1ColTimez.ADD(NewInterval(String("1 HOUR"))).EQ(timez),
|
||||
"((table1.col_timez + INTERVAL '1 HOUR') = '00:00:00.0000001 UTC')")
|
||||
assertClauseDebugSerialize(t, table1ColTimez.SUB(NewInterval(String("1 HOUR"))).EQ(timez),
|
||||
"((table1.col_timez - INTERVAL '1 HOUR') = '00:00:00.0000001 UTC')")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ func SerializeProjectionListJsonObj(statement StatementType, projections []Proje
|
|||
panic("jet: Projection is nil")
|
||||
}
|
||||
|
||||
p.serializeForJsonObj(statement, out)
|
||||
p.serializeForJsonObjEntry(statement, out)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ func AssertJsonEqual(t require.TestingT, actual, expected interface{}, option ..
|
|||
expectedJsonData, err := json.MarshalIndent(expected, "", "\t")
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, actualJsonData, expectedJsonData)
|
||||
require.Equal(t, string(actualJsonData), string(expectedJsonData))
|
||||
}
|
||||
|
||||
// SaveJSONFile saves v as json at testRelativePath
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue