Postgres interval with date/time expression arithmetic.

This commit is contained in:
go-jet 2019-12-01 18:26:01 +01:00
parent d1970b3a55
commit 4a3579e7f9
10 changed files with 313 additions and 76 deletions

View file

@ -5,60 +5,60 @@ import (
)
func TestExpressionCAST_AS(t *testing.T) {
assertClauseSerialize(t, CAST(String("test")).AS("text"), `$1::text`, "test")
assertSerialize(t, CAST(String("test")).AS("text"), `$1::text`, "test")
}
func TestExpressionCAST_AS_BOOL(t *testing.T) {
assertClauseSerialize(t, CAST(Int(1)).AS_BOOL(), "$1::boolean", int64(1))
assertClauseSerialize(t, CAST(table2Col3).AS_BOOL(), "table2.col3::boolean")
assertClauseSerialize(t, CAST(table2Col3.ADD(table2Col3)).AS_BOOL(), "(table2.col3 + table2.col3)::boolean")
assertSerialize(t, CAST(Int(1)).AS_BOOL(), "$1::boolean", int64(1))
assertSerialize(t, CAST(table2Col3).AS_BOOL(), "table2.col3::boolean")
assertSerialize(t, CAST(table2Col3.ADD(table2Col3)).AS_BOOL(), "(table2.col3 + table2.col3)::boolean")
}
func TestExpressionCAST_AS_SMALLINT(t *testing.T) {
assertClauseSerialize(t, CAST(table2Col3).AS_SMALLINT(), "table2.col3::smallint")
assertSerialize(t, CAST(table2Col3).AS_SMALLINT(), "table2.col3::smallint")
}
func TestExpressionCAST_AS_INTEGER(t *testing.T) {
assertClauseSerialize(t, CAST(table2Col3).AS_INTEGER(), "table2.col3::integer")
assertSerialize(t, CAST(table2Col3).AS_INTEGER(), "table2.col3::integer")
}
func TestExpressionCAST_AS_BIGINT(t *testing.T) {
assertClauseSerialize(t, CAST(table2Col3).AS_BIGINT(), "table2.col3::bigint")
assertSerialize(t, CAST(table2Col3).AS_BIGINT(), "table2.col3::bigint")
}
func TestExpressionCAST_AS_NUMERIC(t *testing.T) {
assertClauseSerialize(t, CAST(table2Col3).AS_NUMERIC(11, 11), "table2.col3::numeric(11, 11)")
assertClauseSerialize(t, CAST(table2Col3).AS_NUMERIC(11), "table2.col3::numeric(11)")
assertSerialize(t, CAST(table2Col3).AS_NUMERIC(11, 11), "table2.col3::numeric(11, 11)")
assertSerialize(t, CAST(table2Col3).AS_NUMERIC(11), "table2.col3::numeric(11)")
}
func TestExpressionCAST_AS_REAL(t *testing.T) {
assertClauseSerialize(t, CAST(table2Col3).AS_REAL(), "table2.col3::real")
assertSerialize(t, CAST(table2Col3).AS_REAL(), "table2.col3::real")
}
func TestExpressionCAST_AS_DOUBLE(t *testing.T) {
assertClauseSerialize(t, CAST(table2Col3).AS_DOUBLE(), "table2.col3::double precision")
assertSerialize(t, CAST(table2Col3).AS_DOUBLE(), "table2.col3::double precision")
}
func TestExpressionCAST_AS_TEXT(t *testing.T) {
assertClauseSerialize(t, CAST(table2Col3).AS_TEXT(), "table2.col3::text")
assertSerialize(t, CAST(table2Col3).AS_TEXT(), "table2.col3::text")
}
func TestExpressionCAST_AS_DATE(t *testing.T) {
assertClauseSerialize(t, CAST(table2Col3).AS_DATE(), "table2.col3::date")
assertSerialize(t, CAST(table2Col3).AS_DATE(), "table2.col3::date")
}
func TestExpressionCAST_AS_TIME(t *testing.T) {
assertClauseSerialize(t, CAST(table2Col3).AS_TIME(), "table2.col3::time without time zone")
assertSerialize(t, CAST(table2Col3).AS_TIME(), "table2.col3::time without time zone")
}
func TestExpressionCAST_AS_TIMEZ(t *testing.T) {
assertClauseSerialize(t, CAST(table2Col3).AS_TIMEZ(), "table2.col3::time with time zone")
assertSerialize(t, CAST(table2Col3).AS_TIMEZ(), "table2.col3::time with time zone")
}
func TestExpressionCAST_AS_TIMESTAMP(t *testing.T) {
assertClauseSerialize(t, CAST(table2Col3).AS_TIMESTAMP(), "table2.col3::timestamp without time zone")
assertSerialize(t, CAST(table2Col3).AS_TIMESTAMP(), "table2.col3::timestamp without time zone")
}
func TestExpressionCAST_AS_TIMESTAMPZ(t *testing.T) {
assertClauseSerialize(t, CAST(table2Col3).AS_TIMESTAMPZ(), "table2.col3::timestamp with time zone")
assertSerialize(t, CAST(table2Col3).AS_TIMESTAMPZ(), "table2.col3::timestamp with time zone")
}

View file

@ -29,7 +29,7 @@ func newDialect() jet.Dialect {
return jet.NewDialect(dialectParams)
}
func postgresCAST(expressions ...jet.Expression) jet.SerializeFunc {
func postgresCAST(expressions ...jet.Serializer) jet.SerializerFunc {
return func(statement jet.StatementType, out *jet.SQLBuilder, options ...jet.SerializeOption) {
if len(expressions) < 2 {
panic("jet: invalid number of expressions for operator")
@ -54,7 +54,7 @@ func postgresCAST(expressions ...jet.Expression) jet.SerializeFunc {
}
}
func postgresREGEXPLIKEoperator(expressions ...jet.Expression) jet.SerializeFunc {
func postgresREGEXPLIKEoperator(expressions ...jet.Serializer) jet.SerializerFunc {
return func(statement jet.StatementType, out *jet.SQLBuilder, options ...jet.SerializeOption) {
if len(expressions) < 2 {
panic("jet: invalid number of expressions for operator")
@ -80,7 +80,7 @@ func postgresREGEXPLIKEoperator(expressions ...jet.Expression) jet.SerializeFunc
}
}
func postgresNOTREGEXPLIKEoperator(expressions ...jet.Expression) jet.SerializeFunc {
func postgresNOTREGEXPLIKEoperator(expressions ...jet.Serializer) jet.SerializerFunc {
return func(statement jet.StatementType, out *jet.SQLBuilder, options ...jet.SerializeOption) {
if len(expressions) < 2 {
panic("jet: invalid number of expressions for operator")

View file

@ -3,21 +3,21 @@ package postgres
import "testing"
func TestString_REGEXP_LIKE_operator(t *testing.T) {
assertClauseSerialize(t, table3StrCol.REGEXP_LIKE(table2ColStr), "(table3.col2 ~* table2.col_str)")
assertClauseSerialize(t, table3StrCol.REGEXP_LIKE(String("JOHN")), "(table3.col2 ~* $1)", "JOHN")
assertClauseSerialize(t, table3StrCol.REGEXP_LIKE(String("JOHN"), false), "(table3.col2 ~* $1)", "JOHN")
assertClauseSerialize(t, table3StrCol.REGEXP_LIKE(String("JOHN"), true), "(table3.col2 ~ $1)", "JOHN")
assertSerialize(t, table3StrCol.REGEXP_LIKE(table2ColStr), "(table3.col2 ~* table2.col_str)")
assertSerialize(t, table3StrCol.REGEXP_LIKE(String("JOHN")), "(table3.col2 ~* $1)", "JOHN")
assertSerialize(t, table3StrCol.REGEXP_LIKE(String("JOHN"), false), "(table3.col2 ~* $1)", "JOHN")
assertSerialize(t, table3StrCol.REGEXP_LIKE(String("JOHN"), true), "(table3.col2 ~ $1)", "JOHN")
}
func TestString_NOT_REGEXP_LIKE_operator(t *testing.T) {
assertClauseSerialize(t, table3StrCol.NOT_REGEXP_LIKE(table2ColStr), "(table3.col2 !~* table2.col_str)")
assertClauseSerialize(t, table3StrCol.NOT_REGEXP_LIKE(String("JOHN")), "(table3.col2 !~* $1)", "JOHN")
assertClauseSerialize(t, table3StrCol.NOT_REGEXP_LIKE(String("JOHN"), false), "(table3.col2 !~* $1)", "JOHN")
assertClauseSerialize(t, table3StrCol.NOT_REGEXP_LIKE(String("JOHN"), true), "(table3.col2 !~ $1)", "JOHN")
assertSerialize(t, table3StrCol.NOT_REGEXP_LIKE(table2ColStr), "(table3.col2 !~* table2.col_str)")
assertSerialize(t, table3StrCol.NOT_REGEXP_LIKE(String("JOHN")), "(table3.col2 !~* $1)", "JOHN")
assertSerialize(t, table3StrCol.NOT_REGEXP_LIKE(String("JOHN"), false), "(table3.col2 !~* $1)", "JOHN")
assertSerialize(t, table3StrCol.NOT_REGEXP_LIKE(String("JOHN"), true), "(table3.col2 !~ $1)", "JOHN")
}
func TestExists(t *testing.T) {
assertClauseSerialize(t, EXISTS(
assertSerialize(t, EXISTS(
table2.
SELECT(Int(1)).
WHERE(table1Col1.EQ(table2Col3)),
@ -31,13 +31,13 @@ func TestExists(t *testing.T) {
func TestIN(t *testing.T) {
assertClauseSerialize(t, Float(1.11).IN(table1.SELECT(table1Col1)),
assertSerialize(t, Float(1.11).IN(table1.SELECT(table1Col1)),
`($1 IN ((
SELECT table1.col1 AS "table1.col1"
FROM db.table1
)))`, float64(1.11))
assertClauseSerialize(t, ROW(Int(12), table1Col1).IN(table2.SELECT(table2Col3, table3Col1)),
assertSerialize(t, ROW(Int(12), table1Col1).IN(table2.SELECT(table2Col3, table3Col1)),
`(ROW($1, table1.col1) IN ((
SELECT table2.col3 AS "table2.col3",
table3.col1 AS "table3.col1"
@ -47,13 +47,13 @@ func TestIN(t *testing.T) {
func TestNOT_IN(t *testing.T) {
assertClauseSerialize(t, Float(1.11).NOT_IN(table1.SELECT(table1Col1)),
assertSerialize(t, Float(1.11).NOT_IN(table1.SELECT(table1Col1)),
`($1 NOT IN ((
SELECT table1.col1 AS "table1.col1"
FROM db.table1
)))`, float64(1.11))
assertClauseSerialize(t, ROW(Int(12), table1Col1).NOT_IN(table2.SELECT(table2Col3, table3Col1)),
assertSerialize(t, ROW(Int(12), table1Col1).NOT_IN(table2.SELECT(table2Col3, table3Col1)),
`(ROW($1, table1.col1) NOT IN ((
SELECT table2.col3 AS "table2.col3",
table3.col1 AS "table3.col1"

131
postgres/interval.go Normal file
View file

@ -0,0 +1,131 @@
package postgres
import (
"fmt"
"github.com/go-jet/jet/internal/jet"
"github.com/go-jet/jet/internal/utils"
"strconv"
"strings"
"time"
)
type quantityAndUnit float64
const (
pow2_32 = -4.294967296e+09
YEAR quantityAndUnit = pow2_32 + iota
MONTH
WEEK
DAY
HOUR
MINUTE
SECOND
MILLISECOND
MICROSECOND
DECADE
CENTURY
MILLENNIUM
)
type intervalExpressionImpl struct {
jet.Interval
jet.ExpressionInterfaceImpl
}
type IntervalExpression interface {
jet.IsInterval
jet.Expression
}
func INTERVAL(quantityAndUnit ...quantityAndUnit) IntervalExpression {
if len(quantityAndUnit)%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)
unitString := unitToString(quantityAndUnit[i+1])
fields = append(fields, quantity+" "+unitString)
}
intervalStr := fmt.Sprintf("'%s'", strings.Join(fields, " "))
newInterval := &intervalExpressionImpl{
Interval: jet.NewInterval(jet.Raw(intervalStr)),
}
newInterval.ExpressionInterfaceImpl.Parent = newInterval
return newInterval
}
func INTERVALd(duration time.Duration) IntervalExpression {
days, hours, minutes, seconds, microseconds := utils.ExtractDateTimeComponents(duration)
quantityAndUnits := []quantityAndUnit{}
if days > 0 {
quantityAndUnits = append(quantityAndUnits, quantityAndUnit(days))
quantityAndUnits = append(quantityAndUnits, DAY)
}
if hours > 0 {
quantityAndUnits = append(quantityAndUnits, quantityAndUnit(hours))
quantityAndUnits = append(quantityAndUnits, HOUR)
}
if minutes > 0 {
quantityAndUnits = append(quantityAndUnits, quantityAndUnit(minutes))
quantityAndUnits = append(quantityAndUnits, MINUTE)
}
if seconds > 0 {
quantityAndUnits = append(quantityAndUnits, quantityAndUnit(seconds))
quantityAndUnits = append(quantityAndUnits, SECOND)
}
if microseconds > 0 {
quantityAndUnits = append(quantityAndUnits, quantityAndUnit(microseconds))
quantityAndUnits = append(quantityAndUnits, MICROSECOND)
}
if len(quantityAndUnits) == 0 {
return INTERVAL(0, MICROSECOND)
}
return INTERVAL(quantityAndUnits...)
}
func unitToString(unit quantityAndUnit) string {
switch unit {
case YEAR:
return "YEAR"
case MONTH:
return "MONTH"
case WEEK:
return "WEEK"
case DAY:
return "DAY"
case HOUR:
return "HOUR"
case MINUTE:
return "MINUTE"
case SECOND:
return "SECOND"
case MILLISECOND:
return "MILLISECOND"
case MICROSECOND:
return "MICROSECOND"
case DECADE:
return "DECADE"
case CENTURY:
return "CENTURY"
case MILLENNIUM:
return "MILLENNIUM"
default:
panic("jet: invalid INTERVAL unit type")
}
}

59
postgres/interval_test.go Normal file
View file

@ -0,0 +1,59 @@
package postgres
import (
"testing"
"time"
)
func TestINTERVAL(t *testing.T) {
assertSerialize(t, INTERVAL(1, YEAR), "INTERVAL '1 YEAR'")
assertSerialize(t, INTERVAL(1, MONTH), "INTERVAL '1 MONTH'")
assertSerialize(t, INTERVAL(1, WEEK), "INTERVAL '1 WEEK'")
assertSerialize(t, INTERVAL(1, DAY), "INTERVAL '1 DAY'")
assertSerialize(t, INTERVAL(1, HOUR), "INTERVAL '1 HOUR'")
assertSerialize(t, INTERVAL(1, MINUTE), "INTERVAL '1 MINUTE'")
assertSerialize(t, INTERVAL(1, SECOND), "INTERVAL '1 SECOND'")
assertSerialize(t, INTERVAL(1, MILLISECOND), "INTERVAL '1 MILLISECOND'")
assertSerialize(t, INTERVAL(1, MICROSECOND), "INTERVAL '1 MICROSECOND'")
assertSerialize(t, INTERVAL(1, DECADE), "INTERVAL '1 DECADE'")
assertSerialize(t, INTERVAL(1, CENTURY), "INTERVAL '1 CENTURY'")
assertSerialize(t, INTERVAL(1, MILLENNIUM), "INTERVAL '1 MILLENNIUM'")
assertSerialize(t, INTERVAL(1, YEAR, 10, MONTH), "INTERVAL '1 YEAR 10 MONTH'")
assertSerialize(t, INTERVAL(1, YEAR, 10, MONTH, 20, DAY), "INTERVAL '1 YEAR 10 MONTH 20 DAY'")
assertSerialize(t, INTERVAL(1, YEAR, 10, MONTH, 20, DAY, 3, HOUR), "INTERVAL '1 YEAR 10 MONTH 20 DAY 3 HOUR'")
assertSerialize(t, INTERVAL(1, YEAR).IS_NOT_NULL(), "INTERVAL '1 YEAR' IS NOT NULL")
assertProjectionSerialize(t, INTERVAL(1, YEAR).AS("one year"), `INTERVAL '1 YEAR' AS "one year"`)
}
func TestINTERVALd(t *testing.T) {
assertSerialize(t, INTERVALd(0), "INTERVAL '0 MICROSECOND'")
assertSerialize(t, INTERVALd(1*time.Microsecond), "INTERVAL '1 MICROSECOND'")
assertSerialize(t, INTERVALd(1*time.Millisecond), "INTERVAL '1000 MICROSECOND'")
assertSerialize(t, INTERVALd(1*time.Second), "INTERVAL '1 SECOND'")
assertSerialize(t, INTERVALd(1*time.Minute), "INTERVAL '1 MINUTE'")
assertSerialize(t, INTERVALd(1*time.Hour), "INTERVAL '1 HOUR'")
assertSerialize(t, INTERVALd(24*time.Hour), "INTERVAL '1 DAY'")
assertSerialize(t, INTERVALd(24*time.Hour+2*time.Hour+3*time.Minute+4*time.Second+5*time.Microsecond),
"INTERVAL '1 DAY 2 HOUR 3 MINUTE 4 SECOND 5 MICROSECOND'")
}
func TestINTERVAL_InvalidParams(t *testing.T) {
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) {
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')")
assertSerialize(t, table2ColTime.SUB(INTERVAL(1, HOUR)), "(table2.col_time - INTERVAL '1 HOUR')")
assertSerialize(t, table2ColTimez.ADD(INTERVAL(1, HOUR)), "(table2.col_timez + INTERVAL '1 HOUR')")
assertSerialize(t, table2ColTimez.SUB(INTERVAL(1, HOUR)), "(table2.col_timez - INTERVAL '1 HOUR')")
assertSerialize(t, table2ColTimestamp.ADD(INTERVAL(1, HOUR)), "(table2.col_timestamp + INTERVAL '1 HOUR')")
assertSerialize(t, table2ColTimestamp.SUB(INTERVAL(1, HOUR)), "(table2.col_timestamp - INTERVAL '1 HOUR')")
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')")
}

View file

@ -6,45 +6,45 @@ import (
)
func TestBool(t *testing.T) {
assertClauseSerialize(t, Bool(false), `$1`, false)
assertSerialize(t, Bool(false), `$1`, false)
}
func TestInt(t *testing.T) {
assertClauseSerialize(t, Int(11), `$1`, int64(11))
assertSerialize(t, Int(11), `$1`, int64(11))
}
func TestFloat(t *testing.T) {
assertClauseSerialize(t, Float(12.34), `$1`, float64(12.34))
assertSerialize(t, Float(12.34), `$1`, float64(12.34))
}
func TestString(t *testing.T) {
assertClauseSerialize(t, String("Some text"), `$1`, "Some text")
assertSerialize(t, String("Some text"), `$1`, "Some text")
}
func TestDate(t *testing.T) {
assertClauseSerialize(t, Date(2014, time.January, 2), `$1::date`, "2014-01-02")
assertClauseSerialize(t, DateT(time.Now()), `$1::date`)
assertSerialize(t, Date(2014, time.January, 2), `$1::date`, "2014-01-02")
assertSerialize(t, DateT(time.Now()), `$1::date`)
}
func TestTime(t *testing.T) {
assertClauseSerialize(t, Time(10, 15, 30), `$1::time without time zone`, "10:15:30")
assertClauseSerialize(t, TimeT(time.Now()), `$1::time without time zone`)
assertSerialize(t, Time(10, 15, 30), `$1::time without time zone`, "10:15:30")
assertSerialize(t, TimeT(time.Now()), `$1::time without time zone`)
}
func TestTimez(t *testing.T) {
assertClauseSerialize(t, Timez(10, 15, 30, 0, "UTC"),
assertSerialize(t, Timez(10, 15, 30, 0, "UTC"),
`$1::time with time zone`, "10:15:30 UTC")
assertClauseSerialize(t, TimezT(time.Now()), `$1::time with time zone`)
assertSerialize(t, TimezT(time.Now()), `$1::time with time zone`)
}
func TestTimestamp(t *testing.T) {
assertClauseSerialize(t, Timestamp(2010, time.March, 30, 10, 15, 30),
assertSerialize(t, Timestamp(2010, time.March, 30, 10, 15, 30),
`$1::timestamp without time zone`, "2010-03-30 10:15:30")
assertClauseSerialize(t, TimestampT(time.Now()), `$1::timestamp without time zone`)
assertSerialize(t, TimestampT(time.Now()), `$1::timestamp without time zone`)
}
func TestTimestampz(t *testing.T) {
assertClauseSerialize(t, Timestampz(2010, time.March, 30, 10, 15, 30, 0, "UTC"),
assertSerialize(t, Timestampz(2010, time.March, 30, 10, 15, 30, 0, "UTC"),
`$1::timestamp with time zone`, "2010-03-30 10:15:30 UTC")
assertClauseSerialize(t, TimestampzT(time.Now()), `$1::timestamp with time zone`)
assertSerialize(t, TimestampzT(time.Now()), `$1::timestamp with time zone`)
}

View file

@ -12,17 +12,17 @@ func TestJoinNilInputs(t *testing.T) {
}
func TestINNER_JOIN(t *testing.T) {
assertClauseSerialize(t, table1.
assertSerialize(t, table1.
INNER_JOIN(table2, table1ColInt.EQ(table2ColInt)),
`db.table1
INNER JOIN db.table2 ON (table1.col_int = table2.col_int)`)
assertClauseSerialize(t, table1.
assertSerialize(t, table1.
INNER_JOIN(table2, table1ColInt.EQ(table2ColInt)).
INNER_JOIN(table3, table1ColInt.EQ(table3ColInt)),
`db.table1
INNER JOIN db.table2 ON (table1.col_int = table2.col_int)
INNER JOIN db.table3 ON (table1.col_int = table3.col_int)`)
assertClauseSerialize(t, table1.
assertSerialize(t, table1.
INNER_JOIN(table2, table1ColInt.EQ(Int(1))).
INNER_JOIN(table3, table1ColInt.EQ(Int(2))),
`db.table1
@ -31,17 +31,17 @@ INNER JOIN db.table3 ON (table1.col_int = $2)`, int64(1), int64(2))
}
func TestLEFT_JOIN(t *testing.T) {
assertClauseSerialize(t, table1.
assertSerialize(t, table1.
LEFT_JOIN(table2, table1ColInt.EQ(table2ColInt)),
`db.table1
LEFT JOIN db.table2 ON (table1.col_int = table2.col_int)`)
assertClauseSerialize(t, table1.
assertSerialize(t, table1.
LEFT_JOIN(table2, table1ColInt.EQ(table2ColInt)).
LEFT_JOIN(table3, table1ColInt.EQ(table3ColInt)),
`db.table1
LEFT JOIN db.table2 ON (table1.col_int = table2.col_int)
LEFT JOIN db.table3 ON (table1.col_int = table3.col_int)`)
assertClauseSerialize(t, table1.
assertSerialize(t, table1.
LEFT_JOIN(table2, table1ColInt.EQ(Int(1))).
LEFT_JOIN(table3, table1ColInt.EQ(Int(2))),
`db.table1
@ -50,17 +50,17 @@ LEFT JOIN db.table3 ON (table1.col_int = $2)`, int64(1), int64(2))
}
func TestRIGHT_JOIN(t *testing.T) {
assertClauseSerialize(t, table1.
assertSerialize(t, table1.
RIGHT_JOIN(table2, table1ColInt.EQ(table2ColInt)),
`db.table1
RIGHT JOIN db.table2 ON (table1.col_int = table2.col_int)`)
assertClauseSerialize(t, table1.
assertSerialize(t, table1.
RIGHT_JOIN(table2, table1ColInt.EQ(table2ColInt)).
RIGHT_JOIN(table3, table1ColInt.EQ(table3ColInt)),
`db.table1
RIGHT JOIN db.table2 ON (table1.col_int = table2.col_int)
RIGHT JOIN db.table3 ON (table1.col_int = table3.col_int)`)
assertClauseSerialize(t, table1.
assertSerialize(t, table1.
RIGHT_JOIN(table2, table1ColInt.EQ(Int(1))).
RIGHT_JOIN(table3, table1ColInt.EQ(Int(2))),
`db.table1
@ -69,17 +69,17 @@ RIGHT JOIN db.table3 ON (table1.col_int = $2)`, int64(1), int64(2))
}
func TestFULL_JOIN(t *testing.T) {
assertClauseSerialize(t, table1.
assertSerialize(t, table1.
FULL_JOIN(table2, table1ColInt.EQ(table2ColInt)),
`db.table1
FULL JOIN db.table2 ON (table1.col_int = table2.col_int)`)
assertClauseSerialize(t, table1.
assertSerialize(t, table1.
FULL_JOIN(table2, table1ColInt.EQ(table2ColInt)).
FULL_JOIN(table3, table1ColInt.EQ(table3ColInt)),
`db.table1
FULL JOIN db.table2 ON (table1.col_int = table2.col_int)
FULL JOIN db.table3 ON (table1.col_int = table3.col_int)`)
assertClauseSerialize(t, table1.
assertSerialize(t, table1.
FULL_JOIN(table2, table1ColInt.EQ(Int(1))).
FULL_JOIN(table3, table1ColInt.EQ(Int(2))),
`db.table1
@ -88,11 +88,11 @@ FULL JOIN db.table3 ON (table1.col_int = $2)`, int64(1), int64(2))
}
func TestCROSS_JOIN(t *testing.T) {
assertClauseSerialize(t, table1.
assertSerialize(t, table1.
CROSS_JOIN(table2),
`db.table1
CROSS JOIN db.table2`)
assertClauseSerialize(t, table1.
assertSerialize(t, table1.
CROSS_JOIN(table2).
CROSS_JOIN(table3),
`db.table1

View file

@ -1,9 +1,10 @@
package postgres
import (
"testing"
"github.com/go-jet/jet/internal/jet"
"github.com/go-jet/jet/internal/testutils"
"testing"
)
var table1Col1 = IntegerColumn("col1")
@ -70,7 +71,7 @@ var table3 = NewTable(
table3ColInt,
table3StrCol)
func assertClauseSerialize(t *testing.T, clause jet.Serializer, query string, args ...interface{}) {
func assertSerialize(t *testing.T, clause jet.Serializer, query string, args ...interface{}) {
testutils.AssertClauseSerialize(t, Dialect, clause, query, args...)
}
@ -84,3 +85,4 @@ func assertProjectionSerialize(t *testing.T, projection jet.Projection, query st
var assertStatementSql = testutils.AssertStatementSql
var assertStatementSqlErr = testutils.AssertStatementSqlErr
var assertPanicErr = testutils.AssertPanicErr

View file

@ -1,6 +1,12 @@
package postgres
import (
"testing"
"time"
"github.com/google/uuid"
"gotest.tools/assert"
"github.com/go-jet/jet/internal/testutils"
"github.com/go-jet/jet/postgres"
. "github.com/go-jet/jet/postgres"
@ -8,10 +14,6 @@ import (
. "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/table"
"github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/view"
"github.com/go-jet/jet/tests/testdata/results/common"
"github.com/google/uuid"
"gotest.tools/assert"
"testing"
"time"
)
func TestAllTypesSelect(t *testing.T) {
@ -606,6 +608,17 @@ func TestTimeExpression(t *testing.T) {
AllTypes.Time.GT_EQ(AllTypes.Time),
AllTypes.Time.GT_EQ(Time(23, 6, 6, 1)),
AllTypes.Date.ADD(INTERVAL(1, HOUR)),
AllTypes.Date.SUB(INTERVAL(1, MINUTE)),
AllTypes.Time.ADD(INTERVAL(1, HOUR)),
AllTypes.Time.SUB(INTERVAL(1, MINUTE)),
AllTypes.Timez.ADD(INTERVAL(1, HOUR)),
AllTypes.Timez.SUB(INTERVAL(1, MINUTE)),
AllTypes.Timestamp.ADD(INTERVAL(1, HOUR)),
AllTypes.Timestamp.SUB(INTERVAL(1, MINUTE)),
AllTypes.Timestampz.ADD(INTERVAL(1, HOUR)),
AllTypes.Timestampz.SUB(INTERVAL(1, MINUTE)),
CURRENT_DATE(),
CURRENT_TIME(),
CURRENT_TIME(2),
@ -626,6 +639,44 @@ func TestTimeExpression(t *testing.T) {
assert.NilError(t, err)
}
func TestInterval(t *testing.T) {
stmt := SELECT(
INTERVAL(1, YEAR),
INTERVAL(1, MONTH),
INTERVAL(1, WEEK),
INTERVAL(1, DAY),
INTERVAL(1, HOUR),
INTERVAL(1, MINUTE),
INTERVAL(1, SECOND),
INTERVAL(1, MILLISECOND),
INTERVAL(1, MICROSECOND),
INTERVAL(1, DECADE),
INTERVAL(1, CENTURY),
INTERVAL(1, MILLENNIUM),
INTERVAL(1, YEAR, 10, MONTH),
INTERVAL(1, YEAR, 10, MONTH, 20, DAY),
INTERVAL(1, YEAR, 10, MONTH, 20, DAY, 3, HOUR),
INTERVAL(1, YEAR).IS_NOT_NULL(),
INTERVAL(1, YEAR).AS("one year"),
INTERVALd(0),
INTERVALd(1*time.Microsecond),
INTERVALd(1*time.Millisecond),
INTERVALd(1*time.Second),
INTERVALd(1*time.Minute),
INTERVALd(1*time.Hour),
INTERVALd(24*time.Hour),
INTERVALd(24*time.Hour+2*time.Hour+3*time.Minute+4*time.Second+5*time.Microsecond),
)
//fmt.Println(stmt.DebugSql())
err := stmt.Query(db, &struct{}{})
assert.NilError(t, err)
}
func TestSubQueryColumnReference(t *testing.T) {
type expected struct {

View file

@ -158,7 +158,7 @@ LIMIT 12;
).
LIMIT(12)
fmt.Println(query.DebugSql())
//fmt.Println(query.DebugSql())
testutils.AssertDebugStatementSql(t, query, expectedSQL, int64(1), int64(1), int64(10), int64(1), int64(2), int64(1), int64(12))
@ -1686,7 +1686,7 @@ GROUP BY payment.amount, payment.customer_id, payment.payment_date;
).GROUP_BY(Payment.Amount, Payment.CustomerID, Payment.PaymentDate).
WHERE(Payment.PaymentID.LT(Int(10)))
fmt.Println(query.Sql())
//fmt.Println(query.Sql())
testutils.AssertStatementSql(t, query, expectedSQL, 100, 100, int64(10))
@ -1722,7 +1722,7 @@ ORDER BY payment.customer_id;
WINDOW("w3").AS(Window("w2").ORDER_BY(Payment.CustomerID)).
ORDER_BY(Payment.CustomerID)
fmt.Println(query.Sql())
//fmt.Println(query.Sql())
testutils.AssertStatementSql(t, query, expectedSQL, int64(10))
@ -1748,12 +1748,6 @@ func TestSimpleView(t *testing.T) {
FilmInfo string
}
//sql, args := query.Sql()
//
//row := db.QueryRow(sql, args...)
//
//row.Scan()
var dest []ActorInfo
err := query.Query(db, &dest)