Add support for PostgreSQL interval column

This commit is contained in:
go-jet 2020-02-09 18:37:48 +01:00
parent 641c62098c
commit 3013dc3647
30 changed files with 1038 additions and 255 deletions

View file

@ -57,8 +57,10 @@ func (c ColumnMetaData) getSqlBuilderColumnType() string {
return "Time"
case "time with time zone":
return "Timez"
case "interval":
return "Interval"
case "USER-DEFINED", "enum", "text", "character", "character varying", "bytea", "uuid",
"tsvector", "bit", "bit varying", "money", "json", "jsonb", "xml", "point", "interval", "line", "ARRAY",
"tsvector", "bit", "bit varying", "money", "json", "jsonb", "xml", "point", "line", "ARRAY",
"char", "varchar", "binary", "varbinary",
"tinyblob", "blob", "mediumblob", "longblob", "tinytext", "mediumtext", "longtext": // MySQL
return "String"

View file

@ -13,8 +13,7 @@ func newAlias(expression Expression, aliasName string) Projection {
}
func (a *alias) fromImpl(subQuery SelectTable) Projection {
column := newColumn(a.alias, "", nil)
column.Parent = &column
column := NewColumnImpl(a.alias, "", nil)
column.subQuery = subQuery
return &column

View file

@ -37,19 +37,19 @@ type boolInterfaceImpl struct {
}
func (b *boolInterfaceImpl) EQ(expression BoolExpression) BoolExpression {
return eq(b.parent, expression)
return Eq(b.parent, expression)
}
func (b *boolInterfaceImpl) NOT_EQ(expression BoolExpression) BoolExpression {
return notEq(b.parent, expression)
return NotEq(b.parent, expression)
}
func (b *boolInterfaceImpl) IS_DISTINCT_FROM(rhs BoolExpression) BoolExpression {
return isDistinctFrom(b.parent, rhs)
return IsDistinctFrom(b.parent, rhs)
}
func (b *boolInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs BoolExpression) BoolExpression {
return isNotDistinctFrom(b.parent, rhs)
return IsNotDistinctFrom(b.parent, rhs)
}
func (b *boolInterfaceImpl) AND(expression BoolExpression) BoolExpression {
@ -86,7 +86,7 @@ func (b *boolInterfaceImpl) IS_NOT_UNKNOWN() BoolExpression {
//---------------------------------------------------//
func newBinaryBoolOperatorExpression(lhs, rhs Expression, operator string, additionalParams ...Expression) BoolExpression {
return BoolExp(newBinaryOperatorExpression(lhs, rhs, operator, additionalParams...))
return BoolExp(NewBinaryOperatorExpression(lhs, rhs, operator, additionalParams...))
}
//---------------------------------------------------//

View file

@ -18,8 +18,8 @@ type ColumnExpression interface {
Expression
}
// The base type for real materialized columns.
type columnImpl struct {
// ColumnExpressionImpl is base type for sql columns.
type ColumnExpressionImpl struct {
ExpressionInterfaceImpl
name string
@ -28,34 +28,41 @@ type columnImpl struct {
subQuery SelectTable
}
func newColumn(name string, tableName string, parent ColumnExpression) columnImpl {
bc := columnImpl{
// NewColumnImpl creates new ColumnExpressionImpl
func NewColumnImpl(name string, tableName string, parent ColumnExpression) ColumnExpressionImpl {
bc := ColumnExpressionImpl{
name: name,
tableName: tableName,
}
bc.ExpressionInterfaceImpl.Parent = parent
if parent != nil {
bc.ExpressionInterfaceImpl.Parent = parent
} else {
bc.ExpressionInterfaceImpl.Parent = &bc
}
return bc
}
func (c *columnImpl) Name() string {
// Name returns name of the column
func (c *ColumnExpressionImpl) Name() string {
return c.name
}
func (c *columnImpl) TableName() string {
// TableName returns column table name
func (c *ColumnExpressionImpl) TableName() string {
return c.tableName
}
func (c *columnImpl) setTableName(table string) {
func (c *ColumnExpressionImpl) setTableName(table string) {
c.tableName = table
}
func (c *columnImpl) setSubQuery(subQuery SelectTable) {
func (c *ColumnExpressionImpl) setSubQuery(subQuery SelectTable) {
c.subQuery = subQuery
}
func (c *columnImpl) defaultAlias() string {
func (c *ColumnExpressionImpl) defaultAlias() string {
if c.tableName != "" {
return c.tableName + "." + c.name
}
@ -63,25 +70,31 @@ func (c *columnImpl) defaultAlias() string {
return c.name
}
func (c *columnImpl) serializeForOrderBy(statement StatementType, out *SQLBuilder) {
func (c *ColumnExpressionImpl) fromImpl(subQuery SelectTable) Projection {
newColumn := NewColumnImpl(c.name, c.tableName, nil)
newColumn.setSubQuery(subQuery)
return &newColumn
}
func (c *ColumnExpressionImpl) serializeForOrderBy(statement StatementType, out *SQLBuilder) {
if statement == SetStatementType {
// set Statement (UNION, EXCEPT ...) can reference only select projections in order by clause
out.WriteAlias(c.defaultAlias()) //always quote
return
}
c.serialize(statement, out)
}
func (c columnImpl) serializeForProjection(statement StatementType, out *SQLBuilder) {
func (c ColumnExpressionImpl) serializeForProjection(statement StatementType, out *SQLBuilder) {
c.serialize(statement, out)
out.WriteString("AS")
out.WriteAlias(c.defaultAlias())
}
func (c columnImpl) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
func (c ColumnExpressionImpl) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
if c.subQuery != nil {
out.WriteIdentifier(c.subQuery.Alias())
@ -128,3 +141,13 @@ func (cl ColumnList) TableName() string { return "" }
func (cl ColumnList) setTableName(name string) {}
func (cl ColumnList) setSubQuery(subQuery SelectTable) {}
func (cl ColumnList) defaultAlias() string { return "" }
// SetTableName is utility function to set table name from outside of jet package to avoid making public setTableName
func SetTableName(columnExpression ColumnExpression, tableName string) {
columnExpression.setTableName(tableName)
}
// SetSubQuery is utility function to set table name from outside of jet package to avoid making public setSubQuery
func SetSubQuery(columnExpression ColumnExpression, subQuery SelectTable) {
columnExpression.setSubQuery(subQuery)
}

View file

@ -3,7 +3,7 @@ package jet
import "testing"
func TestColumn(t *testing.T) {
column := newColumn("col", "", nil)
column := NewColumnImpl("col", "", nil)
column.ExpressionInterfaceImpl.Parent = &column
assertClauseSerialize(t, column, "col")

View file

@ -10,11 +10,10 @@ type ColumnBool interface {
type boolColumnImpl struct {
boolInterfaceImpl
columnImpl
ColumnExpressionImpl
}
func (i *boolColumnImpl) fromImpl(subQuery SelectTable) Projection {
func (i *boolColumnImpl) From(subQuery SelectTable) ColumnBool {
newBoolColumn := BoolColumn(i.name)
newBoolColumn.setTableName(i.tableName)
newBoolColumn.setSubQuery(subQuery)
@ -22,16 +21,10 @@ func (i *boolColumnImpl) fromImpl(subQuery SelectTable) Projection {
return newBoolColumn
}
func (i *boolColumnImpl) From(subQuery SelectTable) ColumnBool {
newBoolColumn := i.fromImpl(subQuery).(ColumnBool)
return newBoolColumn
}
// BoolColumn creates named bool column.
func BoolColumn(name string) ColumnBool {
boolColumn := &boolColumnImpl{}
boolColumn.columnImpl = newColumn(name, "", boolColumn)
boolColumn.ColumnExpressionImpl = NewColumnImpl(name, "", boolColumn)
boolColumn.boolInterfaceImpl.parent = boolColumn
return boolColumn
@ -49,19 +42,13 @@ type ColumnFloat interface {
type floatColumnImpl struct {
floatInterfaceImpl
columnImpl
}
func (i *floatColumnImpl) fromImpl(subQuery SelectTable) Projection {
newFloatColumn := FloatColumn(i.name)
newFloatColumn.setTableName(i.tableName)
newFloatColumn.setSubQuery(subQuery)
return newFloatColumn
ColumnExpressionImpl
}
func (i *floatColumnImpl) From(subQuery SelectTable) ColumnFloat {
newFloatColumn := i.fromImpl(subQuery).(ColumnFloat)
newFloatColumn := FloatColumn(i.name)
newFloatColumn.setTableName(i.tableName)
newFloatColumn.setSubQuery(subQuery)
return newFloatColumn
}
@ -70,7 +57,7 @@ func (i *floatColumnImpl) From(subQuery SelectTable) ColumnFloat {
func FloatColumn(name string) ColumnFloat {
floatColumn := &floatColumnImpl{}
floatColumn.floatInterfaceImpl.parent = floatColumn
floatColumn.columnImpl = newColumn(name, "", floatColumn)
floatColumn.ColumnExpressionImpl = NewColumnImpl(name, "", floatColumn)
return floatColumn
}
@ -88,10 +75,10 @@ type ColumnInteger interface {
type integerColumnImpl struct {
integerInterfaceImpl
columnImpl
ColumnExpressionImpl
}
func (i *integerColumnImpl) fromImpl(subQuery SelectTable) Projection {
func (i *integerColumnImpl) From(subQuery SelectTable) ColumnInteger {
newIntColumn := IntegerColumn(i.name)
newIntColumn.setTableName(i.tableName)
newIntColumn.setSubQuery(subQuery)
@ -99,15 +86,11 @@ func (i *integerColumnImpl) fromImpl(subQuery SelectTable) Projection {
return newIntColumn
}
func (i *integerColumnImpl) From(subQuery SelectTable) ColumnInteger {
return i.fromImpl(subQuery).(ColumnInteger)
}
// IntegerColumn creates named integer column.
func IntegerColumn(name string) ColumnInteger {
integerColumn := &integerColumnImpl{}
integerColumn.integerInterfaceImpl.parent = integerColumn
integerColumn.columnImpl = newColumn(name, "", integerColumn)
integerColumn.ColumnExpressionImpl = NewColumnImpl(name, "", integerColumn)
return integerColumn
}
@ -126,10 +109,10 @@ type ColumnString interface {
type stringColumnImpl struct {
stringInterfaceImpl
columnImpl
ColumnExpressionImpl
}
func (i *stringColumnImpl) fromImpl(subQuery SelectTable) Projection {
func (i *stringColumnImpl) From(subQuery SelectTable) ColumnString {
newStrColumn := StringColumn(i.name)
newStrColumn.setTableName(i.tableName)
newStrColumn.setSubQuery(subQuery)
@ -137,15 +120,11 @@ func (i *stringColumnImpl) fromImpl(subQuery SelectTable) Projection {
return newStrColumn
}
func (i *stringColumnImpl) From(subQuery SelectTable) ColumnString {
return i.fromImpl(subQuery).(ColumnString)
}
// StringColumn creates named string column.
func StringColumn(name string) ColumnString {
stringColumn := &stringColumnImpl{}
stringColumn.stringInterfaceImpl.parent = stringColumn
stringColumn.columnImpl = newColumn(name, "", stringColumn)
stringColumn.ColumnExpressionImpl = NewColumnImpl(name, "", stringColumn)
return stringColumn
}
@ -162,10 +141,10 @@ type ColumnTime interface {
type timeColumnImpl struct {
timeInterfaceImpl
columnImpl
ColumnExpressionImpl
}
func (i *timeColumnImpl) fromImpl(subQuery SelectTable) Projection {
func (i *timeColumnImpl) From(subQuery SelectTable) ColumnTime {
newTimeColumn := TimeColumn(i.name)
newTimeColumn.setTableName(i.tableName)
newTimeColumn.setSubQuery(subQuery)
@ -173,15 +152,11 @@ func (i *timeColumnImpl) fromImpl(subQuery SelectTable) Projection {
return newTimeColumn
}
func (i *timeColumnImpl) From(subQuery SelectTable) ColumnTime {
return i.fromImpl(subQuery).(ColumnTime)
}
// TimeColumn creates named time column
func TimeColumn(name string) ColumnTime {
timeColumn := &timeColumnImpl{}
timeColumn.timeInterfaceImpl.parent = timeColumn
timeColumn.columnImpl = newColumn(name, "", timeColumn)
timeColumn.ColumnExpressionImpl = NewColumnImpl(name, "", timeColumn)
return timeColumn
}
@ -197,11 +172,10 @@ type ColumnTimez interface {
type timezColumnImpl struct {
timezInterfaceImpl
columnImpl
ColumnExpressionImpl
}
func (i *timezColumnImpl) fromImpl(subQuery SelectTable) Projection {
func (i *timezColumnImpl) From(subQuery SelectTable) ColumnTimez {
newTimezColumn := TimezColumn(i.name)
newTimezColumn.setTableName(i.tableName)
newTimezColumn.setSubQuery(subQuery)
@ -209,15 +183,11 @@ func (i *timezColumnImpl) fromImpl(subQuery SelectTable) Projection {
return newTimezColumn
}
func (i *timezColumnImpl) From(subQuery SelectTable) ColumnTimez {
return i.fromImpl(subQuery).(ColumnTimez)
}
// TimezColumn creates named time with time zone column.
func TimezColumn(name string) ColumnTimez {
timezColumn := &timezColumnImpl{}
timezColumn.timezInterfaceImpl.parent = timezColumn
timezColumn.columnImpl = newColumn(name, "", timezColumn)
timezColumn.ColumnExpressionImpl = NewColumnImpl(name, "", timezColumn)
return timezColumn
}
@ -234,11 +204,10 @@ type ColumnTimestamp interface {
type timestampColumnImpl struct {
timestampInterfaceImpl
columnImpl
ColumnExpressionImpl
}
func (i *timestampColumnImpl) fromImpl(subQuery SelectTable) Projection {
func (i *timestampColumnImpl) From(subQuery SelectTable) ColumnTimestamp {
newTimestampColumn := TimestampColumn(i.name)
newTimestampColumn.setTableName(i.tableName)
newTimestampColumn.setSubQuery(subQuery)
@ -246,15 +215,11 @@ func (i *timestampColumnImpl) fromImpl(subQuery SelectTable) Projection {
return newTimestampColumn
}
func (i *timestampColumnImpl) From(subQuery SelectTable) ColumnTimestamp {
return i.fromImpl(subQuery).(ColumnTimestamp)
}
// TimestampColumn creates named timestamp column
func TimestampColumn(name string) ColumnTimestamp {
timestampColumn := &timestampColumnImpl{}
timestampColumn.timestampInterfaceImpl.parent = timestampColumn
timestampColumn.columnImpl = newColumn(name, "", timestampColumn)
timestampColumn.ColumnExpressionImpl = NewColumnImpl(name, "", timestampColumn)
return timestampColumn
}
@ -271,11 +236,10 @@ type ColumnTimestampz interface {
type timestampzColumnImpl struct {
timestampzInterfaceImpl
columnImpl
ColumnExpressionImpl
}
func (i *timestampzColumnImpl) fromImpl(subQuery SelectTable) Projection {
func (i *timestampzColumnImpl) From(subQuery SelectTable) ColumnTimestampz {
newTimestampzColumn := TimestampzColumn(i.name)
newTimestampzColumn.setTableName(i.tableName)
newTimestampzColumn.setSubQuery(subQuery)
@ -283,15 +247,11 @@ func (i *timestampzColumnImpl) fromImpl(subQuery SelectTable) Projection {
return newTimestampzColumn
}
func (i *timestampzColumnImpl) From(subQuery SelectTable) ColumnTimestampz {
return i.fromImpl(subQuery).(ColumnTimestampz)
}
// TimestampzColumn creates named timestamp with time zone column.
func TimestampzColumn(name string) ColumnTimestampz {
timestampzColumn := &timestampzColumnImpl{}
timestampzColumn.timestampzInterfaceImpl.parent = timestampzColumn
timestampzColumn.columnImpl = newColumn(name, "", timestampzColumn)
timestampzColumn.ColumnExpressionImpl = NewColumnImpl(name, "", timestampzColumn)
return timestampzColumn
}
@ -308,11 +268,10 @@ type ColumnDate interface {
type dateColumnImpl struct {
dateInterfaceImpl
columnImpl
ColumnExpressionImpl
}
func (i *dateColumnImpl) fromImpl(subQuery SelectTable) Projection {
func (i *dateColumnImpl) From(subQuery SelectTable) ColumnDate {
newDateColumn := DateColumn(i.name)
newDateColumn.setTableName(i.tableName)
newDateColumn.setSubQuery(subQuery)
@ -320,14 +279,10 @@ func (i *dateColumnImpl) fromImpl(subQuery SelectTable) Projection {
return newDateColumn
}
func (i *dateColumnImpl) From(subQuery SelectTable) ColumnDate {
return i.fromImpl(subQuery).(ColumnDate)
}
// DateColumn creates named date column.
func DateColumn(name string) ColumnDate {
dateColumn := &dateColumnImpl{}
dateColumn.dateInterfaceImpl.parent = dateColumn
dateColumn.columnImpl = newColumn(name, "", dateColumn)
dateColumn.ColumnExpressionImpl = NewColumnImpl(name, "", dateColumn)
return dateColumn
}

View file

@ -43,5 +43,74 @@ func TestNewFloatColumnColumn(t *testing.T) {
assertClauseSerialize(t, floatColumn2, `sub_query."table1.col_float"`)
assertClauseSerialize(t, floatColumn2.EQ(Float(2.22)), `(sub_query."table1.col_float" = $1)`, float64(2.22))
assertProjectionSerialize(t, floatColumn2, `sub_query."table1.col_float" AS "table1.col_float"`)
}
func TestNewDateColumnColumn(t *testing.T) {
dateColumn := DateColumn("col_date").From(subQuery)
assertClauseSerialize(t, dateColumn, `sub_query."col_date"`)
assertClauseSerialize(t, dateColumn.EQ(Date(2002, 2, 3)),
`(sub_query."col_date" = $1)`, "2002-02-03")
assertProjectionSerialize(t, dateColumn, `sub_query."col_date" AS "col_date"`)
dateColumn2 := table1ColDate.From(subQuery)
assertClauseSerialize(t, dateColumn2, `sub_query."table1.col_date"`)
assertClauseSerialize(t, dateColumn2.EQ(Date(2002, 2, 3)),
`(sub_query."table1.col_date" = $1)`, "2002-02-03")
assertProjectionSerialize(t, dateColumn2, `sub_query."table1.col_date" AS "table1.col_date"`)
}
func TestNewTimeColumnColumn(t *testing.T) {
timeColumn := TimeColumn("col_time").From(subQuery)
assertClauseSerialize(t, timeColumn, `sub_query."col_time"`)
assertClauseSerialize(t, timeColumn.EQ(Time(1, 1, 1, 1)),
`(sub_query."col_time" = $1)`, "01:01:01.000000001")
assertProjectionSerialize(t, timeColumn, `sub_query."col_time" AS "col_time"`)
timeColumn2 := table1ColTime.From(subQuery)
assertClauseSerialize(t, timeColumn2, `sub_query."table1.col_time"`)
assertClauseSerialize(t, timeColumn2.EQ(Time(2, 2, 2)),
`(sub_query."table1.col_time" = $1)`, "02:02:02")
assertProjectionSerialize(t, timeColumn2, `sub_query."table1.col_time" AS "table1.col_time"`)
}
func TestNewTimezColumnColumn(t *testing.T) {
timezColumn := TimezColumn("col_timez").From(subQuery)
assertClauseSerialize(t, timezColumn, `sub_query."col_timez"`)
assertClauseSerialize(t, timezColumn.EQ(Timez(1, 1, 1, 1, "UTC")),
`(sub_query."col_timez" = $1)`, "01:01:01.000000001 UTC")
assertProjectionSerialize(t, timezColumn, `sub_query."col_timez" AS "col_timez"`)
timezColumn2 := table1ColTimez.From(subQuery)
assertClauseSerialize(t, timezColumn2, `sub_query."table1.col_timez"`)
assertClauseSerialize(t, timezColumn2.EQ(Timez(2, 2, 2, 0, "UTC")),
`(sub_query."table1.col_timez" = $1)`, "02:02:02 UTC")
assertProjectionSerialize(t, timezColumn2, `sub_query."table1.col_timez" AS "table1.col_timez"`)
}
func TestNewTimestampColumnColumn(t *testing.T) {
timestampColumn := TimestampColumn("col_timestamp").From(subQuery)
assertClauseSerialize(t, timestampColumn, `sub_query."col_timestamp"`)
assertClauseSerialize(t, timestampColumn.EQ(Timestamp(1, 1, 1, 1, 1, 1)),
`(sub_query."col_timestamp" = $1)`, "0001-01-01 01:01:01")
assertProjectionSerialize(t, timestampColumn, `sub_query."col_timestamp" AS "col_timestamp"`)
timestampColumn2 := table1ColTimestamp.From(subQuery)
assertClauseSerialize(t, timestampColumn2, `sub_query."table1.col_timestamp"`)
assertClauseSerialize(t, timestampColumn2.EQ(Timestamp(2, 2, 2, 2, 2, 2)),
`(sub_query."table1.col_timestamp" = $1)`, "0002-02-02 02:02:02")
assertProjectionSerialize(t, timestampColumn2, `sub_query."table1.col_timestamp" AS "table1.col_timestamp"`)
}
func TestNewTimestampzColumnColumn(t *testing.T) {
timestampzColumn := TimestampzColumn("col_timestampz").From(subQuery)
assertClauseSerialize(t, timestampzColumn, `sub_query."col_timestampz"`)
assertClauseSerialize(t, timestampzColumn.EQ(Timestampz(1, 1, 1, 1, 1, 1, 0, "UTC")),
`(sub_query."col_timestampz" = $1)`, "0001-01-01 01:01:01 UTC")
assertProjectionSerialize(t, timestampzColumn, `sub_query."col_timestampz" AS "col_timestampz"`)
timestampzColumn2 := table1ColTimestampz.From(subQuery)
assertClauseSerialize(t, timestampzColumn2, `sub_query."table1.col_timestampz"`)
assertClauseSerialize(t, timestampzColumn2.EQ(Timestampz(2, 2, 2, 2, 2, 2, 0, "UTC")),
`(sub_query."table1.col_timestampz" = $1)`, "0002-02-02 02:02:02 UTC")
assertProjectionSerialize(t, timestampzColumn2, `sub_query."table1.col_timestampz" AS "table1.col_timestampz"`)
}

View file

@ -23,43 +23,43 @@ type dateInterfaceImpl struct {
}
func (d *dateInterfaceImpl) EQ(rhs DateExpression) BoolExpression {
return eq(d.parent, rhs)
return Eq(d.parent, rhs)
}
func (d *dateInterfaceImpl) NOT_EQ(rhs DateExpression) BoolExpression {
return notEq(d.parent, rhs)
return NotEq(d.parent, rhs)
}
func (d *dateInterfaceImpl) IS_DISTINCT_FROM(rhs DateExpression) BoolExpression {
return isDistinctFrom(d.parent, rhs)
return IsDistinctFrom(d.parent, rhs)
}
func (d *dateInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs DateExpression) BoolExpression {
return isNotDistinctFrom(d.parent, rhs)
return IsNotDistinctFrom(d.parent, rhs)
}
func (d *dateInterfaceImpl) LT(rhs DateExpression) BoolExpression {
return lt(d.parent, rhs)
return Lt(d.parent, rhs)
}
func (d *dateInterfaceImpl) LT_EQ(rhs DateExpression) BoolExpression {
return ltEq(d.parent, rhs)
return LtEq(d.parent, rhs)
}
func (d *dateInterfaceImpl) GT(rhs DateExpression) BoolExpression {
return gt(d.parent, rhs)
return Gt(d.parent, rhs)
}
func (d *dateInterfaceImpl) GT_EQ(rhs DateExpression) BoolExpression {
return gtEq(d.parent, rhs)
return GtEq(d.parent, rhs)
}
func (d *dateInterfaceImpl) ADD(rhs Interval) TimestampExpression {
return TimestampExp(newBinaryOperatorExpression(d.parent, rhs, "+"))
return TimestampExp(Add(d.parent, rhs))
}
func (d *dateInterfaceImpl) SUB(rhs Interval) TimestampExpression {
return TimestampExp(newBinaryOperatorExpression(d.parent, rhs, "-"))
return TimestampExp(Sub(d.parent, rhs))
}
//---------------------------------------------------//

View file

@ -92,7 +92,8 @@ type binaryOperatorExpression struct {
operator string
}
func newBinaryOperatorExpression(lhs, rhs Serializer, operator string, additionalParam ...Expression) *binaryOperatorExpression {
// NewBinaryOperatorExpression creates new binaryOperatorExpression
func NewBinaryOperatorExpression(lhs, rhs Serializer, operator string, additionalParam ...Expression) *binaryOperatorExpression {
binaryExpression := &binaryOperatorExpression{
lhs: lhs,
rhs: rhs,

View file

@ -29,64 +29,59 @@ type floatInterfaceImpl struct {
}
func (n *floatInterfaceImpl) EQ(rhs FloatExpression) BoolExpression {
return eq(n.parent, rhs)
return Eq(n.parent, rhs)
}
func (n *floatInterfaceImpl) NOT_EQ(rhs FloatExpression) BoolExpression {
return notEq(n.parent, rhs)
return NotEq(n.parent, rhs)
}
func (n *floatInterfaceImpl) IS_DISTINCT_FROM(rhs FloatExpression) BoolExpression {
return isDistinctFrom(n.parent, rhs)
return IsDistinctFrom(n.parent, rhs)
}
func (n *floatInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs FloatExpression) BoolExpression {
return isNotDistinctFrom(n.parent, rhs)
return IsNotDistinctFrom(n.parent, rhs)
}
func (n *floatInterfaceImpl) GT(rhs FloatExpression) BoolExpression {
return gt(n.parent, rhs)
return Gt(n.parent, rhs)
}
func (n *floatInterfaceImpl) GT_EQ(rhs FloatExpression) BoolExpression {
return gtEq(n.parent, rhs)
return GtEq(n.parent, rhs)
}
func (n *floatInterfaceImpl) LT(expression FloatExpression) BoolExpression {
return lt(n.parent, expression)
func (n *floatInterfaceImpl) LT(rhs FloatExpression) BoolExpression {
return Lt(n.parent, rhs)
}
func (n *floatInterfaceImpl) LT_EQ(expression FloatExpression) BoolExpression {
return ltEq(n.parent, expression)
func (n *floatInterfaceImpl) LT_EQ(rhs FloatExpression) BoolExpression {
return LtEq(n.parent, rhs)
}
func (n *floatInterfaceImpl) ADD(expression NumericExpression) FloatExpression {
return newBinaryFloatExpression(n.parent, expression, "+")
func (n *floatInterfaceImpl) ADD(rhs NumericExpression) FloatExpression {
return FloatExp(Add(n.parent, rhs))
}
func (n *floatInterfaceImpl) SUB(expression NumericExpression) FloatExpression {
return newBinaryFloatExpression(n.parent, expression, "-")
func (n *floatInterfaceImpl) SUB(rhs NumericExpression) FloatExpression {
return FloatExp(Sub(n.parent, rhs))
}
func (n *floatInterfaceImpl) MUL(expression NumericExpression) FloatExpression {
return newBinaryFloatExpression(n.parent, expression, "*")
func (n *floatInterfaceImpl) MUL(rhs NumericExpression) FloatExpression {
return FloatExp(Mul(n.parent, rhs))
}
func (n *floatInterfaceImpl) DIV(expression NumericExpression) FloatExpression {
return newBinaryFloatExpression(n.parent, expression, "/")
func (n *floatInterfaceImpl) DIV(rhs NumericExpression) FloatExpression {
return FloatExp(Div(n.parent, rhs))
}
func (n *floatInterfaceImpl) MOD(expression NumericExpression) FloatExpression {
return newBinaryFloatExpression(n.parent, expression, "%")
func (n *floatInterfaceImpl) MOD(rhs NumericExpression) FloatExpression {
return FloatExp(Mod(n.parent, rhs))
}
func (n *floatInterfaceImpl) POW(expression NumericExpression) FloatExpression {
return POW(n.parent, expression)
}
//---------------------------------------------------//
func newBinaryFloatExpression(lhs, rhs Expression, operator string) FloatExpression {
return FloatExp(newBinaryOperatorExpression(lhs, rhs, operator))
func (n *floatInterfaceImpl) POW(rhs NumericExpression) FloatExpression {
return POW(n.parent, rhs)
}
//---------------------------------------------------//

View file

@ -54,71 +54,71 @@ type integerInterfaceImpl struct {
}
func (i *integerInterfaceImpl) EQ(rhs IntegerExpression) BoolExpression {
return eq(i.parent, rhs)
return Eq(i.parent, rhs)
}
func (i *integerInterfaceImpl) NOT_EQ(rhs IntegerExpression) BoolExpression {
return notEq(i.parent, rhs)
return NotEq(i.parent, rhs)
}
func (i *integerInterfaceImpl) IS_DISTINCT_FROM(rhs IntegerExpression) BoolExpression {
return isDistinctFrom(i.parent, rhs)
return IsDistinctFrom(i.parent, rhs)
}
func (i *integerInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs IntegerExpression) BoolExpression {
return isNotDistinctFrom(i.parent, rhs)
return IsNotDistinctFrom(i.parent, rhs)
}
func (i *integerInterfaceImpl) GT(rhs IntegerExpression) BoolExpression {
return gt(i.parent, rhs)
return Gt(i.parent, rhs)
}
func (i *integerInterfaceImpl) GT_EQ(rhs IntegerExpression) BoolExpression {
return gtEq(i.parent, rhs)
return GtEq(i.parent, rhs)
}
func (i *integerInterfaceImpl) LT(expression IntegerExpression) BoolExpression {
return lt(i.parent, expression)
func (i *integerInterfaceImpl) LT(rhs IntegerExpression) BoolExpression {
return Lt(i.parent, rhs)
}
func (i *integerInterfaceImpl) LT_EQ(expression IntegerExpression) BoolExpression {
return ltEq(i.parent, expression)
func (i *integerInterfaceImpl) LT_EQ(rhs IntegerExpression) BoolExpression {
return LtEq(i.parent, rhs)
}
func (i *integerInterfaceImpl) ADD(expression IntegerExpression) IntegerExpression {
return newBinaryIntegerOperatorExpression(i.parent, expression, "+")
func (i *integerInterfaceImpl) ADD(rhs IntegerExpression) IntegerExpression {
return IntExp(Add(i.parent, rhs))
}
func (i *integerInterfaceImpl) SUB(expression IntegerExpression) IntegerExpression {
return newBinaryIntegerOperatorExpression(i.parent, expression, "-")
func (i *integerInterfaceImpl) SUB(rhs IntegerExpression) IntegerExpression {
return IntExp(Sub(i.parent, rhs))
}
func (i *integerInterfaceImpl) MUL(expression IntegerExpression) IntegerExpression {
return newBinaryIntegerOperatorExpression(i.parent, expression, "*")
func (i *integerInterfaceImpl) MUL(rhs IntegerExpression) IntegerExpression {
return IntExp(Mul(i.parent, rhs))
}
func (i *integerInterfaceImpl) DIV(expression IntegerExpression) IntegerExpression {
return newBinaryIntegerOperatorExpression(i.parent, expression, "/")
func (i *integerInterfaceImpl) DIV(rhs IntegerExpression) IntegerExpression {
return IntExp(Div(i.parent, rhs))
}
func (i *integerInterfaceImpl) MOD(expression IntegerExpression) IntegerExpression {
return newBinaryIntegerOperatorExpression(i.parent, expression, "%")
func (i *integerInterfaceImpl) MOD(rhs IntegerExpression) IntegerExpression {
return IntExp(Mod(i.parent, rhs))
}
func (i *integerInterfaceImpl) POW(expression IntegerExpression) IntegerExpression {
return IntExp(POW(i.parent, expression))
func (i *integerInterfaceImpl) POW(rhs IntegerExpression) IntegerExpression {
return IntExp(POW(i.parent, rhs))
}
func (i *integerInterfaceImpl) BIT_AND(expression IntegerExpression) IntegerExpression {
return newBinaryIntegerOperatorExpression(i.parent, expression, "&")
func (i *integerInterfaceImpl) BIT_AND(rhs IntegerExpression) IntegerExpression {
return newBinaryIntegerOperatorExpression(i.parent, rhs, "&")
}
func (i *integerInterfaceImpl) BIT_OR(expression IntegerExpression) IntegerExpression {
return newBinaryIntegerOperatorExpression(i.parent, expression, "|")
func (i *integerInterfaceImpl) BIT_OR(rhs IntegerExpression) IntegerExpression {
return newBinaryIntegerOperatorExpression(i.parent, rhs, "|")
}
func (i *integerInterfaceImpl) BIT_XOR(expression IntegerExpression) IntegerExpression {
return newBinaryIntegerOperatorExpression(i.parent, expression, "#")
func (i *integerInterfaceImpl) BIT_XOR(rhs IntegerExpression) IntegerExpression {
return newBinaryIntegerOperatorExpression(i.parent, rhs, "#")
}
func (i *integerInterfaceImpl) BIT_SHIFT_LEFT(intExpression IntegerExpression) IntegerExpression {
@ -131,7 +131,7 @@ func (i *integerInterfaceImpl) BIT_SHIFT_RIGHT(intExpression IntegerExpression)
//---------------------------------------------------//
func newBinaryIntegerOperatorExpression(lhs, rhs IntegerExpression, operator string) IntegerExpression {
return IntExp(newBinaryOperatorExpression(lhs, rhs, operator))
return IntExp(NewBinaryOperatorExpression(lhs, rhs, operator))
}
//---------------------------------------------------//

View file

@ -11,22 +11,27 @@ 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) Interval {
newInterval := &intervalImpl{
func NewInterval(s Serializer) *IntervalImpl {
newInterval := &IntervalImpl{
interval: s,
}
return newInterval
}
type intervalImpl struct {
// IntervalImpl is implementation of Interval type
type IntervalImpl struct {
interval Serializer
IsIntervalImpl
}
func (i intervalImpl) isInterval() {}
func (i intervalImpl) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
func (i IntervalImpl) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
out.WriteString("INTERVAL")
i.interval.serialize(statement, out, options...)
}

View file

@ -346,9 +346,9 @@ func (n *rawExpression) serialize(statement StatementType, out *SQLBuilder, opti
// Raw can be used for any unsupported functions, operators or expressions.
// For example: Raw("current_database()")
func Raw(raw string) Expression {
func Raw(raw string, parent ...Expression) Expression {
rawExp := &rawExpression{Raw: raw}
rawExp.ExpressionInterfaceImpl.Parent = rawExp
rawExp.ExpressionInterfaceImpl.Parent = OptionalOrDefaultExpression(rawExp, parent...)
return rawExp
}

View file

@ -29,44 +29,71 @@ func EXISTS(subQuery Expression) BoolExpression {
return newPrefixBoolOperatorExpression(subQuery, "EXISTS")
}
// Returns a representation of "a=b"
func eq(lhs, rhs Expression) BoolExpression {
// Eq returns a representation of "a=b"
func Eq(lhs, rhs Expression) BoolExpression {
return newBinaryBoolOperatorExpression(lhs, rhs, "=")
}
// Returns a representation of "a!=b"
func notEq(lhs, rhs Expression) BoolExpression {
// NotEq returns a representation of "a!=b"
func NotEq(lhs, rhs Expression) BoolExpression {
return newBinaryBoolOperatorExpression(lhs, rhs, "!=")
}
func isDistinctFrom(lhs, rhs Expression) BoolExpression {
// IsDistinctFrom returns a representation of "a IS DISTINCT FROM b"
func IsDistinctFrom(lhs, rhs Expression) BoolExpression {
return newBinaryBoolOperatorExpression(lhs, rhs, "IS DISTINCT FROM")
}
func isNotDistinctFrom(lhs, rhs Expression) BoolExpression {
// IsNotDistinctFrom returns a representation of "a IS NOT DISTINCT FROM b"
func IsNotDistinctFrom(lhs, rhs Expression) BoolExpression {
return newBinaryBoolOperatorExpression(lhs, rhs, "IS NOT DISTINCT FROM")
}
// Returns a representation of "a<b"
func lt(lhs Expression, rhs Expression) BoolExpression {
// Lt returns a representation of "a<b"
func Lt(lhs Expression, rhs Expression) BoolExpression {
return newBinaryBoolOperatorExpression(lhs, rhs, "<")
}
// Returns a representation of "a<=b"
func ltEq(lhs, rhs Expression) BoolExpression {
// LtEq returns a representation of "a<=b"
func LtEq(lhs, rhs Expression) BoolExpression {
return newBinaryBoolOperatorExpression(lhs, rhs, "<=")
}
// Returns a representation of "a>b"
func gt(lhs, rhs Expression) BoolExpression {
// Gt returns a representation of "a>b"
func Gt(lhs, rhs Expression) BoolExpression {
return newBinaryBoolOperatorExpression(lhs, rhs, ">")
}
// Returns a representation of "a>=b"
func gtEq(lhs, rhs Expression) BoolExpression {
// GtEq returns a representation of "a>=b"
func GtEq(lhs, rhs Expression) BoolExpression {
return newBinaryBoolOperatorExpression(lhs, rhs, ">=")
}
// Add notEq returns a representation of "a + b"
func Add(lhs, rhs Serializer) Expression {
return NewBinaryOperatorExpression(lhs, rhs, "+")
}
// Sub notEq returns a representation of "a - b"
func Sub(lhs, rhs Serializer) Expression {
return NewBinaryOperatorExpression(lhs, rhs, "-")
}
// Mul returns a representation of "a * b"
func Mul(lhs, rhs Serializer) Expression {
return NewBinaryOperatorExpression(lhs, rhs, "*")
}
// Div returns a representation of "a / b"
func Div(lhs, rhs Serializer) Expression {
return NewBinaryOperatorExpression(lhs, rhs, "/")
}
// Mod returns a representation of "a % b"
func Mod(lhs, rhs Serializer) Expression {
return NewBinaryOperatorExpression(lhs, rhs, "%")
}
// --------------- CASE operator -------------------//
// CaseOperator is interface for SQL case operator

View file

@ -28,35 +28,35 @@ type stringInterfaceImpl struct {
}
func (s *stringInterfaceImpl) EQ(rhs StringExpression) BoolExpression {
return eq(s.parent, rhs)
return Eq(s.parent, rhs)
}
func (s *stringInterfaceImpl) NOT_EQ(rhs StringExpression) BoolExpression {
return notEq(s.parent, rhs)
return NotEq(s.parent, rhs)
}
func (s *stringInterfaceImpl) IS_DISTINCT_FROM(rhs StringExpression) BoolExpression {
return isDistinctFrom(s.parent, rhs)
return IsDistinctFrom(s.parent, rhs)
}
func (s *stringInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs StringExpression) BoolExpression {
return isNotDistinctFrom(s.parent, rhs)
return IsNotDistinctFrom(s.parent, rhs)
}
func (s *stringInterfaceImpl) GT(rhs StringExpression) BoolExpression {
return gt(s.parent, rhs)
return Gt(s.parent, rhs)
}
func (s *stringInterfaceImpl) GT_EQ(rhs StringExpression) BoolExpression {
return gtEq(s.parent, rhs)
return GtEq(s.parent, rhs)
}
func (s *stringInterfaceImpl) LT(rhs StringExpression) BoolExpression {
return lt(s.parent, rhs)
return Lt(s.parent, rhs)
}
func (s *stringInterfaceImpl) LT_EQ(rhs StringExpression) BoolExpression {
return ltEq(s.parent, rhs)
return LtEq(s.parent, rhs)
}
func (s *stringInterfaceImpl) CONCAT(rhs Expression) StringExpression {
@ -81,7 +81,7 @@ func (s *stringInterfaceImpl) NOT_REGEXP_LIKE(pattern StringExpression, caseSens
//---------------------------------------------------//
func newBinaryStringOperatorExpression(lhs, rhs Expression, operator string) StringExpression {
return StringExp(newBinaryOperatorExpression(lhs, rhs, operator))
return StringExp(NewBinaryOperatorExpression(lhs, rhs, operator))
}
//---------------------------------------------------//

View file

@ -23,43 +23,43 @@ type timeInterfaceImpl struct {
}
func (t *timeInterfaceImpl) EQ(rhs TimeExpression) BoolExpression {
return eq(t.parent, rhs)
return Eq(t.parent, rhs)
}
func (t *timeInterfaceImpl) NOT_EQ(rhs TimeExpression) BoolExpression {
return notEq(t.parent, rhs)
return NotEq(t.parent, rhs)
}
func (t *timeInterfaceImpl) IS_DISTINCT_FROM(rhs TimeExpression) BoolExpression {
return isDistinctFrom(t.parent, rhs)
return IsDistinctFrom(t.parent, rhs)
}
func (t *timeInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs TimeExpression) BoolExpression {
return isNotDistinctFrom(t.parent, rhs)
return IsNotDistinctFrom(t.parent, rhs)
}
func (t *timeInterfaceImpl) LT(rhs TimeExpression) BoolExpression {
return lt(t.parent, rhs)
return Lt(t.parent, rhs)
}
func (t *timeInterfaceImpl) LT_EQ(rhs TimeExpression) BoolExpression {
return ltEq(t.parent, rhs)
return LtEq(t.parent, rhs)
}
func (t *timeInterfaceImpl) GT(rhs TimeExpression) BoolExpression {
return gt(t.parent, rhs)
return Gt(t.parent, rhs)
}
func (t *timeInterfaceImpl) GT_EQ(rhs TimeExpression) BoolExpression {
return gtEq(t.parent, rhs)
return GtEq(t.parent, rhs)
}
func (t *timeInterfaceImpl) ADD(rhs Interval) TimeExpression {
return TimeExp(newBinaryOperatorExpression(t.parent, rhs, "+"))
return TimeExp(Add(t.parent, rhs))
}
func (t *timeInterfaceImpl) SUB(rhs Interval) TimeExpression {
return TimeExp(newBinaryOperatorExpression(t.parent, rhs, "-"))
return TimeExp(Sub(t.parent, rhs))
}
//---------------------------------------------------//

View file

@ -23,43 +23,43 @@ type timestampInterfaceImpl struct {
}
func (t *timestampInterfaceImpl) EQ(rhs TimestampExpression) BoolExpression {
return eq(t.parent, rhs)
return Eq(t.parent, rhs)
}
func (t *timestampInterfaceImpl) NOT_EQ(rhs TimestampExpression) BoolExpression {
return notEq(t.parent, rhs)
return NotEq(t.parent, rhs)
}
func (t *timestampInterfaceImpl) IS_DISTINCT_FROM(rhs TimestampExpression) BoolExpression {
return isDistinctFrom(t.parent, rhs)
return IsDistinctFrom(t.parent, rhs)
}
func (t *timestampInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs TimestampExpression) BoolExpression {
return isNotDistinctFrom(t.parent, rhs)
return IsNotDistinctFrom(t.parent, rhs)
}
func (t *timestampInterfaceImpl) LT(rhs TimestampExpression) BoolExpression {
return lt(t.parent, rhs)
return Lt(t.parent, rhs)
}
func (t *timestampInterfaceImpl) LT_EQ(rhs TimestampExpression) BoolExpression {
return ltEq(t.parent, rhs)
return LtEq(t.parent, rhs)
}
func (t *timestampInterfaceImpl) GT(rhs TimestampExpression) BoolExpression {
return gt(t.parent, rhs)
return Gt(t.parent, rhs)
}
func (t *timestampInterfaceImpl) GT_EQ(rhs TimestampExpression) BoolExpression {
return gtEq(t.parent, rhs)
return GtEq(t.parent, rhs)
}
func (t *timestampInterfaceImpl) ADD(rhs Interval) TimestampExpression {
return TimestampExp(newBinaryOperatorExpression(t.parent, rhs, "+"))
return TimestampExp(Add(t.parent, rhs))
}
func (t *timestampInterfaceImpl) SUB(rhs Interval) TimestampExpression {
return TimestampExp(newBinaryOperatorExpression(t.parent, rhs, "-"))
return TimestampExp(Sub(t.parent, rhs))
}
//-------------------------------------------------

View file

@ -23,43 +23,43 @@ type timestampzInterfaceImpl struct {
}
func (t *timestampzInterfaceImpl) EQ(rhs TimestampzExpression) BoolExpression {
return eq(t.parent, rhs)
return Eq(t.parent, rhs)
}
func (t *timestampzInterfaceImpl) NOT_EQ(rhs TimestampzExpression) BoolExpression {
return notEq(t.parent, rhs)
return NotEq(t.parent, rhs)
}
func (t *timestampzInterfaceImpl) IS_DISTINCT_FROM(rhs TimestampzExpression) BoolExpression {
return isDistinctFrom(t.parent, rhs)
return IsDistinctFrom(t.parent, rhs)
}
func (t *timestampzInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs TimestampzExpression) BoolExpression {
return isNotDistinctFrom(t.parent, rhs)
return IsNotDistinctFrom(t.parent, rhs)
}
func (t *timestampzInterfaceImpl) LT(rhs TimestampzExpression) BoolExpression {
return lt(t.parent, rhs)
return Lt(t.parent, rhs)
}
func (t *timestampzInterfaceImpl) LT_EQ(rhs TimestampzExpression) BoolExpression {
return ltEq(t.parent, rhs)
return LtEq(t.parent, rhs)
}
func (t *timestampzInterfaceImpl) GT(rhs TimestampzExpression) BoolExpression {
return gt(t.parent, rhs)
return Gt(t.parent, rhs)
}
func (t *timestampzInterfaceImpl) GT_EQ(rhs TimestampzExpression) BoolExpression {
return gtEq(t.parent, rhs)
return GtEq(t.parent, rhs)
}
func (t *timestampzInterfaceImpl) ADD(rhs Interval) TimestampzExpression {
return TimestampzExp(newBinaryOperatorExpression(t.parent, rhs, "+"))
return TimestampzExp(Add(t.parent, rhs))
}
func (t *timestampzInterfaceImpl) SUB(rhs Interval) TimestampzExpression {
return TimestampzExp(newBinaryOperatorExpression(t.parent, rhs, "-"))
return TimestampzExp(Sub(t.parent, rhs))
}
//-------------------------------------------------

View file

@ -23,43 +23,43 @@ type timezInterfaceImpl struct {
}
func (t *timezInterfaceImpl) EQ(rhs TimezExpression) BoolExpression {
return eq(t.parent, rhs)
return Eq(t.parent, rhs)
}
func (t *timezInterfaceImpl) NOT_EQ(rhs TimezExpression) BoolExpression {
return notEq(t.parent, rhs)
return NotEq(t.parent, rhs)
}
func (t *timezInterfaceImpl) IS_DISTINCT_FROM(rhs TimezExpression) BoolExpression {
return isDistinctFrom(t.parent, rhs)
return IsDistinctFrom(t.parent, rhs)
}
func (t *timezInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs TimezExpression) BoolExpression {
return isNotDistinctFrom(t.parent, rhs)
return IsNotDistinctFrom(t.parent, rhs)
}
func (t *timezInterfaceImpl) LT(rhs TimezExpression) BoolExpression {
return lt(t.parent, rhs)
return Lt(t.parent, rhs)
}
func (t *timezInterfaceImpl) LT_EQ(rhs TimezExpression) BoolExpression {
return ltEq(t.parent, rhs)
return LtEq(t.parent, rhs)
}
func (t *timezInterfaceImpl) GT(rhs TimezExpression) BoolExpression {
return gt(t.parent, rhs)
return Gt(t.parent, rhs)
}
func (t *timezInterfaceImpl) GT_EQ(rhs TimezExpression) BoolExpression {
return gtEq(t.parent, rhs)
return GtEq(t.parent, rhs)
}
func (t *timezInterfaceImpl) ADD(rhs Interval) TimezExpression {
return TimezExp(newBinaryOperatorExpression(t.parent, rhs, "+"))
return TimezExp(Add(t.parent, rhs))
}
func (t *timezInterfaceImpl) SUB(rhs Interval) TimezExpression {
return TimezExp(newBinaryOperatorExpression(t.parent, rhs, "-"))
return TimezExp(Sub(t.parent, rhs))
}
//---------------------------------------------------//

View file

@ -187,3 +187,23 @@ func UnwidColumnList(columns []Column) []Column {
return ret
}
// OptionalOrDefaultString will return first value from variable argument list str or
// defaultStr if variable argument list is empty
func OptionalOrDefaultString(defaultStr string, str ...string) string {
if len(str) > 0 {
return str[0]
}
return defaultStr
}
// OptionalOrDefaultExpression will return first value from variable argument list expression or
// defaultExpression if variable argument list is empty
func OptionalOrDefaultExpression(defaultExpression Expression, expression ...Expression) Expression {
if len(expression) > 0 {
return expression[0]
}
return defaultExpression
}

View file

@ -0,0 +1,19 @@
package jet
import (
"gotest.tools/assert"
"testing"
)
func TestOptionalOrDefaultString(t *testing.T) {
assert.Equal(t, OptionalOrDefaultString("default"), "default")
assert.Equal(t, OptionalOrDefaultString("default", "optional"), "optional")
}
func TestOptionalOrDefaultExpression(t *testing.T) {
defaultExpression := table2ColFloat
optionalExpression := table1Col1
assert.Equal(t, OptionalOrDefaultExpression(defaultExpression), defaultExpression)
assert.Equal(t, OptionalOrDefaultExpression(defaultExpression, optionalExpression), optionalExpression)
}

View file

@ -1,6 +1,8 @@
package postgres
import "github.com/go-jet/jet/internal/jet"
import (
"github.com/go-jet/jet/internal/jet"
)
// Column is common column interface for all types of columns.
type Column = jet.ColumnExpression
@ -62,3 +64,34 @@ type ColumnTimestampz = jet.ColumnTimestampz
// TimestampzColumn creates named timestamp with time zone column.
var TimestampzColumn = jet.TimestampzColumn
//------------------------------------------------------//
// ColumnInterval is interface of PostgreSQL interval columns.
type ColumnInterval interface {
IntervalExpression
jet.Column
From(subQuery SelectTable) ColumnInterval
}
type intervalColumnImpl struct {
jet.ColumnExpressionImpl
intervalInterfaceImpl
}
func (i *intervalColumnImpl) From(subQuery SelectTable) ColumnInterval {
newIntervalColumn := IntervalColumn(i.Name())
jet.SetTableName(newIntervalColumn, i.TableName())
jet.SetSubQuery(newIntervalColumn, subQuery)
return newIntervalColumn
}
// IntervalColumn creates named interval column.
func IntervalColumn(name string) ColumnInterval {
intervalColumn := &intervalColumnImpl{}
intervalColumn.ColumnExpressionImpl = jet.NewColumnImpl(name, "", intervalColumn)
intervalColumn.intervalInterfaceImpl.parent = intervalColumn
return intervalColumn
}

20
postgres/columns_test.go Normal file
View file

@ -0,0 +1,20 @@
package postgres
import (
"testing"
)
func TestNewIntervalColumn(t *testing.T) {
subQuery := SELECT(Int(1)).AsTable("sub_query")
subQueryIntervalColumn := IntervalColumn("col_interval").From(subQuery)
assertSerialize(t, subQueryIntervalColumn, `sub_query."col_interval"`)
assertSerialize(t, subQueryIntervalColumn.EQ(INTERVAL(2, HOUR, 10, MINUTE)),
`(sub_query."col_interval" = INTERVAL '2 HOUR 10 MINUTE')`)
assertProjectionSerialize(t, subQueryIntervalColumn, `sub_query."col_interval" AS "col_interval"`)
subQueryIntervalColumn2 := table1ColInterval.From(subQuery)
assertSerialize(t, subQueryIntervalColumn2, `sub_query."table1.col_interval"`)
assertSerialize(t, subQueryIntervalColumn2.EQ(INTERVAL(1, DAY)), `(sub_query."table1.col_interval" = INTERVAL '1 DAY')`)
assertProjectionSerialize(t, subQueryIntervalColumn2, `sub_query."table1.col_interval" AS "table1.col_interval"`)
}

View file

@ -12,6 +12,9 @@ type BoolExpression = jet.BoolExpression
// StringExpression interface
type StringExpression = jet.StringExpression
// NumericExpression interface
type NumericExpression = jet.NumericExpression
// IntegerExpression interface
type IntegerExpression = jet.IntegerExpression

View file

@ -27,39 +27,109 @@ const (
MILLENNIUM
)
type intervalExpressionImpl struct {
jet.Interval
jet.ExpressionInterfaceImpl
}
// IntervalExpression is representation of postgres INTERVAL
type IntervalExpression interface {
jet.IsInterval
jet.Expression
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
ADD(rhs IntervalExpression) IntervalExpression
SUB(rhs IntervalExpression) IntervalExpression
MUL(rhs NumericExpression) IntervalExpression
DIV(rhs NumericExpression) IntervalExpression
}
type intervalInterfaceImpl struct {
jet.IsIntervalImpl
parent IntervalExpression
}
func (i *intervalInterfaceImpl) EQ(rhs IntervalExpression) BoolExpression {
return jet.Eq(i.parent, rhs)
}
func (i *intervalInterfaceImpl) NOT_EQ(rhs IntervalExpression) BoolExpression {
return jet.NotEq(i.parent, rhs)
}
func (i *intervalInterfaceImpl) IS_DISTINCT_FROM(rhs IntervalExpression) BoolExpression {
return jet.IsDistinctFrom(i.parent, rhs)
}
func (i *intervalInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs IntervalExpression) BoolExpression {
return jet.IsNotDistinctFrom(i.parent, rhs)
}
func (i *intervalInterfaceImpl) LT(rhs IntervalExpression) BoolExpression {
return jet.Lt(i.parent, rhs)
}
func (i *intervalInterfaceImpl) LT_EQ(rhs IntervalExpression) BoolExpression {
return jet.LtEq(i.parent, rhs)
}
func (i *intervalInterfaceImpl) GT(rhs IntervalExpression) BoolExpression {
return jet.Gt(i.parent, rhs)
}
func (i *intervalInterfaceImpl) GT_EQ(rhs IntervalExpression) BoolExpression {
return jet.GtEq(i.parent, rhs)
}
func (i *intervalInterfaceImpl) ADD(rhs IntervalExpression) IntervalExpression {
return IntervalExp(jet.Add(i.parent, rhs))
}
func (i *intervalInterfaceImpl) SUB(rhs IntervalExpression) IntervalExpression {
return IntervalExp(jet.Sub(i.parent, rhs))
}
func (i *intervalInterfaceImpl) MUL(rhs NumericExpression) IntervalExpression {
return IntervalExp(jet.Mul(i.parent, rhs))
}
func (i *intervalInterfaceImpl) DIV(rhs NumericExpression) IntervalExpression {
return IntervalExp(jet.Div(i.parent, rhs))
}
type intervalExpression struct {
jet.Expression
intervalInterfaceImpl
}
// INTERVAL creates new interval expression from the list of quantity-unit pairs.
// For example: INTERVAL(1, DAY, 3, MINUTE)
func INTERVAL(quantityAndUnit ...quantityAndUnit) IntervalExpression {
if len(quantityAndUnit)%2 != 0 {
quantityAndUnitLen := len(quantityAndUnit)
if quantityAndUnitLen == 0 || quantityAndUnitLen%2 != 0 {
panic("jet: invalid number of quantity and unit fields")
}
fields := []string{}
for i := 0; i < len(quantityAndUnit); i += 2 {
quantity := strconv.FormatFloat(float64(quantityAndUnit[i]), 'f', -1, 64)
quantity := strconv.FormatFloat(quantityAndUnit[i], 'f', -1, 64)
unitString := unitToString(quantityAndUnit[i+1])
fields = append(fields, quantity+" "+unitString)
}
intervalStr := fmt.Sprintf("'%s'", strings.Join(fields, " "))
intervalStr := fmt.Sprintf("INTERVAL '%s'", strings.Join(fields, " "))
newInterval := &intervalExpressionImpl{
Interval: jet.NewInterval(jet.Raw(intervalStr)),
}
newInterval := &intervalExpression{}
newInterval.ExpressionInterfaceImpl.Parent = newInterval
newInterval.Expression = jet.Raw(intervalStr, newInterval)
newInterval.intervalInterfaceImpl.parent = newInterval
return newInterval
}
@ -136,13 +206,14 @@ func unitToString(unit quantityAndUnit) string {
//---------------------------------------------------//
type intervalWrapper struct {
jet.IsInterval
intervalInterfaceImpl
Expression
}
func newIntervalExpressionWrap(expression Expression) IntervalExpression {
intervalWrap := intervalWrapper{Expression: expression}
return &intervalWrap
intervalWrap := &intervalWrapper{Expression: expression}
intervalWrap.intervalInterfaceImpl.parent = intervalWrap
return intervalWrap
}
// IntervalExp is interval expression wrapper around arbitrary expression.

View file

@ -44,11 +44,12 @@ func TestINTERVALd(t *testing.T) {
}
func TestINTERVAL_InvalidParams(t *testing.T) {
assertPanicErr(t, func() { INTERVAL() }, "jet: invalid number of quantity and unit fields")
assertPanicErr(t, func() { INTERVAL(1) }, "jet: invalid number of quantity and unit fields")
assertPanicErr(t, func() { INTERVAL(1, 2) }, "jet: invalid INTERVAL unit type")
}
func TestIntervalArithmetic(t *testing.T) {
func TestDateTimeIntervalArithmetic(t *testing.T) {
assertSerialize(t, table2ColDate.ADD(INTERVAL(1, HOUR)), "(table2.col_date + INTERVAL '1 HOUR')")
assertSerialize(t, table2ColDate.SUB(INTERVAL(1, HOUR)), "(table2.col_date - INTERVAL '1 HOUR')")
assertSerialize(t, table2ColTime.ADD(INTERVAL(1, HOUR)), "(table2.col_time + INTERVAL '1 HOUR')")
@ -60,3 +61,24 @@ func TestIntervalArithmetic(t *testing.T) {
assertSerialize(t, table2ColTimestampz.ADD(INTERVAL(1, HOUR)), "(table2.col_timestampz + INTERVAL '1 HOUR')")
assertSerialize(t, table2ColTimestampz.SUB(INTERVAL(1, HOUR)), "(table2.col_timestampz - INTERVAL '1 HOUR')")
}
func TestIntervalExpressionMethods(t *testing.T) {
assertSerialize(t, table1ColInterval.EQ(table2ColInterval), "(table1.col_interval = table2.col_interval)")
assertSerialize(t, table1ColInterval.EQ(INTERVAL(10, SECOND)), "(table1.col_interval = INTERVAL '10 SECOND')")
assertSerialize(t, table1ColInterval.EQ(INTERVALd(11*time.Minute)), "(table1.col_interval = INTERVAL '11 MINUTE')")
assertSerialize(t, table1ColInterval.EQ(INTERVALd(11*time.Minute)).EQ(Bool(false)),
"((table1.col_interval = INTERVAL '11 MINUTE') = $1)", false)
assertSerialize(t, table1ColInterval.NOT_EQ(table2ColInterval), "(table1.col_interval != table2.col_interval)")
assertSerialize(t, table1ColInterval.IS_DISTINCT_FROM(table2ColInterval), "(table1.col_interval IS DISTINCT FROM table2.col_interval)")
assertSerialize(t, table1ColInterval.IS_NOT_DISTINCT_FROM(table2ColInterval), "(table1.col_interval IS NOT DISTINCT FROM table2.col_interval)")
assertSerialize(t, table1ColInterval.LT(table2ColInterval), "(table1.col_interval < table2.col_interval)")
assertSerialize(t, table1ColInterval.LT_EQ(table2ColInterval), "(table1.col_interval <= table2.col_interval)")
assertSerialize(t, table1ColInterval.GT(table2ColInterval), "(table1.col_interval > table2.col_interval)")
assertSerialize(t, table1ColInterval.GT_EQ(table2ColInterval), "(table1.col_interval >= table2.col_interval)")
assertSerialize(t, table1ColInterval.ADD(table2ColInterval), "(table1.col_interval + table2.col_interval)")
assertSerialize(t, table1ColInterval.SUB(table2ColInterval), "(table1.col_interval - table2.col_interval)")
assertSerialize(t, table1ColInterval.MUL(table2ColInt), "(table1.col_interval * table2.col_int)")
assertSerialize(t, table1ColInterval.MUL(table2ColFloat), "(table1.col_interval * table2.col_float)")
assertSerialize(t, table1ColInterval.DIV(table2ColInt), "(table1.col_interval / table2.col_int)")
assertSerialize(t, table1ColInterval.DIV(table2ColFloat), "(table1.col_interval / table2.col_float)")
}

View file

@ -17,6 +17,7 @@ var table1ColTimestamp = TimestampColumn("col_timestamp")
var table1ColTimestampz = TimestampzColumn("col_timestampz")
var table1ColBool = BoolColumn("col_bool")
var table1ColDate = DateColumn("col_date")
var table1ColInterval = IntervalColumn("col_interval")
var table1 = NewTable(
"db",
@ -31,6 +32,7 @@ var table1 = NewTable(
table1ColDate,
table1ColTimestamp,
table1ColTimestampz,
table1ColInterval,
)
var table2Col3 = IntegerColumn("col3")
@ -44,6 +46,7 @@ var table2ColTimez = TimezColumn("col_timez")
var table2ColTimestamp = TimestampColumn("col_timestamp")
var table2ColTimestampz = TimestampzColumn("col_timestampz")
var table2ColDate = DateColumn("col_date")
var table2ColInterval = IntervalColumn("col_interval")
var table2 = NewTable(
"db",
@ -59,6 +62,7 @@ var table2 = NewTable(
table2ColDate,
table2ColTimestamp,
table2ColTimestampz,
table2ColInterval,
)
var table3Col1 = IntegerColumn("col1")

View file

@ -71,6 +71,152 @@ func TestAllTypesInsertQuery(t *testing.T) {
assert.DeepEqual(t, dest[1], allTypesRow1)
}
func TestAllTypesFromSubQuery(t *testing.T) {
subQuery := SELECT(AllTypes.AllColumns).
FROM(AllTypes).
AsTable("allTypesSubQuery")
mainQuery := SELECT(subQuery.AllColumns()).
FROM(subQuery).
LIMIT(2)
assert.Equal(t, mainQuery.DebugSql(), `
SELECT "allTypesSubQuery"."all_types.small_int_ptr" AS "all_types.small_int_ptr",
"allTypesSubQuery"."all_types.small_int" AS "all_types.small_int",
"allTypesSubQuery"."all_types.integer_ptr" AS "all_types.integer_ptr",
"allTypesSubQuery"."all_types.integer" AS "all_types.integer",
"allTypesSubQuery"."all_types.big_int_ptr" AS "all_types.big_int_ptr",
"allTypesSubQuery"."all_types.big_int" AS "all_types.big_int",
"allTypesSubQuery"."all_types.decimal_ptr" AS "all_types.decimal_ptr",
"allTypesSubQuery"."all_types.decimal" AS "all_types.decimal",
"allTypesSubQuery"."all_types.numeric_ptr" AS "all_types.numeric_ptr",
"allTypesSubQuery"."all_types.numeric" AS "all_types.numeric",
"allTypesSubQuery"."all_types.real_ptr" AS "all_types.real_ptr",
"allTypesSubQuery"."all_types.real" AS "all_types.real",
"allTypesSubQuery"."all_types.double_precision_ptr" AS "all_types.double_precision_ptr",
"allTypesSubQuery"."all_types.double_precision" AS "all_types.double_precision",
"allTypesSubQuery"."all_types.smallserial" AS "all_types.smallserial",
"allTypesSubQuery"."all_types.serial" AS "all_types.serial",
"allTypesSubQuery"."all_types.bigserial" AS "all_types.bigserial",
"allTypesSubQuery"."all_types.var_char_ptr" AS "all_types.var_char_ptr",
"allTypesSubQuery"."all_types.var_char" AS "all_types.var_char",
"allTypesSubQuery"."all_types.char_ptr" AS "all_types.char_ptr",
"allTypesSubQuery"."all_types.char" AS "all_types.char",
"allTypesSubQuery"."all_types.text_ptr" AS "all_types.text_ptr",
"allTypesSubQuery"."all_types.text" AS "all_types.text",
"allTypesSubQuery"."all_types.bytea_ptr" AS "all_types.bytea_ptr",
"allTypesSubQuery"."all_types.bytea" AS "all_types.bytea",
"allTypesSubQuery"."all_types.timestampz_ptr" AS "all_types.timestampz_ptr",
"allTypesSubQuery"."all_types.timestampz" AS "all_types.timestampz",
"allTypesSubQuery"."all_types.timestamp_ptr" AS "all_types.timestamp_ptr",
"allTypesSubQuery"."all_types.timestamp" AS "all_types.timestamp",
"allTypesSubQuery"."all_types.date_ptr" AS "all_types.date_ptr",
"allTypesSubQuery"."all_types.date" AS "all_types.date",
"allTypesSubQuery"."all_types.timez_ptr" AS "all_types.timez_ptr",
"allTypesSubQuery"."all_types.timez" AS "all_types.timez",
"allTypesSubQuery"."all_types.time_ptr" AS "all_types.time_ptr",
"allTypesSubQuery"."all_types.time" AS "all_types.time",
"allTypesSubQuery"."all_types.interval_ptr" AS "all_types.interval_ptr",
"allTypesSubQuery"."all_types.interval" AS "all_types.interval",
"allTypesSubQuery"."all_types.boolean_ptr" AS "all_types.boolean_ptr",
"allTypesSubQuery"."all_types.boolean" AS "all_types.boolean",
"allTypesSubQuery"."all_types.point_ptr" AS "all_types.point_ptr",
"allTypesSubQuery"."all_types.bit_ptr" AS "all_types.bit_ptr",
"allTypesSubQuery"."all_types.bit" AS "all_types.bit",
"allTypesSubQuery"."all_types.bit_varying_ptr" AS "all_types.bit_varying_ptr",
"allTypesSubQuery"."all_types.bit_varying" AS "all_types.bit_varying",
"allTypesSubQuery"."all_types.tsvector_ptr" AS "all_types.tsvector_ptr",
"allTypesSubQuery"."all_types.tsvector" AS "all_types.tsvector",
"allTypesSubQuery"."all_types.uuid_ptr" AS "all_types.uuid_ptr",
"allTypesSubQuery"."all_types.uuid" AS "all_types.uuid",
"allTypesSubQuery"."all_types.xml_ptr" AS "all_types.xml_ptr",
"allTypesSubQuery"."all_types.xml" AS "all_types.xml",
"allTypesSubQuery"."all_types.json_ptr" AS "all_types.json_ptr",
"allTypesSubQuery"."all_types.json" AS "all_types.json",
"allTypesSubQuery"."all_types.jsonb_ptr" AS "all_types.jsonb_ptr",
"allTypesSubQuery"."all_types.jsonb" AS "all_types.jsonb",
"allTypesSubQuery"."all_types.integer_array_ptr" AS "all_types.integer_array_ptr",
"allTypesSubQuery"."all_types.integer_array" AS "all_types.integer_array",
"allTypesSubQuery"."all_types.text_array_ptr" AS "all_types.text_array_ptr",
"allTypesSubQuery"."all_types.text_array" AS "all_types.text_array",
"allTypesSubQuery"."all_types.jsonb_array" AS "all_types.jsonb_array",
"allTypesSubQuery"."all_types.text_multi_dim_array_ptr" AS "all_types.text_multi_dim_array_ptr",
"allTypesSubQuery"."all_types.text_multi_dim_array" AS "all_types.text_multi_dim_array"
FROM (
SELECT all_types.small_int_ptr AS "all_types.small_int_ptr",
all_types.small_int AS "all_types.small_int",
all_types.integer_ptr AS "all_types.integer_ptr",
all_types.integer AS "all_types.integer",
all_types.big_int_ptr AS "all_types.big_int_ptr",
all_types.big_int AS "all_types.big_int",
all_types.decimal_ptr AS "all_types.decimal_ptr",
all_types.decimal AS "all_types.decimal",
all_types.numeric_ptr AS "all_types.numeric_ptr",
all_types.numeric AS "all_types.numeric",
all_types.real_ptr AS "all_types.real_ptr",
all_types.real AS "all_types.real",
all_types.double_precision_ptr AS "all_types.double_precision_ptr",
all_types.double_precision AS "all_types.double_precision",
all_types.smallserial AS "all_types.smallserial",
all_types.serial AS "all_types.serial",
all_types.bigserial AS "all_types.bigserial",
all_types.var_char_ptr AS "all_types.var_char_ptr",
all_types.var_char AS "all_types.var_char",
all_types.char_ptr AS "all_types.char_ptr",
all_types.char AS "all_types.char",
all_types.text_ptr AS "all_types.text_ptr",
all_types.text AS "all_types.text",
all_types.bytea_ptr AS "all_types.bytea_ptr",
all_types.bytea AS "all_types.bytea",
all_types.timestampz_ptr AS "all_types.timestampz_ptr",
all_types.timestampz AS "all_types.timestampz",
all_types.timestamp_ptr AS "all_types.timestamp_ptr",
all_types.timestamp AS "all_types.timestamp",
all_types.date_ptr AS "all_types.date_ptr",
all_types.date AS "all_types.date",
all_types.timez_ptr AS "all_types.timez_ptr",
all_types.timez AS "all_types.timez",
all_types.time_ptr AS "all_types.time_ptr",
all_types.time AS "all_types.time",
all_types.interval_ptr AS "all_types.interval_ptr",
all_types.interval AS "all_types.interval",
all_types.boolean_ptr AS "all_types.boolean_ptr",
all_types.boolean AS "all_types.boolean",
all_types.point_ptr AS "all_types.point_ptr",
all_types.bit_ptr AS "all_types.bit_ptr",
all_types.bit AS "all_types.bit",
all_types.bit_varying_ptr AS "all_types.bit_varying_ptr",
all_types.bit_varying AS "all_types.bit_varying",
all_types.tsvector_ptr AS "all_types.tsvector_ptr",
all_types.tsvector AS "all_types.tsvector",
all_types.uuid_ptr AS "all_types.uuid_ptr",
all_types.uuid AS "all_types.uuid",
all_types.xml_ptr AS "all_types.xml_ptr",
all_types.xml AS "all_types.xml",
all_types.json_ptr AS "all_types.json_ptr",
all_types.json AS "all_types.json",
all_types.jsonb_ptr AS "all_types.jsonb_ptr",
all_types.jsonb AS "all_types.jsonb",
all_types.integer_array_ptr AS "all_types.integer_array_ptr",
all_types.integer_array AS "all_types.integer_array",
all_types.text_array_ptr AS "all_types.text_array_ptr",
all_types.text_array AS "all_types.text_array",
all_types.jsonb_array AS "all_types.jsonb_array",
all_types.text_multi_dim_array_ptr AS "all_types.text_multi_dim_array_ptr",
all_types.text_multi_dim_array AS "all_types.text_multi_dim_array"
FROM test_sample.all_types
) AS "allTypesSubQuery"
LIMIT 2;
`)
dest := []model.AllTypes{}
err := mainQuery.Query(db, &dest)
assert.NilError(t, err)
assert.Equal(t, len(dest), 2)
}
func TestExpressionOperators(t *testing.T) {
query := AllTypes.SELECT(
AllTypes.Integer.IS_NULL().AS("result.is_null"),
@ -671,7 +817,20 @@ func TestInterval(t *testing.T) {
INTERVALd(1*time.Hour),
INTERVALd(24*time.Hour),
INTERVALd(24*time.Hour+2*time.Hour+3*time.Minute+4*time.Second+5*time.Microsecond),
)
AllTypes.Interval.EQ(INTERVAL(2, HOUR, 20, MINUTE)).EQ(Bool(true)),
AllTypes.IntervalPtr.NOT_EQ(INTERVAL(2, HOUR, 20, MINUTE)).EQ(Bool(false)),
AllTypes.Interval.IS_DISTINCT_FROM(INTERVAL(2, HOUR, 20, MINUTE)).EQ(AllTypes.Boolean),
AllTypes.IntervalPtr.IS_NOT_DISTINCT_FROM(INTERVALd(10*time.Microsecond)).EQ(AllTypes.Boolean),
AllTypes.Interval.LT(AllTypes.IntervalPtr).EQ(AllTypes.BooleanPtr),
AllTypes.Interval.LT_EQ(AllTypes.IntervalPtr).EQ(AllTypes.BooleanPtr),
AllTypes.Interval.GT(AllTypes.IntervalPtr).EQ(AllTypes.BooleanPtr),
AllTypes.Interval.GT_EQ(AllTypes.IntervalPtr).EQ(AllTypes.BooleanPtr),
AllTypes.Interval.ADD(AllTypes.IntervalPtr).EQ(INTERVALd(17*time.Second)),
AllTypes.Interval.SUB(AllTypes.IntervalPtr).EQ(INTERVAL(100, MICROSECOND)),
AllTypes.IntervalPtr.MUL(Int(11)).EQ(AllTypes.Interval),
AllTypes.IntervalPtr.DIV(Float(22.222)).EQ(AllTypes.IntervalPtr),
).FROM(AllTypes)
//fmt.Println(stmt.DebugSql())

View file

@ -15,7 +15,6 @@ import (
)
func TestGeneratedModel(t *testing.T) {
actor := model.Actor{}
assert.Equal(t, reflect.TypeOf(actor.ActorID).String(), "int32")
@ -275,3 +274,345 @@ func newActorInfoTable() *ActorInfoTable {
}
}
`
func TestGeneratedAllTypesSQLBuilderFiles(t *testing.T) {
enumDir := testRoot + ".gentestdata/jetdb/test_sample/enum/"
modelDir := testRoot + ".gentestdata/jetdb/test_sample/model/"
tableDir := testRoot + ".gentestdata/jetdb/test_sample/table/"
enumFiles, err := ioutil.ReadDir(enumDir)
assert.NilError(t, err)
testutils.AssertFileNamesEqual(t, enumFiles, "mood.go")
testutils.AssertFileContent(t, enumDir+"mood.go", "\npackage enum", moodEnumContent)
modelFiles, err := ioutil.ReadDir(modelDir)
assert.NilError(t, err)
testutils.AssertFileNamesEqual(t, modelFiles, "all_types.go", "all_types_view.go", "employee.go", "link.go",
"mood.go", "person.go", "person_phone.go", "weird_names_table.go")
testutils.AssertFileContent(t, modelDir+"all_types.go", "\npackage model", allTypesModelContent)
tableFiles, err := ioutil.ReadDir(tableDir)
assert.NilError(t, err)
testutils.AssertFileNamesEqual(t, tableFiles, "all_types.go", "employee.go", "link.go",
"person.go", "person_phone.go", "weird_names_table.go")
testutils.AssertFileContent(t, tableDir+"all_types.go", "\npackage table", allTypesTableContent)
}
var moodEnumContent = `
package enum
import "github.com/go-jet/jet/postgres"
var Mood = &struct {
Sad postgres.StringExpression
Ok postgres.StringExpression
Happy postgres.StringExpression
}{
Sad: postgres.NewEnumValue("sad"),
Ok: postgres.NewEnumValue("ok"),
Happy: postgres.NewEnumValue("happy"),
}
`
var allTypesModelContent = `
package model
import (
"github.com/google/uuid"
"time"
)
type AllTypes struct {
SmallIntPtr *int16
SmallInt int16
IntegerPtr *int32
Integer int32
BigIntPtr *int64
BigInt int64
DecimalPtr *float64
Decimal float64
NumericPtr *float64
Numeric float64
RealPtr *float32
Real float32
DoublePrecisionPtr *float64
DoublePrecision float64
Smallserial int16
Serial int32
Bigserial int64
VarCharPtr *string
VarChar string
CharPtr *string
Char string
TextPtr *string
Text string
ByteaPtr *[]byte
Bytea []byte
TimestampzPtr *time.Time
Timestampz time.Time
TimestampPtr *time.Time
Timestamp time.Time
DatePtr *time.Time
Date time.Time
TimezPtr *time.Time
Timez time.Time
TimePtr *time.Time
Time time.Time
IntervalPtr *string
Interval string
BooleanPtr *bool
Boolean bool
PointPtr *string
BitPtr *string
Bit string
BitVaryingPtr *string
BitVarying string
TsvectorPtr *string
Tsvector string
UUIDPtr *uuid.UUID
UUID uuid.UUID
XMLPtr *string
XML string
JSONPtr *string
JSON string
JsonbPtr *string
Jsonb string
IntegerArrayPtr *string
IntegerArray string
TextArrayPtr *string
TextArray string
JsonbArray string
TextMultiDimArrayPtr *string
TextMultiDimArray string
}
`
var allTypesTableContent = `
package table
import (
"github.com/go-jet/jet/postgres"
)
var AllTypes = newAllTypesTable()
type AllTypesTable struct {
postgres.Table
//Columns
SmallIntPtr postgres.ColumnInteger
SmallInt postgres.ColumnInteger
IntegerPtr postgres.ColumnInteger
Integer postgres.ColumnInteger
BigIntPtr postgres.ColumnInteger
BigInt postgres.ColumnInteger
DecimalPtr postgres.ColumnFloat
Decimal postgres.ColumnFloat
NumericPtr postgres.ColumnFloat
Numeric postgres.ColumnFloat
RealPtr postgres.ColumnFloat
Real postgres.ColumnFloat
DoublePrecisionPtr postgres.ColumnFloat
DoublePrecision postgres.ColumnFloat
Smallserial postgres.ColumnInteger
Serial postgres.ColumnInteger
Bigserial postgres.ColumnInteger
VarCharPtr postgres.ColumnString
VarChar postgres.ColumnString
CharPtr postgres.ColumnString
Char postgres.ColumnString
TextPtr postgres.ColumnString
Text postgres.ColumnString
ByteaPtr postgres.ColumnString
Bytea postgres.ColumnString
TimestampzPtr postgres.ColumnTimestampz
Timestampz postgres.ColumnTimestampz
TimestampPtr postgres.ColumnTimestamp
Timestamp postgres.ColumnTimestamp
DatePtr postgres.ColumnDate
Date postgres.ColumnDate
TimezPtr postgres.ColumnTimez
Timez postgres.ColumnTimez
TimePtr postgres.ColumnTime
Time postgres.ColumnTime
IntervalPtr postgres.ColumnInterval
Interval postgres.ColumnInterval
BooleanPtr postgres.ColumnBool
Boolean postgres.ColumnBool
PointPtr postgres.ColumnString
BitPtr postgres.ColumnString
Bit postgres.ColumnString
BitVaryingPtr postgres.ColumnString
BitVarying postgres.ColumnString
TsvectorPtr postgres.ColumnString
Tsvector postgres.ColumnString
UUIDPtr postgres.ColumnString
UUID postgres.ColumnString
XMLPtr postgres.ColumnString
XML postgres.ColumnString
JSONPtr postgres.ColumnString
JSON postgres.ColumnString
JsonbPtr postgres.ColumnString
Jsonb postgres.ColumnString
IntegerArrayPtr postgres.ColumnString
IntegerArray postgres.ColumnString
TextArrayPtr postgres.ColumnString
TextArray postgres.ColumnString
JsonbArray postgres.ColumnString
TextMultiDimArrayPtr postgres.ColumnString
TextMultiDimArray postgres.ColumnString
AllColumns postgres.ColumnList
MutableColumns postgres.ColumnList
}
// creates new AllTypesTable with assigned alias
func (a *AllTypesTable) AS(alias string) *AllTypesTable {
aliasTable := newAllTypesTable()
aliasTable.Table.AS(alias)
return aliasTable
}
func newAllTypesTable() *AllTypesTable {
var (
SmallIntPtrColumn = postgres.IntegerColumn("small_int_ptr")
SmallIntColumn = postgres.IntegerColumn("small_int")
IntegerPtrColumn = postgres.IntegerColumn("integer_ptr")
IntegerColumn = postgres.IntegerColumn("integer")
BigIntPtrColumn = postgres.IntegerColumn("big_int_ptr")
BigIntColumn = postgres.IntegerColumn("big_int")
DecimalPtrColumn = postgres.FloatColumn("decimal_ptr")
DecimalColumn = postgres.FloatColumn("decimal")
NumericPtrColumn = postgres.FloatColumn("numeric_ptr")
NumericColumn = postgres.FloatColumn("numeric")
RealPtrColumn = postgres.FloatColumn("real_ptr")
RealColumn = postgres.FloatColumn("real")
DoublePrecisionPtrColumn = postgres.FloatColumn("double_precision_ptr")
DoublePrecisionColumn = postgres.FloatColumn("double_precision")
SmallserialColumn = postgres.IntegerColumn("smallserial")
SerialColumn = postgres.IntegerColumn("serial")
BigserialColumn = postgres.IntegerColumn("bigserial")
VarCharPtrColumn = postgres.StringColumn("var_char_ptr")
VarCharColumn = postgres.StringColumn("var_char")
CharPtrColumn = postgres.StringColumn("char_ptr")
CharColumn = postgres.StringColumn("char")
TextPtrColumn = postgres.StringColumn("text_ptr")
TextColumn = postgres.StringColumn("text")
ByteaPtrColumn = postgres.StringColumn("bytea_ptr")
ByteaColumn = postgres.StringColumn("bytea")
TimestampzPtrColumn = postgres.TimestampzColumn("timestampz_ptr")
TimestampzColumn = postgres.TimestampzColumn("timestampz")
TimestampPtrColumn = postgres.TimestampColumn("timestamp_ptr")
TimestampColumn = postgres.TimestampColumn("timestamp")
DatePtrColumn = postgres.DateColumn("date_ptr")
DateColumn = postgres.DateColumn("date")
TimezPtrColumn = postgres.TimezColumn("timez_ptr")
TimezColumn = postgres.TimezColumn("timez")
TimePtrColumn = postgres.TimeColumn("time_ptr")
TimeColumn = postgres.TimeColumn("time")
IntervalPtrColumn = postgres.IntervalColumn("interval_ptr")
IntervalColumn = postgres.IntervalColumn("interval")
BooleanPtrColumn = postgres.BoolColumn("boolean_ptr")
BooleanColumn = postgres.BoolColumn("boolean")
PointPtrColumn = postgres.StringColumn("point_ptr")
BitPtrColumn = postgres.StringColumn("bit_ptr")
BitColumn = postgres.StringColumn("bit")
BitVaryingPtrColumn = postgres.StringColumn("bit_varying_ptr")
BitVaryingColumn = postgres.StringColumn("bit_varying")
TsvectorPtrColumn = postgres.StringColumn("tsvector_ptr")
TsvectorColumn = postgres.StringColumn("tsvector")
UUIDPtrColumn = postgres.StringColumn("uuid_ptr")
UUIDColumn = postgres.StringColumn("uuid")
XMLPtrColumn = postgres.StringColumn("xml_ptr")
XMLColumn = postgres.StringColumn("xml")
JSONPtrColumn = postgres.StringColumn("json_ptr")
JSONColumn = postgres.StringColumn("json")
JsonbPtrColumn = postgres.StringColumn("jsonb_ptr")
JsonbColumn = postgres.StringColumn("jsonb")
IntegerArrayPtrColumn = postgres.StringColumn("integer_array_ptr")
IntegerArrayColumn = postgres.StringColumn("integer_array")
TextArrayPtrColumn = postgres.StringColumn("text_array_ptr")
TextArrayColumn = postgres.StringColumn("text_array")
JsonbArrayColumn = postgres.StringColumn("jsonb_array")
TextMultiDimArrayPtrColumn = postgres.StringColumn("text_multi_dim_array_ptr")
TextMultiDimArrayColumn = postgres.StringColumn("text_multi_dim_array")
)
return &AllTypesTable{
Table: postgres.NewTable("test_sample", "all_types", SmallIntPtrColumn, SmallIntColumn, IntegerPtrColumn, IntegerColumn, BigIntPtrColumn, BigIntColumn, DecimalPtrColumn, DecimalColumn, NumericPtrColumn, NumericColumn, RealPtrColumn, RealColumn, DoublePrecisionPtrColumn, DoublePrecisionColumn, SmallserialColumn, SerialColumn, BigserialColumn, VarCharPtrColumn, VarCharColumn, CharPtrColumn, CharColumn, TextPtrColumn, TextColumn, ByteaPtrColumn, ByteaColumn, TimestampzPtrColumn, TimestampzColumn, TimestampPtrColumn, TimestampColumn, DatePtrColumn, DateColumn, TimezPtrColumn, TimezColumn, TimePtrColumn, TimeColumn, IntervalPtrColumn, IntervalColumn, BooleanPtrColumn, BooleanColumn, PointPtrColumn, BitPtrColumn, BitColumn, BitVaryingPtrColumn, BitVaryingColumn, TsvectorPtrColumn, TsvectorColumn, UUIDPtrColumn, UUIDColumn, XMLPtrColumn, XMLColumn, JSONPtrColumn, JSONColumn, JsonbPtrColumn, JsonbColumn, IntegerArrayPtrColumn, IntegerArrayColumn, TextArrayPtrColumn, TextArrayColumn, JsonbArrayColumn, TextMultiDimArrayPtrColumn, TextMultiDimArrayColumn),
//Columns
SmallIntPtr: SmallIntPtrColumn,
SmallInt: SmallIntColumn,
IntegerPtr: IntegerPtrColumn,
Integer: IntegerColumn,
BigIntPtr: BigIntPtrColumn,
BigInt: BigIntColumn,
DecimalPtr: DecimalPtrColumn,
Decimal: DecimalColumn,
NumericPtr: NumericPtrColumn,
Numeric: NumericColumn,
RealPtr: RealPtrColumn,
Real: RealColumn,
DoublePrecisionPtr: DoublePrecisionPtrColumn,
DoublePrecision: DoublePrecisionColumn,
Smallserial: SmallserialColumn,
Serial: SerialColumn,
Bigserial: BigserialColumn,
VarCharPtr: VarCharPtrColumn,
VarChar: VarCharColumn,
CharPtr: CharPtrColumn,
Char: CharColumn,
TextPtr: TextPtrColumn,
Text: TextColumn,
ByteaPtr: ByteaPtrColumn,
Bytea: ByteaColumn,
TimestampzPtr: TimestampzPtrColumn,
Timestampz: TimestampzColumn,
TimestampPtr: TimestampPtrColumn,
Timestamp: TimestampColumn,
DatePtr: DatePtrColumn,
Date: DateColumn,
TimezPtr: TimezPtrColumn,
Timez: TimezColumn,
TimePtr: TimePtrColumn,
Time: TimeColumn,
IntervalPtr: IntervalPtrColumn,
Interval: IntervalColumn,
BooleanPtr: BooleanPtrColumn,
Boolean: BooleanColumn,
PointPtr: PointPtrColumn,
BitPtr: BitPtrColumn,
Bit: BitColumn,
BitVaryingPtr: BitVaryingPtrColumn,
BitVarying: BitVaryingColumn,
TsvectorPtr: TsvectorPtrColumn,
Tsvector: TsvectorColumn,
UUIDPtr: UUIDPtrColumn,
UUID: UUIDColumn,
XMLPtr: XMLPtrColumn,
XML: XMLColumn,
JSONPtr: JSONPtrColumn,
JSON: JSONColumn,
JsonbPtr: JsonbPtrColumn,
Jsonb: JsonbColumn,
IntegerArrayPtr: IntegerArrayPtrColumn,
IntegerArray: IntegerArrayColumn,
TextArrayPtr: TextArrayPtrColumn,
TextArray: TextArrayColumn,
JsonbArray: JsonbArrayColumn,
TextMultiDimArrayPtr: TextMultiDimArrayPtrColumn,
TextMultiDimArray: TextMultiDimArrayColumn,
AllColumns: postgres.ColumnList{SmallIntPtrColumn, SmallIntColumn, IntegerPtrColumn, IntegerColumn, BigIntPtrColumn, BigIntColumn, DecimalPtrColumn, DecimalColumn, NumericPtrColumn, NumericColumn, RealPtrColumn, RealColumn, DoublePrecisionPtrColumn, DoublePrecisionColumn, SmallserialColumn, SerialColumn, BigserialColumn, VarCharPtrColumn, VarCharColumn, CharPtrColumn, CharColumn, TextPtrColumn, TextColumn, ByteaPtrColumn, ByteaColumn, TimestampzPtrColumn, TimestampzColumn, TimestampPtrColumn, TimestampColumn, DatePtrColumn, DateColumn, TimezPtrColumn, TimezColumn, TimePtrColumn, TimeColumn, IntervalPtrColumn, IntervalColumn, BooleanPtrColumn, BooleanColumn, PointPtrColumn, BitPtrColumn, BitColumn, BitVaryingPtrColumn, BitVaryingColumn, TsvectorPtrColumn, TsvectorColumn, UUIDPtrColumn, UUIDColumn, XMLPtrColumn, XMLColumn, JSONPtrColumn, JSONColumn, JsonbPtrColumn, JsonbColumn, IntegerArrayPtrColumn, IntegerArrayColumn, TextArrayPtrColumn, TextArrayColumn, JsonbArrayColumn, TextMultiDimArrayPtrColumn, TextMultiDimArrayColumn},
MutableColumns: postgres.ColumnList{SmallIntPtrColumn, SmallIntColumn, IntegerPtrColumn, IntegerColumn, BigIntPtrColumn, BigIntColumn, DecimalPtrColumn, DecimalColumn, NumericPtrColumn, NumericColumn, RealPtrColumn, RealColumn, DoublePrecisionPtrColumn, DoublePrecisionColumn, SmallserialColumn, SerialColumn, BigserialColumn, VarCharPtrColumn, VarCharColumn, CharPtrColumn, CharColumn, TextPtrColumn, TextColumn, ByteaPtrColumn, ByteaColumn, TimestampzPtrColumn, TimestampzColumn, TimestampPtrColumn, TimestampColumn, DatePtrColumn, DateColumn, TimezPtrColumn, TimezColumn, TimePtrColumn, TimeColumn, IntervalPtrColumn, IntervalColumn, BooleanPtrColumn, BooleanColumn, PointPtrColumn, BitPtrColumn, BitColumn, BitVaryingPtrColumn, BitVaryingColumn, TsvectorPtrColumn, TsvectorColumn, UUIDPtrColumn, UUIDColumn, XMLPtrColumn, XMLColumn, JSONPtrColumn, JSONColumn, JsonbPtrColumn, JsonbColumn, IntegerArrayPtrColumn, IntegerArrayColumn, TextArrayPtrColumn, TextArrayColumn, JsonbArrayColumn, TextMultiDimArrayPtrColumn, TextMultiDimArrayColumn},
}
}
`

View file

@ -6,14 +6,19 @@ import (
_ "github.com/lib/pq"
"github.com/pkg/profile"
"os"
"os/exec"
"strings"
"testing"
)
var db *sql.DB
var testRoot string
func TestMain(m *testing.M) {
defer profile.Start().Stop()
setTestRoot()
var err error
db, err = sql.Open("postgres", dbconfig.PostgresConnectString)
if err != nil {
@ -25,3 +30,13 @@ func TestMain(m *testing.M) {
os.Exit(ret)
}
func setTestRoot() {
cmd := exec.Command("git", "rev-parse", "--show-toplevel")
byteArr, err := cmd.Output()
if err != nil {
panic(err)
}
testRoot = strings.TrimSpace(string(byteArr)) + "/tests/"
}