diff --git a/postgres/cast_test.go b/postgres/cast_test.go index 4537784..a1e4be5 100644 --- a/postgres/cast_test.go +++ b/postgres/cast_test.go @@ -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") } diff --git a/postgres/dialect.go b/postgres/dialect.go index 114e5a6..c1e8c0b 100644 --- a/postgres/dialect.go +++ b/postgres/dialect.go @@ -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") diff --git a/postgres/dialect_test.go b/postgres/dialect_test.go index b6061b7..a37c0c9 100644 --- a/postgres/dialect_test.go +++ b/postgres/dialect_test.go @@ -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" diff --git a/postgres/interval.go b/postgres/interval.go new file mode 100644 index 0000000..dba2c6c --- /dev/null +++ b/postgres/interval.go @@ -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") + } +} diff --git a/postgres/interval_test.go b/postgres/interval_test.go new file mode 100644 index 0000000..1d1e3de --- /dev/null +++ b/postgres/interval_test.go @@ -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')") +} diff --git a/postgres/literal_test.go b/postgres/literal_test.go index f30ef01..5206aaa 100644 --- a/postgres/literal_test.go +++ b/postgres/literal_test.go @@ -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`) } diff --git a/postgres/table_test.go b/postgres/table_test.go index 6573b02..43aa096 100644 --- a/postgres/table_test.go +++ b/postgres/table_test.go @@ -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 diff --git a/postgres/utils_test.go b/postgres/utils_test.go index c65d5b6..4a80954 100644 --- a/postgres/utils_test.go +++ b/postgres/utils_test.go @@ -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 diff --git a/tests/postgres/alltypes_test.go b/tests/postgres/alltypes_test.go index f2e8fbe..eed0695 100644 --- a/tests/postgres/alltypes_test.go +++ b/tests/postgres/alltypes_test.go @@ -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 { diff --git a/tests/postgres/select_test.go b/tests/postgres/select_test.go index 3cd2fba..2ac6c36 100644 --- a/tests/postgres/select_test.go +++ b/tests/postgres/select_test.go @@ -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)