diff --git a/bool_expression_test.go b/bool_expression_test.go deleted file mode 100644 index bb57824..0000000 --- a/bool_expression_test.go +++ /dev/null @@ -1,136 +0,0 @@ -package jet - -import ( - "testing" -) - -func TestBoolExpressionEQ(t *testing.T) { - assertClauseSerializeErr(t, table1ColBool.EQ(nil), "jet: nil rhs") - AssertPostgreClauseSerialize(t, table1ColBool.EQ(table2ColBool), "(table1.col_bool = table2.col_bool)") - AssertPostgreClauseSerialize(t, table1ColBool.EQ(Bool(true)), "(table1.col_bool = $1)", true) - - AssertMySQLClauseSerialize(t, table1ColBool.EQ(table2ColBool), "(table1.col_bool = table2.col_bool)") - AssertMySQLClauseSerialize(t, table1ColBool.EQ(Bool(true)), "(table1.col_bool = ?)", true) -} - -func TestBoolExpressionNOT_EQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColBool.NOT_EQ(table2ColBool), "(table1.col_bool != table2.col_bool)") - AssertPostgreClauseSerialize(t, table1ColBool.NOT_EQ(Bool(true)), "(table1.col_bool != $1)", true) - - AssertMySQLClauseSerialize(t, table1ColBool.NOT_EQ(table2ColBool), "(table1.col_bool != table2.col_bool)") - AssertMySQLClauseSerialize(t, table1ColBool.NOT_EQ(Bool(true)), "(table1.col_bool != ?)", true) -} - -func TestBoolExpressionIS_DISTINCT_FROM(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColBool.IS_DISTINCT_FROM(table2ColBool), "(table1.col_bool IS DISTINCT FROM table2.col_bool)") - AssertPostgreClauseSerialize(t, table1ColBool.IS_DISTINCT_FROM(Bool(false)), "(table1.col_bool IS DISTINCT FROM $1)", false) - - AssertMySQLClauseSerialize(t, table1ColBool.IS_DISTINCT_FROM(table2ColBool), "(NOT table1.col_bool <=> table2.col_bool)") - AssertMySQLClauseSerialize(t, table1ColBool.IS_DISTINCT_FROM(Bool(false)), "(NOT table1.col_bool <=> ?)", false) -} - -func TestBoolExpressionIS_NOT_DISTINCT_FROM(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColBool.IS_NOT_DISTINCT_FROM(table2ColBool), "(table1.col_bool IS NOT DISTINCT FROM table2.col_bool)") - AssertPostgreClauseSerialize(t, table1ColBool.IS_NOT_DISTINCT_FROM(Bool(false)), "(table1.col_bool IS NOT DISTINCT FROM $1)", false) - - AssertMySQLClauseSerialize(t, table1ColBool.IS_NOT_DISTINCT_FROM(table2ColBool), "(table1.col_bool <=> table2.col_bool)") - AssertMySQLClauseSerialize(t, table1ColBool.IS_NOT_DISTINCT_FROM(Bool(false)), "(table1.col_bool <=> ?)", false) - -} - -func TestBoolExpressionIS_TRUE(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColBool.IS_TRUE(), "table1.col_bool IS TRUE") - AssertPostgreClauseSerialize(t, (Int(2).EQ(table1ColInt)).IS_TRUE(), - `($1 = table1.col_int) IS TRUE`, int64(2)) - AssertPostgreClauseSerialize(t, (Int(2).EQ(table1ColInt)).IS_TRUE().AND(Int(4).EQ(table2ColInt)), - `(($1 = table1.col_int) IS TRUE AND ($2 = table2.col_int))`, int64(2), int64(4)) - - AssertMySQLClauseSerialize(t, table1ColBool.IS_TRUE(), "table1.col_bool IS TRUE") - AssertMySQLClauseSerialize(t, (Int(2).EQ(table1ColInt)).IS_TRUE(), - `(? = table1.col_int) IS TRUE`, int64(2)) - AssertMySQLClauseSerialize(t, (Int(2).EQ(table1ColInt)).IS_TRUE().AND(Int(4).EQ(table2ColInt)), - `((? = table1.col_int) IS TRUE AND (? = table2.col_int))`, int64(2), int64(4)) -} - -func TestBoolExpressionIS_NOT_TRUE(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColBool.IS_NOT_TRUE(), "table1.col_bool IS NOT TRUE") - - AssertMySQLClauseSerialize(t, table1ColBool.IS_NOT_TRUE(), "table1.col_bool IS NOT TRUE") -} - -func TestBoolExpressionIS_FALSE(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColBool.IS_FALSE(), "table1.col_bool IS FALSE") - - AssertMySQLClauseSerialize(t, table1ColBool.IS_FALSE(), "table1.col_bool IS FALSE") -} - -func TestBoolExpressionIS_NOT_FALSE(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColBool.IS_NOT_FALSE(), "table1.col_bool IS NOT FALSE") -} - -func TestBoolExpressionIS_UNKNOWN(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColBool.IS_UNKNOWN(), "table1.col_bool IS UNKNOWN") - - AssertMySQLClauseSerialize(t, table1ColBool.IS_UNKNOWN(), "table1.col_bool IS UNKNOWN") -} - -func TestBoolExpressionIS_NOT_UNKNOWN(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColBool.IS_NOT_UNKNOWN(), "table1.col_bool IS NOT UNKNOWN") - - AssertMySQLClauseSerialize(t, table1ColBool.IS_NOT_UNKNOWN(), "table1.col_bool IS NOT UNKNOWN") -} - -func TestBinaryBoolExpression(t *testing.T) { - boolExpression := Int(2).EQ(Int(3)) - - AssertPostgreClauseSerialize(t, boolExpression, "($1 = $2)", int64(2), int64(3)) - - assertProjectionSerialize(t, boolExpression, "$1 = $2", int64(2), int64(3)) - assertProjectionSerialize(t, boolExpression.AS("alias_eq_expression"), - `($1 = $2) AS "alias_eq_expression"`, int64(2), int64(3)) - AssertPostgreClauseSerialize(t, boolExpression.AND(Int(4).EQ(Int(5))), - "(($1 = $2) AND ($3 = $4))", int64(2), int64(3), int64(4), int64(5)) - AssertPostgreClauseSerialize(t, boolExpression.OR(Int(4).EQ(Int(5))), - "(($1 = $2) OR ($3 = $4))", int64(2), int64(3), int64(4), int64(5)) -} - -func TestBoolLiteral(t *testing.T) { - AssertPostgreClauseSerialize(t, Bool(true), "$1", true) - AssertPostgreClauseSerialize(t, Bool(false), "$1", false) - - AssertMySQLClauseSerialize(t, Bool(true), "?", true) - AssertMySQLClauseSerialize(t, Bool(false), "?", false) -} - -func TestExists(t *testing.T) { - - AssertPostgreClauseSerialize(t, EXISTS( - table2. - SELECT(Int(1)). - WHERE(table1Col1.EQ(table2Col3)), - ), - `(EXISTS ( - SELECT $1 - FROM db.table2 - WHERE table1.col1 = table2.col3 -))`, int64(1)) - - AssertMySQLClauseSerialize(t, EXISTS( - table2. - SELECT(Int(1)). - WHERE(table1Col1.EQ(table2Col3)), - ), - `(EXISTS ( - SELECT ? - FROM db.table2 - WHERE table1.col1 = table2.col3 -))`, int64(1)) -} - -func TestBoolExp(t *testing.T) { - AssertPostgreClauseSerialize(t, BoolExp(String("true")), "$1", "true") - AssertPostgreClauseSerialize(t, BoolExp(String("true")).IS_TRUE(), "$1 IS TRUE", "true") - - AssertMySQLClauseSerialize(t, BoolExp(String("true")), "?", "true") - AssertMySQLClauseSerialize(t, BoolExp(String("true")).IS_TRUE(), "? IS TRUE", "true") -} diff --git a/cmd/jet/main.go b/cmd/jet/main.go index 9d1997a..56b0322 100644 --- a/cmd/jet/main.go +++ b/cmd/jet/main.go @@ -3,9 +3,10 @@ package main import ( "flag" "fmt" - "github.com/go-jet/jet" - "github.com/go-jet/jet/generator/mysql" - "github.com/go-jet/jet/generator/postgres" + mysqlgen "github.com/go-jet/jet/generator/mysql" + postgresgen "github.com/go-jet/jet/generator/postgres" + "github.com/go-jet/jet/mysql" + "github.com/go-jet/jet/postgres" _ "github.com/go-sql-driver/mysql" _ "github.com/lib/pq" "os" @@ -27,7 +28,7 @@ var ( ) func init() { - flag.StringVar(&source, "source", string(jet.PostgreSQL.Name), "Database name") + flag.StringVar(&source, "source", postgres.Dialect.Name(), "Database name") flag.StringVar(&host, "host", "", "Database host path (Example: localhost)") flag.IntVar(&port, "port", 0, "Database port") @@ -72,14 +73,14 @@ Usage of jet: var err error switch source { - case jet.PostgreSQL.Name: + case postgres.Dialect.Name(): if host == "" || port == 0 || user == "" || dbName == "" || schemaName == "" { fmt.Println("\njet: required flag missing") flag.Usage() os.Exit(-2) } - genData := postgres.DBConnection{ + genData := postgresgen.DBConnection{ Host: host, Port: port, User: user, @@ -91,16 +92,16 @@ Usage of jet: SchemaName: schemaName, } - err = postgres.Generate(destDir, genData) + err = postgresgen.Generate(destDir, genData) - case jet.MySQL.Name: + case mysql.Dialect.Name(): if host == "" || port == 0 || user == "" || dbName == "" { fmt.Println("\njet: required flag missing") flag.Usage() os.Exit(-2) } - dbConn := mysql.DBConnection{ + dbConn := mysqlgen.DBConnection{ Host: host, Port: port, User: user, @@ -110,7 +111,7 @@ Usage of jet: DBName: dbName, } - err = mysql.Generate(destDir, dbConn) + err = mysqlgen.Generate(destDir, dbConn) } if err != nil { diff --git a/dialects.go b/dialects.go deleted file mode 100644 index ac3c996..0000000 --- a/dialects.go +++ /dev/null @@ -1,232 +0,0 @@ -package jet - -import ( - "github.com/pkg/errors" - "strconv" -) - -var ( - Default = MySQL - PostgreSQL = newPostgresDialect() - MySQL = newMySQLDialect() -) - -func newPostgresDialect() Dialect { - postgresDialect := newDialect("PostgreSQL", "postgres") - - postgresDialect.CastOverride = postgresCAST - postgresDialect.AliasQuoteChar = '"' - postgresDialect.IdentifierQuoteChar = '"' - postgresDialect.ArgumentPlaceholder = func(ord int) string { - return "$" + strconv.Itoa(ord) - } - postgresDialect.SupportsReturning = true - postgresDialect.UpdateAssigment = postgresUpdateAssigment - - return postgresDialect -} - -func newMySQLDialect() Dialect { - mySQLDialect := newDialect("MySQL", "mysql") - - mySQLDialect.SerializeOverrides["IS DISTINCT FROM"] = mysql_IS_DISTINCT_FROM - mySQLDialect.SerializeOverrides["IS NOT DISTINCT FROM"] = mysql_IS_NOT_DISTINCT_FROM - mySQLDialect.SerializeOverrides["/"] = mysql_DIVISION - mySQLDialect.SerializeOverrides["#"] = mysql_BIT_XOR - - mySQLDialect.AliasQuoteChar = '"' - mySQLDialect.IdentifierQuoteChar = '`' - mySQLDialect.ArgumentPlaceholder = func(int) string { - return "?" - } - - mySQLDialect.SupportsReturning = false - mySQLDialect.UpdateAssigment = mysqlUpdateAssigment - - return mySQLDialect -} - -type Dialect struct { - Name string - PackageName string - SerializeOverrides map[string]serializeOverride - CastOverride castOverride - AliasQuoteChar byte - IdentifierQuoteChar byte - ArgumentPlaceholder queryPlaceholderFunc - UpdateAssigment func(columns []column, values []clause, out *sqlBuilder) (err error) - - SupportsReturning bool -} - -func (d *Dialect) serializeOverride(operator string) serializeOverride { - return d.SerializeOverrides[operator] -} - -func mysqlUpdateAssigment(columns []column, values []clause, out *sqlBuilder) (err error) { - - if len(columns) != len(values) { - return errors.New("jet: mismatch in numers of columns and values") - } - - for i, column := range columns { - if i > 0 { - out.writeString(", ") - } - - out.writeString(column.Name()) - - out.writeString(" = ") - - if err = values[i].serialize(updateStatement, out); err != nil { - return err - } - } - - return nil -} - -func postgresUpdateAssigment(columns []column, values []clause, out *sqlBuilder) (err error) { - if len(columns) > 1 { - out.writeString("(") - } - - err = serializeColumnNames(columns, out) - - if err != nil { - return - } - - if len(columns) > 1 { - out.writeString(")") - } - - out.writeString("=") - - if len(values) > 1 { - out.writeString("(") - } - - err = serializeClauseList(updateStatement, values, out) - - if err != nil { - return - } - - if len(values) > 1 { - out.writeString(")") - } - - return -} - -type queryPlaceholderFunc func(ord int) string - -func newDialect(name, packageName string) Dialect { - newDialect := Dialect{ - Name: name, - PackageName: packageName, - } - newDialect.SerializeOverrides = make(map[string]serializeOverride) - - return newDialect -} - -func mysql_BIT_XOR(expressions ...Expression) serializeFunc { - return func(statement statementType, out *sqlBuilder, options ...serializeOption) error { - if len(expressions) != 2 { - return errors.New("Invalid number of expressions for operator") - } - - lhs := expressions[0] - rhs := expressions[1] - - if err := lhs.serialize(statement, out, options...); err != nil { - return err - } - - out.writeString("^") - - if err := rhs.serialize(statement, out, options...); err != nil { - return err - } - return nil - } -} - -func mysql_DIVISION(expressions ...Expression) serializeFunc { - return func(statement statementType, out *sqlBuilder, options ...serializeOption) error { - if len(expressions) != 2 { - return errors.New("Invalid number of expressions for operator") - } - - lhs := expressions[0] - rhs := expressions[1] - - if err := lhs.serialize(statement, out, options...); err != nil { - return err - } - - _, isLhsInt := lhs.(IntegerExpression) - _, isRhsInt := rhs.(IntegerExpression) - - if isLhsInt && isRhsInt { - out.writeString("DIV") - } else { - out.writeString("/") - } - - if err := rhs.serialize(statement, out, options...); err != nil { - return err - } - return nil - } -} - -func mysql_IS_NOT_DISTINCT_FROM(expressions ...Expression) serializeFunc { - return func(statement statementType, out *sqlBuilder, options ...serializeOption) error { - if len(expressions) != 2 { - return errors.New("Invalid number of expressions for operator") - } - if err := expressions[0].serialize(statement, out); err != nil { - return err - } - - out.writeString("<=>") - - if err := expressions[1].serialize(statement, out); err != nil { - return err - } - - return nil - } -} - -func mysql_IS_DISTINCT_FROM(expressions ...Expression) serializeFunc { - return func(statement statementType, out *sqlBuilder, options ...serializeOption) error { - out.writeString("NOT") - - err := mysql_IS_NOT_DISTINCT_FROM(expressions...)(statement, out, options...) - - if err != nil { - return err - } - - return nil - } -} - -func postgresCAST(expression Expression, castType string) serializeFunc { - return func(statement statementType, out *sqlBuilder, options ...serializeOption) error { - if err := expression.serialize(statement, out, options...); err != nil { - return err - } - out.writeString("::" + castType) - return nil - } -} - -type serializeFunc func(statement statementType, out *sqlBuilder, options ...serializeOption) error -type serializeOverride func(expressions ...Expression) serializeFunc - -type castOverride func(expression Expression, castType string) serializeFunc diff --git a/examples/quick-start/quick-start.go b/examples/quick-start/quick-start.go index 5317bda..6060fa9 100644 --- a/examples/quick-start/quick-start.go +++ b/examples/quick-start/quick-start.go @@ -9,8 +9,8 @@ import ( // dot import so go code would resemble as much as native SQL // dot import is not mandatory - . "github.com/go-jet/jet" . "github.com/go-jet/jet/examples/quick-start/.gen/jetdb/dvds/table" + . "github.com/go-jet/jet/postgres" "github.com/go-jet/jet/examples/quick-start/.gen/jetdb/dvds/model" ) diff --git a/expression_test.go b/expression_test.go deleted file mode 100644 index 2961d78..0000000 --- a/expression_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package jet - -import ( - "testing" -) - -func TestExpressionIS_NULL(t *testing.T) { - AssertPostgreClauseSerialize(t, table2Col3.IS_NULL(), "table2.col3 IS NULL") - AssertPostgreClauseSerialize(t, table2Col3.ADD(table2Col3).IS_NULL(), "(table2.col3 + table2.col3) IS NULL") - assertClauseSerializeErr(t, table2Col3.ADD(nil), "jet: nil rhs") -} - -func TestExpressionIS_NOT_NULL(t *testing.T) { - AssertPostgreClauseSerialize(t, table2Col3.IS_NOT_NULL(), "table2.col3 IS NOT NULL") - AssertPostgreClauseSerialize(t, table2Col3.ADD(table2Col3).IS_NOT_NULL(), "(table2.col3 + table2.col3) IS NOT NULL") -} - -func TestExpressionIS_DISTINCT_FROM(t *testing.T) { - AssertPostgreClauseSerialize(t, table2Col3.IS_DISTINCT_FROM(table2Col4), "(table2.col3 IS DISTINCT FROM table2.col4)") - AssertPostgreClauseSerialize(t, table2Col3.ADD(table2Col3).IS_DISTINCT_FROM(Int(23)), "((table2.col3 + table2.col3) IS DISTINCT FROM $1)", int64(23)) -} - -func TestExpressionIS_NOT_DISTINCT_FROM(t *testing.T) { - AssertPostgreClauseSerialize(t, table2Col3.IS_NOT_DISTINCT_FROM(table2Col4), "(table2.col3 IS NOT DISTINCT FROM table2.col4)") - AssertPostgreClauseSerialize(t, table2Col3.ADD(table2Col3).IS_NOT_DISTINCT_FROM(Int(23)), "((table2.col3 + table2.col3) IS NOT DISTINCT FROM $1)", int64(23)) -} - -func TestIN(t *testing.T) { - - AssertPostgreClauseSerialize(t, Float(1.11).IN(table1.SELECT(table1Col1)), - `($1 IN (( - SELECT table1.col1 AS "table1.col1" - FROM db.table1 -)))`, float64(1.11)) - - AssertPostgreClauseSerialize(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" - FROM db.table2 -)))`, int64(12)) -} - -func TestNOT_IN(t *testing.T) { - - AssertPostgreClauseSerialize(t, Float(1.11).NOT_IN(table1.SELECT(table1Col1)), - `($1 NOT IN (( - SELECT table1.col1 AS "table1.col1" - FROM db.table1 -)))`, float64(1.11)) - - AssertPostgreClauseSerialize(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" - FROM db.table2 -)))`, int64(12)) -} diff --git a/float_expression_test.go b/float_expression_test.go deleted file mode 100644 index 85c553b..0000000 --- a/float_expression_test.go +++ /dev/null @@ -1,85 +0,0 @@ -package jet - -import ( - "testing" -) - -func TestFloatExpressionEQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColFloat.EQ(table2ColFloat), "(table1.col_float = table2.col_float)") - AssertPostgreClauseSerialize(t, table1ColFloat.EQ(Float(2.11)), "(table1.col_float = $1)", float64(2.11)) -} - -func TestFloatExpressionNOT_EQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColFloat.NOT_EQ(table2ColFloat), "(table1.col_float != table2.col_float)") - AssertPostgreClauseSerialize(t, table1ColFloat.NOT_EQ(Float(2.11)), "(table1.col_float != $1)", float64(2.11)) -} - -func TestFloatExpressionIS_DISTINCT_FROM(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColFloat.IS_DISTINCT_FROM(table2ColFloat), "(table1.col_float IS DISTINCT FROM table2.col_float)") - AssertPostgreClauseSerialize(t, table1ColFloat.IS_DISTINCT_FROM(Float(2.11)), "(table1.col_float IS DISTINCT FROM $1)", float64(2.11)) -} - -func TestFloatExpressionIS_NOT_DISTINCT_FROM(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColFloat.IS_NOT_DISTINCT_FROM(table2ColFloat), "(table1.col_float IS NOT DISTINCT FROM table2.col_float)") - AssertPostgreClauseSerialize(t, table1ColFloat.IS_NOT_DISTINCT_FROM(Float(2.11)), "(table1.col_float IS NOT DISTINCT FROM $1)", float64(2.11)) -} - -func TestFloatExpressionGT(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColFloat.GT(table2ColFloat), "(table1.col_float > table2.col_float)") - AssertPostgreClauseSerialize(t, table1ColFloat.GT(Float(2.11)), "(table1.col_float > $1)", float64(2.11)) -} - -func TestFloatExpressionGT_EQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColFloat.GT_EQ(table2ColFloat), "(table1.col_float >= table2.col_float)") - AssertPostgreClauseSerialize(t, table1ColFloat.GT_EQ(Float(2.11)), "(table1.col_float >= $1)", float64(2.11)) -} - -func TestFloatExpressionLT(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColFloat.LT(table2ColFloat), "(table1.col_float < table2.col_float)") - AssertPostgreClauseSerialize(t, table1ColFloat.LT(Float(2.11)), "(table1.col_float < $1)", float64(2.11)) -} - -func TestFloatExpressionLT_EQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColFloat.LT_EQ(table2ColFloat), "(table1.col_float <= table2.col_float)") - AssertPostgreClauseSerialize(t, table1ColFloat.LT_EQ(Float(2.11)), "(table1.col_float <= $1)", float64(2.11)) -} - -func TestFloatExpressionADD(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColFloat.ADD(table2ColFloat), "(table1.col_float + table2.col_float)") - AssertPostgreClauseSerialize(t, table1ColFloat.ADD(Float(2.11)), "(table1.col_float + $1)", float64(2.11)) -} - -func TestFloatExpressionSUB(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColFloat.SUB(table2ColFloat), "(table1.col_float - table2.col_float)") - AssertPostgreClauseSerialize(t, table1ColFloat.SUB(Float(2.11)), "(table1.col_float - $1)", float64(2.11)) -} - -func TestFloatExpressionMUL(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColFloat.MUL(table2ColFloat), "(table1.col_float * table2.col_float)") - AssertPostgreClauseSerialize(t, table1ColFloat.MUL(Float(2.11)), "(table1.col_float * $1)", float64(2.11)) -} - -func TestFloatExpressionDIV(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColFloat.DIV(table2ColFloat), "(table1.col_float / table2.col_float)") - AssertPostgreClauseSerialize(t, table1ColFloat.DIV(Float(2.11)), "(table1.col_float / $1)", float64(2.11)) - - AssertMySQLClauseSerialize(t, table1ColFloat.DIV(table2ColFloat), "(table1.col_float / table2.col_float)") - AssertMySQLClauseSerialize(t, table1ColFloat.DIV(Float(2.11)), "(table1.col_float / ?)", float64(2.11)) -} - -func TestFloatExpressionMOD(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColFloat.MOD(table2ColFloat), "(table1.col_float % table2.col_float)") - AssertPostgreClauseSerialize(t, table1ColFloat.MOD(Float(2.11)), "(table1.col_float % $1)", float64(2.11)) -} - -func TestFloatExpressionPOW(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColFloat.POW(table2ColFloat), "POW(table1.col_float, table2.col_float)") - AssertPostgreClauseSerialize(t, table1ColFloat.POW(Float(2.11)), "POW(table1.col_float, $1)", float64(2.11)) -} - -func TestFloatExp(t *testing.T) { - AssertPostgreClauseSerialize(t, FloatExp(table1ColInt), "table1.col_int") - AssertPostgreClauseSerialize(t, FloatExp(table1ColInt.ADD(table3ColInt)), "(table1.col_int + table3.col_int)") - AssertPostgreClauseSerialize(t, FloatExp(table1ColInt.ADD(table3ColInt)).ADD(Float(11.11)), - "((table1.col_int + table3.col_int) + $1)", float64(11.11)) -} diff --git a/func_expression_test.go b/func_expression_test.go deleted file mode 100644 index fc7b302..0000000 --- a/func_expression_test.go +++ /dev/null @@ -1,162 +0,0 @@ -package jet - -import ( - "testing" -) - -func TestFuncAVG(t *testing.T) { - AssertPostgreClauseSerialize(t, AVG(table1ColFloat), "AVG(table1.col_float)") - AssertPostgreClauseSerialize(t, AVG(table1ColInt), "AVG(table1.col_int)") -} - -func TestFuncBIT_AND(t *testing.T) { - AssertPostgreClauseSerialize(t, BIT_AND(table1ColInt), "BIT_AND(table1.col_int)") -} - -func TestFuncBIT_OR(t *testing.T) { - AssertPostgreClauseSerialize(t, BIT_OR(table1ColInt), "BIT_OR(table1.col_int)") -} - -func TestFuncBOOL_AND(t *testing.T) { - AssertPostgreClauseSerialize(t, BOOL_AND(table1ColBool), "BOOL_AND(table1.col_bool)") -} - -func TestFuncBOOL_OR(t *testing.T) { - AssertPostgreClauseSerialize(t, BOOL_OR(table1ColBool), "BOOL_OR(table1.col_bool)") -} - -func TestFuncEVERY(t *testing.T) { - AssertPostgreClauseSerialize(t, EVERY(table1ColBool), "EVERY(table1.col_bool)") -} - -func TestFuncMIN(t *testing.T) { - t.Run("float", func(t *testing.T) { - AssertPostgreClauseSerialize(t, MINf(table1ColFloat), "MIN(table1.col_float)") - }) - - t.Run("integer", func(t *testing.T) { - AssertPostgreClauseSerialize(t, MINi(table1ColInt), "MIN(table1.col_int)") - }) -} - -func TestFuncMAX(t *testing.T) { - t.Run("float", func(t *testing.T) { - AssertPostgreClauseSerialize(t, MAXf(table1ColFloat), "MAX(table1.col_float)") - AssertPostgreClauseSerialize(t, MAXf(Float(11.2222)), "MAX($1)", float64(11.2222)) - }) - - t.Run("integer", func(t *testing.T) { - AssertPostgreClauseSerialize(t, MAXi(table1ColInt), "MAX(table1.col_int)") - AssertPostgreClauseSerialize(t, MAXi(Int(11)), "MAX($1)", int64(11)) - }) -} - -func TestFuncSUM(t *testing.T) { - t.Run("float", func(t *testing.T) { - AssertPostgreClauseSerialize(t, SUMf(table1ColFloat), "SUM(table1.col_float)") - AssertPostgreClauseSerialize(t, SUMf(Float(11.2222)), "SUM($1)", float64(11.2222)) - }) - - t.Run("integer", func(t *testing.T) { - AssertPostgreClauseSerialize(t, SUMi(table1ColInt), "SUM(table1.col_int)") - AssertPostgreClauseSerialize(t, SUMi(Int(11)), "SUM($1)", int64(11)) - }) -} - -func TestFuncCOUNT(t *testing.T) { - AssertPostgreClauseSerialize(t, COUNT(STAR), "COUNT(*)") - AssertPostgreClauseSerialize(t, COUNT(table1ColFloat), "COUNT(table1.col_float)") - AssertPostgreClauseSerialize(t, COUNT(Float(11.2222)), "COUNT($1)", float64(11.2222)) -} - -func TestFuncABS(t *testing.T) { - t.Run("float", func(t *testing.T) { - AssertPostgreClauseSerialize(t, ABSf(table1ColFloat), "ABS(table1.col_float)") - AssertPostgreClauseSerialize(t, ABSf(Float(11.2222)), "ABS($1)", float64(11.2222)) - }) - - t.Run("integer", func(t *testing.T) { - AssertPostgreClauseSerialize(t, ABSi(table1ColInt), "ABS(table1.col_int)") - AssertPostgreClauseSerialize(t, ABSi(Int(11)), "ABS($1)", int64(11)) - }) -} - -func TestFuncSQRT(t *testing.T) { - AssertPostgreClauseSerialize(t, SQRT(table1ColFloat), "SQRT(table1.col_float)") - AssertPostgreClauseSerialize(t, SQRT(Float(11.2222)), "SQRT($1)", float64(11.2222)) - AssertPostgreClauseSerialize(t, SQRT(table1ColInt), "SQRT(table1.col_int)") - AssertPostgreClauseSerialize(t, SQRT(Int(11)), "SQRT($1)", int64(11)) -} - -func TestFuncCBRT(t *testing.T) { - AssertPostgreClauseSerialize(t, CBRT(table1ColFloat), "CBRT(table1.col_float)") - AssertPostgreClauseSerialize(t, CBRT(Float(11.2222)), "CBRT($1)", float64(11.2222)) - AssertPostgreClauseSerialize(t, CBRT(table1ColInt), "CBRT(table1.col_int)") - AssertPostgreClauseSerialize(t, CBRT(Int(11)), "CBRT($1)", int64(11)) -} - -func TestFuncCEIL(t *testing.T) { - AssertPostgreClauseSerialize(t, CEIL(table1ColFloat), "CEIL(table1.col_float)") - AssertPostgreClauseSerialize(t, CEIL(Float(11.2222)), "CEIL($1)", float64(11.2222)) -} - -func TestFuncFLOOR(t *testing.T) { - AssertPostgreClauseSerialize(t, FLOOR(table1ColFloat), "FLOOR(table1.col_float)") - AssertPostgreClauseSerialize(t, FLOOR(Float(11.2222)), "FLOOR($1)", float64(11.2222)) -} - -func TestFuncROUND(t *testing.T) { - AssertPostgreClauseSerialize(t, ROUND(table1ColFloat), "ROUND(table1.col_float)") - AssertPostgreClauseSerialize(t, ROUND(Float(11.2222)), "ROUND($1)", float64(11.2222)) - - AssertPostgreClauseSerialize(t, ROUND(table1ColFloat, Int(2)), "ROUND(table1.col_float, $1)", int64(2)) - AssertPostgreClauseSerialize(t, ROUND(Float(11.2222), Int(1)), "ROUND($1, $2)", float64(11.2222), int64(1)) -} - -func TestFuncSIGN(t *testing.T) { - AssertPostgreClauseSerialize(t, SIGN(table1ColFloat), "SIGN(table1.col_float)") - AssertPostgreClauseSerialize(t, SIGN(Float(11.2222)), "SIGN($1)", float64(11.2222)) -} - -func TestFuncTRUNC(t *testing.T) { - AssertPostgreClauseSerialize(t, TRUNC(table1ColFloat), "TRUNC(table1.col_float)") - AssertPostgreClauseSerialize(t, TRUNC(Float(11.2222)), "TRUNC($1)", float64(11.2222)) - - AssertPostgreClauseSerialize(t, TRUNC(table1ColFloat, Int(2)), "TRUNC(table1.col_float, $1)", int64(2)) - AssertPostgreClauseSerialize(t, TRUNC(Float(11.2222), Int(1)), "TRUNC($1, $2)", float64(11.2222), int64(1)) -} - -func TestFuncLN(t *testing.T) { - AssertPostgreClauseSerialize(t, LN(table1ColFloat), "LN(table1.col_float)") - AssertPostgreClauseSerialize(t, LN(Float(11.2222)), "LN($1)", float64(11.2222)) -} - -func TestFuncLOG(t *testing.T) { - AssertPostgreClauseSerialize(t, LOG(table1ColFloat), "LOG(table1.col_float)") - AssertPostgreClauseSerialize(t, LOG(Float(11.2222)), "LOG($1)", float64(11.2222)) -} - -func TestFuncCOALESCE(t *testing.T) { - AssertPostgreClauseSerialize(t, COALESCE(table1ColFloat), "COALESCE(table1.col_float)") - AssertPostgreClauseSerialize(t, COALESCE(Float(11.2222), NULL, String("str")), "COALESCE($1, NULL, $2)", float64(11.2222), "str") -} - -func TestFuncNULLIF(t *testing.T) { - AssertPostgreClauseSerialize(t, NULLIF(table1ColFloat, table2ColInt), "NULLIF(table1.col_float, table2.col_int)") - AssertPostgreClauseSerialize(t, NULLIF(Float(11.2222), NULL), "NULLIF($1, NULL)", float64(11.2222)) -} - -func TestFuncGREATEST(t *testing.T) { - AssertPostgreClauseSerialize(t, GREATEST(table1ColFloat), "GREATEST(table1.col_float)") - AssertPostgreClauseSerialize(t, GREATEST(Float(11.2222), NULL, String("str")), "GREATEST($1, NULL, $2)", float64(11.2222), "str") -} - -func TestFuncLEAST(t *testing.T) { - AssertPostgreClauseSerialize(t, LEAST(table1ColFloat), "LEAST(table1.col_float)") - AssertPostgreClauseSerialize(t, LEAST(Float(11.2222), NULL, String("str")), "LEAST($1, NULL, $2)", float64(11.2222), "str") -} - -func TestTO_ASCII(t *testing.T) { - AssertPostgreClauseSerialize(t, TO_ASCII(String("Karel")), `TO_ASCII($1)`, "Karel") - AssertPostgreClauseSerialize(t, TO_ASCII(String("Karel")), `TO_ASCII($1)`, "Karel") -} diff --git a/generator/internal/template/generate.go b/generator/internal/template/generate.go index 366e907..bc853fe 100644 --- a/generator/internal/template/generate.go +++ b/generator/internal/template/generate.go @@ -3,8 +3,8 @@ package template import ( "bytes" "fmt" - "github.com/go-jet/jet" "github.com/go-jet/jet/generator/internal/metadata" + "github.com/go-jet/jet/internal/jet" "github.com/go-jet/jet/internal/utils" "path/filepath" "text/template" @@ -93,7 +93,7 @@ func generate(dirPath, packageName string, template string, metaDataList []metad } // GenerateTemplate generates template with template text and template data. -func GenerateTemplate(templateText string, templateData interface{}, dialect jet.Dialect) ([]byte, error) { +func GenerateTemplate(templateText string, templateData interface{}, dialect1 jet.Dialect) ([]byte, error) { t, err := template.New("sqlBuilderTableTemplate").Funcs(template.FuncMap{ "ToGoIdentifier": utils.ToGoIdentifier, @@ -101,7 +101,7 @@ func GenerateTemplate(templateText string, templateData interface{}, dialect jet return time.Now().Format(time.RFC850) }, "dialect": func() jet.Dialect { - return dialect + return dialect1 }, }).Parse(templateText) diff --git a/generator/internal/template/templates.go b/generator/internal/template/templates.go index c066e6b..594867a 100644 --- a/generator/internal/template/templates.go +++ b/generator/internal/template/templates.go @@ -21,22 +21,21 @@ var tableSQLBuilderTemplate = ` package table import ( - "github.com/go-jet/jet" "github.com/go-jet/jet/{{dialect.PackageName}}" ) var {{ToGoIdentifier .Name}} = new{{.GoStructName}}() type {{.GoStructName}} struct { - jet.Table + {{dialect.PackageName}}.Table //Columns {{- range .Columns}} {{ToGoIdentifier .Name}} {{dialect.PackageName}}.Column{{.SqlBuilderColumnType}} {{- end}} - AllColumns jet.ColumnList - MutableColumns jet.ColumnList + AllColumns {{dialect.PackageName}}.IColumnList + MutableColumns {{dialect.PackageName}}.IColumnList } // creates new {{.GoStructName}} with assigned alias @@ -56,15 +55,15 @@ func new{{.GoStructName}}() *{{.GoStructName}} { ) return &{{.GoStructName}}{ - Table: jet.NewTable(jet.{{dialect.Name}}, "{{.SchemaName}}", "{{.Name}}", {{template "column-list" .Columns}}), + Table: {{dialect.PackageName}}.NewTable("{{.SchemaName}}", "{{.Name}}", {{template "column-list" .Columns}}), //Columns {{- range .Columns}} {{ToGoIdentifier .Name}}: {{ToGoIdentifier .Name}}Column, {{- end}} - AllColumns: jet.ColumnList{ {{template "column-list" .Columns}} }, - MutableColumns: jet.ColumnList{ {{template "column-list" .MutableColumns}} }, + AllColumns: {{dialect.PackageName}}.ColumnList( {{template "column-list" .Columns}} ), + MutableColumns: {{dialect.PackageName}}.ColumnList( {{template "column-list" .MutableColumns}} ), } } @@ -91,15 +90,15 @@ type {{ToGoIdentifier .Name}} struct { ` var enumSQLBuilderTemplate = `package enum -import "github.com/go-jet/jet" +import "github.com/go-jet/jet/postgres" var {{ToGoIdentifier $.Name}} = &struct { {{- range $index, $element := .Values}} - {{ToGoIdentifier $element}} jet.StringExpression + {{ToGoIdentifier $element}} postgres.StringExpression {{- end}} } { {{- range $index, $element := .Values}} - {{ToGoIdentifier $element}}: jet.NewEnumValue("{{$element}}"), + {{ToGoIdentifier $element}}: postgres.NewEnumValue("{{$element}}"), {{- end}} } ` diff --git a/generator/mysql/mysql_generator.go b/generator/mysql/mysql_generator.go index ec3920e..64c14b9 100644 --- a/generator/mysql/mysql_generator.go +++ b/generator/mysql/mysql_generator.go @@ -3,9 +3,9 @@ package mysql import ( "database/sql" "fmt" - "github.com/go-jet/jet" "github.com/go-jet/jet/generator/internal/metadata" "github.com/go-jet/jet/generator/internal/template" + "github.com/go-jet/jet/mysql" "path" ) @@ -38,7 +38,7 @@ func Generate(destDir string, dbConn DBConnection) error { genPath := path.Join(destDir, dbConn.DBName) - err = template.GenerateFiles(genPath, dbInfo.TableInfos, dbInfo.EnumInfos, jet.MySQL) + err = template.GenerateFiles(genPath, dbInfo.TableInfos, dbInfo.EnumInfos, mysql.Dialect) if err != nil { return err diff --git a/generator/postgres/postgres_generator.go b/generator/postgres/postgres_generator.go index 727ca94..1fc82d4 100644 --- a/generator/postgres/postgres_generator.go +++ b/generator/postgres/postgres_generator.go @@ -3,9 +3,9 @@ package postgres import ( "database/sql" "fmt" - "github.com/go-jet/jet" "github.com/go-jet/jet/generator/internal/metadata" "github.com/go-jet/jet/generator/internal/template" + "github.com/go-jet/jet/postgres" "path" "strconv" ) @@ -42,7 +42,7 @@ func Generate(destDir string, dbConn DBConnection) error { genPath := path.Join(destDir, dbConn.DBName, dbConn.SchemaName) - err = template.GenerateFiles(genPath, schemaInfo.TableInfos, schemaInfo.EnumInfos, jet.PostgreSQL) + err = template.GenerateFiles(genPath, schemaInfo.TableInfos, schemaInfo.EnumInfos, postgres.Dialect) if err != nil { return err diff --git a/group_by_clause.go b/group_by_clause.go deleted file mode 100644 index 21b007a..0000000 --- a/group_by_clause.go +++ /dev/null @@ -1,5 +0,0 @@ -package jet - -type groupByClause interface { - serializeForGroupBy(statement statementType, out *sqlBuilder) error -} diff --git a/integer_expression_test.go b/integer_expression_test.go deleted file mode 100644 index c750ed9..0000000 --- a/integer_expression_test.go +++ /dev/null @@ -1,118 +0,0 @@ -package jet - -import ( - "testing" -) - -func TestIntegerExpressionEQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColInt.EQ(table2ColInt), "(table1.col_int = table2.col_int)") - AssertPostgreClauseSerialize(t, table1ColInt.EQ(Int(11)), "(table1.col_int = $1)", int64(11)) -} - -func TestIntegerExpressionNOT_EQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColInt.NOT_EQ(table2ColInt), "(table1.col_int != table2.col_int)") - AssertPostgreClauseSerialize(t, table1ColInt.NOT_EQ(Int(11)), "(table1.col_int != $1)", int64(11)) -} - -func TestIntegerExpressionGT(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColInt.GT(table2ColInt), "(table1.col_int > table2.col_int)") - AssertPostgreClauseSerialize(t, table1ColInt.GT(Int(11)), "(table1.col_int > $1)", int64(11)) -} - -func TestIntegerExpressionGT_EQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColInt.GT_EQ(table2ColInt), "(table1.col_int >= table2.col_int)") - AssertPostgreClauseSerialize(t, table1ColInt.GT_EQ(Int(11)), "(table1.col_int >= $1)", int64(11)) -} - -func TestIntegerExpressionLT(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColInt.LT(table2ColInt), "(table1.col_int < table2.col_int)") - AssertPostgreClauseSerialize(t, table1ColInt.LT(Int(11)), "(table1.col_int < $1)", int64(11)) -} - -func TestIntegerExpressionLT_EQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColInt.LT_EQ(table2ColInt), "(table1.col_int <= table2.col_int)") - AssertPostgreClauseSerialize(t, table1ColInt.LT_EQ(Int(11)), "(table1.col_int <= $1)", int64(11)) -} - -func TestIntegerExpressionADD(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColInt.ADD(table2ColInt), "(table1.col_int + table2.col_int)") - AssertPostgreClauseSerialize(t, table1ColInt.ADD(Int(11)), "(table1.col_int + $1)", int64(11)) -} - -func TestIntegerExpressionSUB(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColInt.SUB(table2ColInt), "(table1.col_int - table2.col_int)") - AssertPostgreClauseSerialize(t, table1ColInt.SUB(Int(11)), "(table1.col_int - $1)", int64(11)) -} - -func TestIntegerExpressionMUL(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColInt.MUL(table2ColInt), "(table1.col_int * table2.col_int)") - AssertPostgreClauseSerialize(t, table1ColInt.MUL(Int(11)), "(table1.col_int * $1)", int64(11)) -} - -func TestIntegerExpressionDIV(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColInt.DIV(table2ColInt), "(table1.col_int / table2.col_int)") - AssertPostgreClauseSerialize(t, table1ColInt.DIV(Int(11)), "(table1.col_int / $1)", int64(11)) - - AssertMySQLClauseSerialize(t, table1ColInt.DIV(table2ColInt), "(table1.col_int DIV table2.col_int)") - AssertMySQLClauseSerialize(t, table1ColInt.DIV(Int(11)), "(table1.col_int DIV ?)", int64(11)) -} - -func TestIntExpressionMOD(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColInt.MOD(table2ColInt), "(table1.col_int % table2.col_int)") - AssertPostgreClauseSerialize(t, table1ColInt.MOD(Int(11)), "(table1.col_int % $1)", int64(11)) -} - -func TestIntExpressionPOW(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColInt.POW(table2ColInt), "POW(table1.col_int, table2.col_int)") - AssertPostgreClauseSerialize(t, table1ColInt.POW(Int(11)), "POW(table1.col_int, $1)", int64(11)) -} - -func TestIntExpressionBIT_NOT(t *testing.T) { - AssertPostgreClauseSerialize(t, BIT_NOT(table2ColInt), "(~ table2.col_int)") - AssertPostgreClauseSerialize(t, BIT_NOT(Int(11)), "(~ $1)", int64(11)) -} - -func TestIntExpressionBIT_AND(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColInt.BIT_AND(table2ColInt), "(table1.col_int & table2.col_int)") - AssertPostgreClauseSerialize(t, table1ColInt.BIT_AND(Int(11)), "(table1.col_int & $1)", int64(11)) - - AssertMySQLClauseSerialize(t, table1ColInt.BIT_AND(table2ColInt), "(table1.col_int & table2.col_int)") - AssertMySQLClauseSerialize(t, table1ColInt.BIT_AND(Int(11)), "(table1.col_int & ?)", int64(11)) -} - -func TestIntExpressionBIT_OR(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColInt.BIT_OR(table2ColInt), "(table1.col_int | table2.col_int)") - AssertPostgreClauseSerialize(t, table1ColInt.BIT_OR(Int(11)), "(table1.col_int | $1)", int64(11)) - - AssertMySQLClauseSerialize(t, table1ColInt.BIT_OR(table2ColInt), "(table1.col_int | table2.col_int)") - AssertMySQLClauseSerialize(t, table1ColInt.BIT_OR(Int(11)), "(table1.col_int | ?)", int64(11)) -} - -func TestIntExpressionBIT_XOR(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColInt.BIT_XOR(table2ColInt), "(table1.col_int # table2.col_int)") - AssertPostgreClauseSerialize(t, table1ColInt.BIT_XOR(Int(11)), "(table1.col_int # $1)", int64(11)) - - AssertMySQLClauseSerialize(t, table1ColInt.BIT_XOR(table2ColInt), "(table1.col_int ^ table2.col_int)") - AssertMySQLClauseSerialize(t, table1ColInt.BIT_XOR(Int(11)), "(table1.col_int ^ ?)", int64(11)) -} - -func TestIntExpressionBIT_SHIFT_LEFT(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColInt.BIT_SHIFT_LEFT(table2ColInt), "(table1.col_int << table2.col_int)") - AssertPostgreClauseSerialize(t, table1ColInt.BIT_SHIFT_LEFT(Int(11)), "(table1.col_int << $1)", int64(11)) -} - -func TestIntExpressionBIT_SHIFT_RIGHT(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColInt.BIT_SHIFT_RIGHT(table2ColInt), "(table1.col_int >> table2.col_int)") - AssertPostgreClauseSerialize(t, table1ColInt.BIT_SHIFT_RIGHT(Int(11)), "(table1.col_int >> $1)", int64(11)) -} - -func TestIntExpressionIntExp(t *testing.T) { - AssertPostgreClauseSerialize(t, IntExp(table1ColFloat), "table1.col_float") - AssertPostgreClauseSerialize(t, IntExp(table1ColFloat.ADD(table2ColFloat)).ADD(Int(11)), - "((table1.col_float + table2.col_float) + $1)", int64(11)) -} - -func TestIntExpression_MINUSi(t *testing.T) { - AssertPostgreClauseSerialize(t, MINUSi(table2ColInt), "(- table2.col_int)") - AssertPostgreClauseSerialize(t, MINUSi(Int(3)), "(- $1)", int64(3)) -} diff --git a/README.md b/internal/jet/README.md similarity index 100% rename from README.md rename to internal/jet/README.md diff --git a/alias.go b/internal/jet/alias.go similarity index 62% rename from alias.go rename to internal/jet/alias.go index d19198b..4ec7948 100644 --- a/alias.go +++ b/internal/jet/alias.go @@ -5,14 +5,14 @@ type alias struct { alias string } -func newAlias(expression Expression, aliasName string) projection { +func newAlias(expression Expression, aliasName string) Projection { return &alias{ expression: expression, alias: aliasName, } } -func (a *alias) from(subQuery SelectTable) projection { +func (a *alias) fromImpl(subQuery SelectTable) Projection { column := newColumn(a.alias, "", nil) column.parent = &column column.subQuery = subQuery @@ -20,14 +20,14 @@ func (a *alias) from(subQuery SelectTable) projection { return &column } -func (a *alias) serializeForProjection(statement statementType, out *sqlBuilder) error { +func (a *alias) serializeForProjection(statement StatementType, out *SqlBuilder) error { err := a.expression.serialize(statement, out) if err != nil { return err } - out.writeString("AS") + out.WriteString("AS") out.writeAlias(a.alias) return nil diff --git a/bool_expression.go b/internal/jet/bool_expression.go similarity index 100% rename from bool_expression.go rename to internal/jet/bool_expression.go diff --git a/internal/jet/bool_expression_test.go b/internal/jet/bool_expression_test.go new file mode 100644 index 0000000..2b7a8e0 --- /dev/null +++ b/internal/jet/bool_expression_test.go @@ -0,0 +1,90 @@ +package jet + +import ( + "testing" +) + +func TestBoolExpressionEQ(t *testing.T) { + assertClauseSerializeErr(t, table1ColBool.EQ(nil), "jet: nil rhs") + assertClauseSerialize(t, table1ColBool.EQ(table2ColBool), "(table1.col_bool = table2.col_bool)") +} + +func TestBoolExpressionNOT_EQ(t *testing.T) { + assertClauseSerialize(t, table1ColBool.NOT_EQ(table2ColBool), "(table1.col_bool != table2.col_bool)") + assertClauseSerialize(t, table1ColBool.NOT_EQ(Bool(true)), "(table1.col_bool != TRUE)") +} + +func TestBoolExpressionIS_DISTINCT_FROM(t *testing.T) { + assertClauseSerialize(t, table1ColBool.IS_DISTINCT_FROM(table2ColBool), "(table1.col_bool IS DISTINCT FROM table2.col_bool)") + assertClauseSerialize(t, table1ColBool.IS_DISTINCT_FROM(Bool(false)), "(table1.col_bool IS DISTINCT FROM FALSE)") +} + +func TestBoolExpressionIS_NOT_DISTINCT_FROM(t *testing.T) { + assertClauseSerialize(t, table1ColBool.IS_NOT_DISTINCT_FROM(table2ColBool), "(table1.col_bool IS NOT DISTINCT FROM table2.col_bool)") + assertClauseSerialize(t, table1ColBool.IS_NOT_DISTINCT_FROM(Bool(false)), "(table1.col_bool IS NOT DISTINCT FROM FALSE)") +} + +func TestBoolExpressionIS_TRUE(t *testing.T) { + assertClauseSerialize(t, table1ColBool.IS_TRUE(), "table1.col_bool IS TRUE") + assertClauseSerialize(t, (Int(2).EQ(table1ColInt)).IS_TRUE(), + `(2 = table1.col_int) IS TRUE`) + assertClauseSerialize(t, (Int(2).EQ(table1ColInt)).IS_TRUE().AND(Int(4).EQ(table2ColInt)), + `((2 = table1.col_int) IS TRUE AND (4 = table2.col_int))`) +} + +func TestBoolExpressionIS_NOT_TRUE(t *testing.T) { + assertClauseSerialize(t, table1ColBool.IS_NOT_TRUE(), "table1.col_bool IS NOT TRUE") +} + +func TestBoolExpressionIS_FALSE(t *testing.T) { + assertClauseSerialize(t, table1ColBool.IS_FALSE(), "table1.col_bool IS FALSE") +} + +func TestBoolExpressionIS_NOT_FALSE(t *testing.T) { + assertClauseSerialize(t, table1ColBool.IS_NOT_FALSE(), "table1.col_bool IS NOT FALSE") +} + +func TestBoolExpressionIS_UNKNOWN(t *testing.T) { + assertClauseSerialize(t, table1ColBool.IS_UNKNOWN(), "table1.col_bool IS UNKNOWN") +} + +func TestBoolExpressionIS_NOT_UNKNOWN(t *testing.T) { + assertClauseSerialize(t, table1ColBool.IS_NOT_UNKNOWN(), "table1.col_bool IS NOT UNKNOWN") +} + +func TestBinaryBoolExpression(t *testing.T) { + boolExpression := Int(2).EQ(Int(3)) + + assertClauseSerialize(t, boolExpression, "(2 = 3)") + + assertProjectionSerialize(t, boolExpression, "2 = 3") + assertProjectionSerialize(t, boolExpression.AS("alias_eq_expression"), + `(2 = 3) AS "alias_eq_expression"`) + assertClauseSerialize(t, boolExpression.AND(Int(4).EQ(Int(5))), + "((2 = 3) AND (4 = 5))") + assertClauseSerialize(t, boolExpression.OR(Int(4).EQ(Int(5))), + "((2 = 3) OR (4 = 5))") +} + +func TestBoolLiteral(t *testing.T) { + assertClauseSerialize(t, Bool(true), "TRUE", true) + assertClauseSerialize(t, Bool(false), "FALSE", false) +} + +func TestExists(t *testing.T) { + assertClauseSerialize(t, EXISTS( + table2. + SELECT(Int(1)). + WHERE(table1Col1.EQ(table2Col3)), + ), + `(EXISTS ( + SELECT 1 + FROM db.table2 + WHERE table1.col1 = table2.col3 +))`) +} + +func TestBoolExp(t *testing.T) { + assertClauseSerialize(t, BoolExp(String("true")), "'true'") + assertClauseSerialize(t, BoolExp(String("true")).IS_TRUE(), "'true' IS TRUE") +} diff --git a/cast.go b/internal/jet/cast.go similarity index 86% rename from cast.go rename to internal/jet/cast.go index 7143395..4d1c0dd 100644 --- a/cast.go +++ b/internal/jet/cast.go @@ -71,23 +71,23 @@ func (b *castExpression) accept(visitor visitor) { b.expression.accept(visitor) } -func (b *castExpression) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { +func (b *castExpression) serialize(statement StatementType, out *SqlBuilder, options ...SerializeOption) error { expression := b.expression castType := b.cast - if castOverride := out.dialect.CastOverride; castOverride != nil { + if castOverride := out.Dialect.CastOverride(); castOverride != nil { return castOverride(expression, castType)(statement, out, options...) } - out.writeString("CAST(") + out.WriteString("CAST(") err := expression.serialize(statement, out, options...) if err != nil { return err } - out.writeString("AS") - out.writeString(castType + ")") + out.WriteString("AS") + out.WriteString(castType + ")") return err } diff --git a/cast_test.go b/internal/jet/cast_test.go similarity index 100% rename from cast_test.go rename to internal/jet/cast_test.go diff --git a/clause.go b/internal/jet/clause.go similarity index 54% rename from clause.go rename to internal/jet/clause.go index dfd2474..6e3388a 100644 --- a/clause.go +++ b/internal/jet/clause.go @@ -9,17 +9,21 @@ import ( "time" ) -type serializeOption int +type SerializeOption int const ( - noWrap serializeOption = iota + noWrap SerializeOption = iota ) -type clause interface { - serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error +type Clause interface { + serialize(statement StatementType, out *SqlBuilder, options ...SerializeOption) error } -func contains(options []serializeOption, option serializeOption) bool { +func Serialize(exp Clause, statementType StatementType, out *SqlBuilder, options ...SerializeOption) error { + return exp.serialize(statementType, out, options...) +} + +func contains(options []SerializeOption, option SerializeOption) bool { for _, opt := range options { if opt == option { return true @@ -29,33 +33,37 @@ func contains(options []serializeOption, option serializeOption) bool { return false } -type sqlBuilder struct { - dialect Dialect - buff bytes.Buffer - args []interface{} +type SqlBuilder struct { + Dialect Dialect + Buff bytes.Buffer + Args []interface{} lastChar byte ident int } -type statementType string +func (s *SqlBuilder) DebugSQL() string { + return queryStringToDebugString(s.Buff.String(), s.Args, s.Dialect) +} + +type StatementType string const ( - selectStatement statementType = "SELECT" - insertStatement statementType = "INSERT" - updateStatement statementType = "UPDATE" - deleteStatement statementType = "DELETE" - setStatement statementType = "SET" - lockStatement statementType = "LOCK" + SelectStatementType StatementType = "SELECT" + InsertStatementType StatementType = "INSERT" + UpdateStatementType StatementType = "UPDATE" + DeleteStatementType StatementType = "DELETE" + SetStatementType StatementType = "SET" + LockStatementType StatementType = "LOCK" ) const defaultIdent = 5 -func (q *sqlBuilder) increaseIdent() { +func (q *SqlBuilder) increaseIdent() { q.ident += defaultIdent } -func (q *sqlBuilder) decreaseIdent() { +func (q *SqlBuilder) decreaseIdent() { if q.ident < defaultIdent { q.ident = 0 } @@ -63,16 +71,16 @@ func (q *sqlBuilder) decreaseIdent() { q.ident -= defaultIdent } -func (q *sqlBuilder) writeProjections(statement statementType, projections []projection) error { +func (q *SqlBuilder) writeProjections(statement StatementType, projections []Projection) error { q.increaseIdent() - err := serializeProjectionList(statement, projections, q) + err := SerializeProjectionList(statement, projections, q) q.decreaseIdent() return err } -func (q *sqlBuilder) writeFrom(statement statementType, table ReadableTable) error { +func (q *SqlBuilder) writeFrom(statement StatementType, table ReadableTable) error { q.newLine() - q.writeString("FROM") + q.WriteString("FROM") q.increaseIdent() err := table.serialize(statement, q) @@ -81,9 +89,9 @@ func (q *sqlBuilder) writeFrom(statement statementType, table ReadableTable) err return err } -func (q *sqlBuilder) writeWhere(statement statementType, where Expression) error { +func (q *SqlBuilder) writeWhere(statement StatementType, where Expression) error { q.newLine() - q.writeString("WHERE") + q.WriteString("WHERE") q.increaseIdent() err := where.serialize(statement, q, noWrap) @@ -92,9 +100,9 @@ func (q *sqlBuilder) writeWhere(statement statementType, where Expression) error return err } -func (q *sqlBuilder) writeGroupBy(statement statementType, groupBy []groupByClause) error { +func (q *SqlBuilder) writeGroupBy(statement StatementType, groupBy []groupByClause) error { q.newLine() - q.writeString("GROUP BY") + q.WriteString("GROUP BY") q.increaseIdent() err := serializeGroupByClauseList(statement, groupBy, q) @@ -103,9 +111,9 @@ func (q *sqlBuilder) writeGroupBy(statement statementType, groupBy []groupByClau return err } -func (q *sqlBuilder) writeOrderBy(statement statementType, orderBy []orderByClause) error { +func (q *SqlBuilder) writeOrderBy(statement StatementType, orderBy []orderByClause) error { q.newLine() - q.writeString("ORDER BY") + q.WriteString("ORDER BY") q.increaseIdent() err := serializeOrderByClauseList(statement, orderBy, q) @@ -114,9 +122,9 @@ func (q *sqlBuilder) writeOrderBy(statement statementType, orderBy []orderByClau return err } -func (q *sqlBuilder) writeHaving(statement statementType, having Expression) error { +func (q *SqlBuilder) writeHaving(statement StatementType, having Expression) error { q.newLine() - q.writeString("HAVING") + q.WriteString("HAVING") q.increaseIdent() err := having.serialize(statement, q, noWrap) @@ -125,37 +133,37 @@ func (q *sqlBuilder) writeHaving(statement statementType, having Expression) err return err } -func (q *sqlBuilder) writeReturning(statement statementType, returning []projection) error { +func (q *SqlBuilder) writeReturning(statement StatementType, returning []Projection) error { if len(returning) == 0 { return nil } - if !q.dialect.SupportsReturning { - panic("jet: " + q.dialect.Name + " dialect does not support RETURNING.") + if !q.Dialect.SupportsReturning() { + panic("jet: " + q.Dialect.Name() + " dialect does not support RETURNING.") } q.newLine() - q.writeString("RETURNING") + q.WriteString("RETURNING") q.increaseIdent() return q.writeProjections(statement, returning) } -func (q *sqlBuilder) newLine() { +func (q *SqlBuilder) newLine() { q.write([]byte{'\n'}) q.write(bytes.Repeat([]byte{' '}, q.ident)) } -func (q *sqlBuilder) write(data []byte) { +func (q *SqlBuilder) write(data []byte) { if len(data) == 0 { return } - if !isPreSeparator(q.lastChar) && !isPostSeparator(data[0]) && q.buff.Len() > 0 { - q.buff.WriteByte(' ') + if !isPreSeparator(q.lastChar) && !isPostSeparator(data[0]) && q.Buff.Len() > 0 { + q.Buff.WriteByte(' ') } - q.buff.Write(data) + q.Buff.Write(data) q.lastChar = data[len(data)-1] } @@ -167,43 +175,43 @@ func isPostSeparator(b byte) bool { return b == ' ' || b == '.' || b == ',' || b == ')' || b == '\n' || b == ':' } -func (q *sqlBuilder) writeAlias(str string) { - aliasQuoteChar := string(q.dialect.AliasQuoteChar) - q.writeString(aliasQuoteChar + str + aliasQuoteChar) +func (q *SqlBuilder) writeAlias(str string) { + aliasQuoteChar := string(q.Dialect.AliasQuoteChar()) + q.WriteString(aliasQuoteChar + str + aliasQuoteChar) } -func (q *sqlBuilder) writeString(str string) { +func (q *SqlBuilder) WriteString(str string) { q.write([]byte(str)) } -func (q *sqlBuilder) writeIdentifier(name string, alwaysQuote ...bool) { +func (q *SqlBuilder) writeIdentifier(name string, alwaysQuote ...bool) { quoteWrap := name != strings.ToLower(name) || strings.ContainsAny(name, ". -") if quoteWrap || len(alwaysQuote) > 0 { - identQuoteChar := string(q.dialect.IdentifierQuoteChar) - q.writeString(identQuoteChar + name + identQuoteChar) + identQuoteChar := string(q.Dialect.IdentifierQuoteChar()) + q.WriteString(identQuoteChar + name + identQuoteChar) } else { - q.writeString(name) + q.WriteString(name) } } -func (q *sqlBuilder) writeByte(b byte) { +func (q *SqlBuilder) writeByte(b byte) { q.write([]byte{b}) } -func (q *sqlBuilder) finalize() (string, []interface{}) { - return q.buff.String() + ";\n", q.args +func (q *SqlBuilder) finalize() (string, []interface{}) { + return q.Buff.String() + ";\n", q.Args } -func (q *sqlBuilder) insertConstantArgument(arg interface{}) { - q.writeString(argToString(arg)) +func (q *SqlBuilder) insertConstantArgument(arg interface{}) { + q.WriteString(argToString(arg)) } -func (q *sqlBuilder) insertParametrizedArgument(arg interface{}) { - q.args = append(q.args, arg) - argPlaceholder := q.dialect.ArgumentPlaceholder(len(q.args)) +func (q *SqlBuilder) insertParametrizedArgument(arg interface{}) { + q.Args = append(q.Args, arg) + argPlaceholder := q.Dialect.ArgumentPlaceholder()(len(q.Args)) - q.writeString(argPlaceholder) + q.WriteString(argPlaceholder) } func argToString(value interface{}) string { diff --git a/clause_test.go b/internal/jet/clause_test.go similarity index 100% rename from clause_test.go rename to internal/jet/clause_test.go diff --git a/column.go b/internal/jet/column.go similarity index 50% rename from column.go rename to internal/jet/column.go index cd19e5d..d634132 100644 --- a/column.go +++ b/internal/jet/column.go @@ -2,19 +2,19 @@ package jet -type column interface { +type IColumn interface { Name() string TableName() string - setTableName(table string) - setSubQuery(subQuery SelectTable) - defaultAlias() string + SetTableName(table string) + SetSubQuery(subQuery SelectTable) + DefaultAlias() string } // Column is common column interface for all types of columns. type Column interface { Expression - column + IColumn } // The base type for real materialized columns. @@ -47,15 +47,15 @@ func (c *columnImpl) TableName() string { return c.tableName } -func (c *columnImpl) setTableName(table string) { +func (c *columnImpl) SetTableName(table string) { c.tableName = table } -func (c *columnImpl) setSubQuery(subQuery SelectTable) { +func (c *columnImpl) SetSubQuery(subQuery SelectTable) { c.subQuery = subQuery } -func (c *columnImpl) defaultAlias() string { +func (c *columnImpl) DefaultAlias() string { if c.tableName != "" { return c.tableName + "." + c.name } @@ -63,10 +63,10 @@ func (c *columnImpl) defaultAlias() string { return c.name } -func (c *columnImpl) serializeForOrderBy(statement statementType, out *sqlBuilder) error { - if statement == setStatement { +func (c *columnImpl) serializeForOrderBy(statement StatementType, out *SqlBuilder) error { + if statement == SetStatementType { // set Statement (UNION, EXCEPT ...) can reference only select projections in order by clause - out.writeAlias(c.defaultAlias()) //always quote + out.writeAlias(c.DefaultAlias()) //always quote return nil } @@ -74,25 +74,25 @@ func (c *columnImpl) serializeForOrderBy(statement statementType, out *sqlBuilde return c.serialize(statement, out) } -func (c columnImpl) serializeForProjection(statement statementType, out *sqlBuilder) error { +func (c columnImpl) serializeForProjection(statement StatementType, out *SqlBuilder) error { err := c.serialize(statement, out) if err != nil { return err } - out.writeString("AS") - out.writeAlias(c.defaultAlias()) + out.WriteString("AS") + out.writeAlias(c.DefaultAlias()) return nil } -func (c columnImpl) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { +func (c columnImpl) serialize(statement StatementType, out *SqlBuilder, options ...SerializeOption) error { if c.subQuery != nil { out.writeIdentifier(c.subQuery.Alias()) out.writeByte('.') - out.writeIdentifier(c.defaultAlias(), true) + out.writeIdentifier(c.DefaultAlias(), true) } else { if c.tableName != "" { out.writeIdentifier(c.tableName) @@ -107,26 +107,38 @@ func (c columnImpl) serialize(statement statementType, out *sqlBuilder, options //------------------------------------------------------// -// ColumnList is redefined type to support list of columns as single projection -type ColumnList []Column +type IColumnList interface { + Projection + IColumn -// projection interface implementation -func (cl ColumnList) isProjectionType() {} + Columns() []Column +} -func (cl ColumnList) from(subQuery SelectTable) projection { +func ColumnList(columns ...Column) IColumnList { + return columnListImpl(columns) +} + +// ColumnList is redefined type to support list of columns as single Projection +type columnListImpl []Column + +func (cl columnListImpl) Columns() []Column { + return cl +} + +func (cl columnListImpl) fromImpl(subQuery SelectTable) Projection { newProjectionList := ProjectionList{} for _, column := range cl { - newProjectionList = append(newProjectionList, column.from(subQuery)) + newProjectionList = append(newProjectionList, column.fromImpl(subQuery)) } return newProjectionList } -func (cl ColumnList) serializeForProjection(statement statementType, out *sqlBuilder) error { - projections := columnListToProjectionList(cl) +func (cl columnListImpl) serializeForProjection(statement StatementType, out *SqlBuilder) error { + projections := ColumnListToProjectionList(cl) - err := serializeProjectionList(statement, projections, out) + err := SerializeProjectionList(statement, projections, out) if err != nil { return err @@ -138,10 +150,10 @@ func (cl ColumnList) serializeForProjection(statement statementType, out *sqlBui // dummy column interface implementation // Name is placeholder for ColumnList to implement Column interface -func (cl ColumnList) Name() string { return "" } +func (cl columnListImpl) Name() string { return "" } // TableName is placeholder for ColumnList to implement Column interface -func (cl ColumnList) TableName() string { return "" } -func (cl ColumnList) setTableName(name string) {} -func (cl ColumnList) setSubQuery(subQuery SelectTable) {} -func (cl ColumnList) defaultAlias() string { return "" } +func (cl columnListImpl) TableName() string { return "" } +func (cl columnListImpl) SetTableName(name string) {} +func (cl columnListImpl) SetSubQuery(subQuery SelectTable) {} +func (cl columnListImpl) DefaultAlias() string { return "" } diff --git a/column_test.go b/internal/jet/column_test.go similarity index 68% rename from column_test.go rename to internal/jet/column_test.go index 9cf6c0b..c6ded56 100644 --- a/column_test.go +++ b/internal/jet/column_test.go @@ -6,9 +6,9 @@ func TestColumn(t *testing.T) { column := newColumn("col", "", nil) column.expressionInterfaceImpl.parent = &column - AssertPostgreClauseSerialize(t, column, "col") - column.setTableName("table1") - AssertPostgreClauseSerialize(t, column, "table1.col") + assertClauseSerialize(t, column, "col") + column.SetTableName("table1") + assertClauseSerialize(t, column, "table1.col") assertProjectionSerialize(t, &column, `table1.col AS "table1.col"`) assertProjectionSerialize(t, column.AS("alias1"), `table1.col AS "alias1"`) } diff --git a/column_types.go b/internal/jet/column_types.go similarity index 77% rename from column_types.go rename to internal/jet/column_types.go index 370942f..baff46c 100644 --- a/column_types.go +++ b/internal/jet/column_types.go @@ -3,7 +3,7 @@ package jet // ColumnBool is interface for SQL boolean columns. type ColumnBool interface { BoolExpression - column + IColumn From(subQuery SelectTable) ColumnBool } @@ -14,16 +14,16 @@ type boolColumnImpl struct { columnImpl } -func (i *boolColumnImpl) from(subQuery SelectTable) projection { +func (i *boolColumnImpl) fromImpl(subQuery SelectTable) Projection { newBoolColumn := BoolColumn(i.name) - newBoolColumn.setTableName(i.tableName) - newBoolColumn.setSubQuery(subQuery) + newBoolColumn.SetTableName(i.tableName) + newBoolColumn.SetSubQuery(subQuery) return newBoolColumn } func (i *boolColumnImpl) From(subQuery SelectTable) ColumnBool { - newBoolColumn := i.from(subQuery).(ColumnBool) + newBoolColumn := i.fromImpl(subQuery).(ColumnBool) return newBoolColumn } @@ -42,7 +42,7 @@ func BoolColumn(name string) ColumnBool { // ColumnFloat is interface for SQL real, numeric, decimal or double precision column. type ColumnFloat interface { FloatExpression - column + IColumn From(subQuery SelectTable) ColumnFloat } @@ -52,16 +52,16 @@ type floatColumnImpl struct { columnImpl } -func (i *floatColumnImpl) from(subQuery SelectTable) projection { +func (i *floatColumnImpl) fromImpl(subQuery SelectTable) Projection { newFloatColumn := FloatColumn(i.name) - newFloatColumn.setTableName(i.tableName) - newFloatColumn.setSubQuery(subQuery) + newFloatColumn.SetTableName(i.tableName) + newFloatColumn.SetSubQuery(subQuery) return newFloatColumn } func (i *floatColumnImpl) From(subQuery SelectTable) ColumnFloat { - newFloatColumn := i.from(subQuery).(ColumnFloat) + newFloatColumn := i.fromImpl(subQuery).(ColumnFloat) return newFloatColumn } @@ -80,7 +80,7 @@ func FloatColumn(name string) ColumnFloat { // ColumnInteger is interface for SQL smallint, integer, bigint columns. type ColumnInteger interface { IntegerExpression - column + IColumn From(subQuery SelectTable) ColumnInteger } @@ -91,16 +91,16 @@ type integerColumnImpl struct { columnImpl } -func (i *integerColumnImpl) from(subQuery SelectTable) projection { +func (i *integerColumnImpl) fromImpl(subQuery SelectTable) Projection { newIntColumn := IntegerColumn(i.name) - newIntColumn.setTableName(i.tableName) - newIntColumn.setSubQuery(subQuery) + newIntColumn.SetTableName(i.tableName) + newIntColumn.SetSubQuery(subQuery) return newIntColumn } func (i *integerColumnImpl) From(subQuery SelectTable) ColumnInteger { - return i.from(subQuery).(ColumnInteger) + return i.fromImpl(subQuery).(ColumnInteger) } // IntegerColumn creates named integer column. @@ -118,7 +118,7 @@ func IntegerColumn(name string) ColumnInteger { // bytea, uuid columns and enums types. type ColumnString interface { StringExpression - column + IColumn From(subQuery SelectTable) ColumnString } @@ -129,16 +129,16 @@ type stringColumnImpl struct { columnImpl } -func (i *stringColumnImpl) from(subQuery SelectTable) projection { +func (i *stringColumnImpl) fromImpl(subQuery SelectTable) Projection { newStrColumn := StringColumn(i.name) - newStrColumn.setTableName(i.tableName) - newStrColumn.setSubQuery(subQuery) + newStrColumn.SetTableName(i.tableName) + newStrColumn.SetSubQuery(subQuery) return newStrColumn } func (i *stringColumnImpl) From(subQuery SelectTable) ColumnString { - return i.from(subQuery).(ColumnString) + return i.fromImpl(subQuery).(ColumnString) } // StringColumn creates named string column. @@ -155,7 +155,7 @@ func StringColumn(name string) ColumnString { // ColumnTime is interface for SQL time column. type ColumnTime interface { TimeExpression - column + IColumn From(subQuery SelectTable) ColumnTime } @@ -165,16 +165,16 @@ type timeColumnImpl struct { columnImpl } -func (i *timeColumnImpl) from(subQuery SelectTable) projection { +func (i *timeColumnImpl) fromImpl(subQuery SelectTable) Projection { newTimeColumn := TimeColumn(i.name) - newTimeColumn.setTableName(i.tableName) - newTimeColumn.setSubQuery(subQuery) + newTimeColumn.SetTableName(i.tableName) + newTimeColumn.SetSubQuery(subQuery) return newTimeColumn } func (i *timeColumnImpl) From(subQuery SelectTable) ColumnTime { - return i.from(subQuery).(ColumnTime) + return i.fromImpl(subQuery).(ColumnTime) } // TimeColumn creates named time column @@ -190,7 +190,7 @@ func TimeColumn(name string) ColumnTime { // ColumnTimez is interface of SQL time with time zone columns. type ColumnTimez interface { TimezExpression - column + IColumn From(subQuery SelectTable) ColumnTimez } @@ -201,16 +201,16 @@ type timezColumnImpl struct { columnImpl } -func (i *timezColumnImpl) from(subQuery SelectTable) projection { +func (i *timezColumnImpl) fromImpl(subQuery SelectTable) Projection { newTimezColumn := TimezColumn(i.name) - newTimezColumn.setTableName(i.tableName) - newTimezColumn.setSubQuery(subQuery) + newTimezColumn.SetTableName(i.tableName) + newTimezColumn.SetSubQuery(subQuery) return newTimezColumn } func (i *timezColumnImpl) From(subQuery SelectTable) ColumnTimez { - return i.from(subQuery).(ColumnTimez) + return i.fromImpl(subQuery).(ColumnTimez) } // TimezColumn creates named time with time zone column. @@ -227,7 +227,7 @@ func TimezColumn(name string) ColumnTimez { // ColumnTimestamp is interface of SQL timestamp columns. type ColumnTimestamp interface { TimestampExpression - column + IColumn From(subQuery SelectTable) ColumnTimestamp } @@ -238,16 +238,16 @@ type timestampColumnImpl struct { columnImpl } -func (i *timestampColumnImpl) from(subQuery SelectTable) projection { +func (i *timestampColumnImpl) fromImpl(subQuery SelectTable) Projection { newTimestampColumn := TimestampColumn(i.name) - newTimestampColumn.setTableName(i.tableName) - newTimestampColumn.setSubQuery(subQuery) + newTimestampColumn.SetTableName(i.tableName) + newTimestampColumn.SetSubQuery(subQuery) return newTimestampColumn } func (i *timestampColumnImpl) From(subQuery SelectTable) ColumnTimestamp { - return i.from(subQuery).(ColumnTimestamp) + return i.fromImpl(subQuery).(ColumnTimestamp) } // TimestampColumn creates named timestamp column @@ -264,7 +264,7 @@ func TimestampColumn(name string) ColumnTimestamp { // ColumnTimestampz is interface of SQL timestamp with timezone columns. type ColumnTimestampz interface { TimestampzExpression - column + IColumn From(subQuery SelectTable) ColumnTimestampz } @@ -275,16 +275,16 @@ type timestampzColumnImpl struct { columnImpl } -func (i *timestampzColumnImpl) from(subQuery SelectTable) projection { +func (i *timestampzColumnImpl) fromImpl(subQuery SelectTable) Projection { newTimestampzColumn := TimestampzColumn(i.name) - newTimestampzColumn.setTableName(i.tableName) - newTimestampzColumn.setSubQuery(subQuery) + newTimestampzColumn.SetTableName(i.tableName) + newTimestampzColumn.SetSubQuery(subQuery) return newTimestampzColumn } func (i *timestampzColumnImpl) From(subQuery SelectTable) ColumnTimestampz { - return i.from(subQuery).(ColumnTimestampz) + return i.fromImpl(subQuery).(ColumnTimestampz) } // TimestampzColumn creates named timestamp with time zone column. @@ -301,7 +301,7 @@ func TimestampzColumn(name string) ColumnTimestampz { // ColumnDate is interface of SQL date columns. type ColumnDate interface { DateExpression - column + IColumn From(subQuery SelectTable) ColumnDate } @@ -312,16 +312,16 @@ type dateColumnImpl struct { columnImpl } -func (i *dateColumnImpl) from(subQuery SelectTable) projection { +func (i *dateColumnImpl) fromImpl(subQuery SelectTable) Projection { newDateColumn := DateColumn(i.name) - newDateColumn.setTableName(i.tableName) - newDateColumn.setSubQuery(subQuery) + newDateColumn.SetTableName(i.tableName) + newDateColumn.SetSubQuery(subQuery) return newDateColumn } func (i *dateColumnImpl) From(subQuery SelectTable) ColumnDate { - return i.from(subQuery).(ColumnDate) + return i.fromImpl(subQuery).(ColumnDate) } // DateColumn creates named date column. diff --git a/column_types_test.go b/internal/jet/column_types_test.go similarity index 50% rename from column_types_test.go rename to internal/jet/column_types_test.go index 4ceeec0..df8c241 100644 --- a/column_types_test.go +++ b/internal/jet/column_types_test.go @@ -8,38 +8,38 @@ var subQuery = table1.SELECT(table1ColFloat, table1ColInt).AsTable("sub_query") func TestNewBoolColumn(t *testing.T) { boolColumn := BoolColumn("colBool").From(subQuery) - AssertPostgreClauseSerialize(t, boolColumn, `sub_query."colBool"`) - AssertPostgreClauseSerialize(t, boolColumn.EQ(Bool(true)), `(sub_query."colBool" = $1)`, true) + assertClauseSerialize(t, boolColumn, `sub_query."colBool"`) + assertClauseSerialize(t, boolColumn.EQ(Bool(true)), `(sub_query."colBool" = $1)`, true) assertProjectionSerialize(t, boolColumn, `sub_query."colBool" AS "colBool"`) boolColumn2 := table1ColBool.From(subQuery) - AssertPostgreClauseSerialize(t, boolColumn2, `sub_query."table1.col_bool"`) - AssertPostgreClauseSerialize(t, boolColumn2.EQ(Bool(true)), `(sub_query."table1.col_bool" = $1)`, true) + assertClauseSerialize(t, boolColumn2, `sub_query."table1.col_bool"`) + assertClauseSerialize(t, boolColumn2.EQ(Bool(true)), `(sub_query."table1.col_bool" = $1)`, true) assertProjectionSerialize(t, boolColumn2, `sub_query."table1.col_bool" AS "table1.col_bool"`) } func TestNewIntColumn(t *testing.T) { intColumn := IntegerColumn("col_int").From(subQuery) - AssertPostgreClauseSerialize(t, intColumn, `sub_query."col_int"`) - AssertPostgreClauseSerialize(t, intColumn.EQ(Int(12)), `(sub_query."col_int" = $1)`, int64(12)) + assertClauseSerialize(t, intColumn, `sub_query."col_int"`) + assertClauseSerialize(t, intColumn.EQ(Int(12)), `(sub_query."col_int" = $1)`, int64(12)) assertProjectionSerialize(t, intColumn, `sub_query."col_int" AS "col_int"`) intColumn2 := table1ColInt.From(subQuery) - AssertPostgreClauseSerialize(t, intColumn2, `sub_query."table1.col_int"`) - AssertPostgreClauseSerialize(t, intColumn2.EQ(Int(14)), `(sub_query."table1.col_int" = $1)`, int64(14)) + assertClauseSerialize(t, intColumn2, `sub_query."table1.col_int"`) + assertClauseSerialize(t, intColumn2.EQ(Int(14)), `(sub_query."table1.col_int" = $1)`, int64(14)) assertProjectionSerialize(t, intColumn2, `sub_query."table1.col_int" AS "table1.col_int"`) } func TestNewFloatColumnColumn(t *testing.T) { floatColumn := FloatColumn("col_float").From(subQuery) - AssertPostgreClauseSerialize(t, floatColumn, `sub_query."col_float"`) - AssertPostgreClauseSerialize(t, floatColumn.EQ(Float(1.11)), `(sub_query."col_float" = $1)`, float64(1.11)) + assertClauseSerialize(t, floatColumn, `sub_query."col_float"`) + assertClauseSerialize(t, floatColumn.EQ(Float(1.11)), `(sub_query."col_float" = $1)`, float64(1.11)) assertProjectionSerialize(t, floatColumn, `sub_query."col_float" AS "col_float"`) floatColumn2 := table1ColFloat.From(subQuery) - AssertPostgreClauseSerialize(t, floatColumn2, `sub_query."table1.col_float"`) - AssertPostgreClauseSerialize(t, floatColumn2.EQ(Float(2.22)), `(sub_query."table1.col_float" = $1)`, float64(2.22)) + 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"`) } diff --git a/date_expression.go b/internal/jet/date_expression.go similarity index 100% rename from date_expression.go rename to internal/jet/date_expression.go diff --git a/delete_statement.go b/internal/jet/delete_statement.go similarity index 78% rename from delete_statement.go rename to internal/jet/delete_statement.go index ec0c09c..1efb6ed 100644 --- a/delete_statement.go +++ b/internal/jet/delete_statement.go @@ -13,7 +13,7 @@ type DeleteStatement interface { WHERE(expression BoolExpression) DeleteStatement - RETURNING(projections ...projection) DeleteStatement + RETURNING(projections ...Projection) DeleteStatement } func newDeleteStatement(table WritableTable) DeleteStatement { @@ -25,7 +25,7 @@ func newDeleteStatement(table WritableTable) DeleteStatement { type deleteStatementImpl struct { table WritableTable where BoolExpression - returning []projection + returning []Projection } func (d *deleteStatementImpl) WHERE(expression BoolExpression) DeleteStatement { @@ -33,7 +33,7 @@ func (d *deleteStatementImpl) WHERE(expression BoolExpression) DeleteStatement { return d } -func (d *deleteStatementImpl) RETURNING(projections ...projection) DeleteStatement { +func (d *deleteStatementImpl) RETURNING(projections ...Projection) DeleteStatement { d.returning = projections return d } @@ -44,18 +44,18 @@ func (d *deleteStatementImpl) accept(visitor visitor) { d.table.accept(visitor) } -func (d *deleteStatementImpl) serializeImpl(out *sqlBuilder) error { +func (d *deleteStatementImpl) serializeImpl(out *SqlBuilder) error { if d == nil { return errors.New("jet: delete statement is nil") } out.newLine() - out.writeString("DELETE FROM") + out.WriteString("DELETE FROM") if d.table == nil { return errors.New("jet: nil tableName") } - if err := d.table.serialize(deleteStatement, out); err != nil { + if err := d.table.serialize(DeleteStatementType, out); err != nil { return err } @@ -63,11 +63,11 @@ func (d *deleteStatementImpl) serializeImpl(out *sqlBuilder) error { return errors.New("jet: deleting without a WHERE clause") } - if err := out.writeWhere(deleteStatement, d.where); err != nil { + if err := out.writeWhere(DeleteStatementType, d.where); err != nil { return err } - if err := out.writeReturning(deleteStatement, d.returning); err != nil { + if err := out.writeReturning(DeleteStatementType, d.returning); err != nil { return err } @@ -75,8 +75,8 @@ func (d *deleteStatementImpl) serializeImpl(out *sqlBuilder) error { } func (d *deleteStatementImpl) Sql(dialect ...Dialect) (query string, args []interface{}, err error) { - queryData := &sqlBuilder{ - dialect: detectDialect(d, dialect...), + queryData := &SqlBuilder{ + Dialect: detectDialect(d, dialect...), } err = d.serializeImpl(queryData) diff --git a/delete_statement_test.go b/internal/jet/delete_statement_test.go similarity index 100% rename from delete_statement_test.go rename to internal/jet/delete_statement_test.go diff --git a/internal/jet/dialects.go b/internal/jet/dialects.go new file mode 100644 index 0000000..5a0e15f --- /dev/null +++ b/internal/jet/dialects.go @@ -0,0 +1,104 @@ +package jet + +var ANSII = NewDialect(DialectParams{ // just for tests + AliasQuoteChar: '"', + ArgumentPlaceholder: func(ord int) string { + return "#" + }, +}) + +type Dialect interface { + Name() string + PackageName() string + SerializeOverride(operator string) SerializeOverride + CastOverride() CastOverride + AliasQuoteChar() byte + IdentifierQuoteChar() byte + ArgumentPlaceholder() QueryPlaceholderFunc + UpdateAssigment() func(columns []IColumn, values []Clause, out *SqlBuilder) (err error) + SupportsReturning() bool +} + +type SerializeFunc func(statement StatementType, out *SqlBuilder, options ...SerializeOption) error +type SerializeOverride func(expressions ...Expression) SerializeFunc + +type QueryPlaceholderFunc func(ord int) string + +type CastOverride func(expression Expression, castType string) SerializeFunc +type UpdateAssigmentFunc func(columns []IColumn, values []Clause, out *SqlBuilder) (err error) + +type DialectParams struct { + Name string + PackageName string + SerializeOverrides map[string]SerializeOverride + CastOverride CastOverride + AliasQuoteChar byte + IdentifierQuoteChar byte + ArgumentPlaceholder QueryPlaceholderFunc + UpdateAssigment func(columns []IColumn, values []Clause, out *SqlBuilder) (err error) + + SupportsReturning bool +} + +func NewDialect(params DialectParams) Dialect { + return &dialectImpl{ + name: params.Name, + packageName: params.PackageName, + serializeOverrides: params.SerializeOverrides, + castOverride: params.CastOverride, + aliasQuoteChar: params.AliasQuoteChar, + identifierQuoteChar: params.IdentifierQuoteChar, + argumentPlaceholder: params.ArgumentPlaceholder, + updateAssigment: params.UpdateAssigment, + supportsReturning: params.SupportsReturning, + } +} + +type dialectImpl struct { + name string + packageName string + serializeOverrides map[string]SerializeOverride + castOverride CastOverride + aliasQuoteChar byte + identifierQuoteChar byte + argumentPlaceholder QueryPlaceholderFunc + updateAssigment UpdateAssigmentFunc + + supportsReturning bool +} + +func (d *dialectImpl) Name() string { + return d.name +} + +func (d *dialectImpl) PackageName() string { + return d.packageName +} + +func (d *dialectImpl) SerializeOverride(operator string) SerializeOverride { + return d.serializeOverrides[operator] +} + +func (d *dialectImpl) CastOverride() CastOverride { + return d.castOverride +} + +func (d *dialectImpl) AliasQuoteChar() byte { + return d.aliasQuoteChar +} + +func (d *dialectImpl) IdentifierQuoteChar() byte { + return d.identifierQuoteChar +} + +func (d *dialectImpl) ArgumentPlaceholder() QueryPlaceholderFunc { + return d.argumentPlaceholder +} + +func (d *dialectImpl) UpdateAssigment() func(columns []IColumn, values []Clause, out *SqlBuilder) (err error) { + return d.updateAssigment +} + +func (d *dialectImpl) SupportsReturning() bool { + return d.supportsReturning +} diff --git a/enum_value.go b/internal/jet/enum_value.go similarity index 79% rename from enum_value.go rename to internal/jet/enum_value.go index 0828517..ba598b1 100644 --- a/enum_value.go +++ b/internal/jet/enum_value.go @@ -18,7 +18,7 @@ func NewEnumValue(name string) StringExpression { return enumValue } -func (e enumValue) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { +func (e enumValue) serialize(statement StatementType, out *SqlBuilder, options ...SerializeOption) error { out.insertConstantArgument(e.name) return nil } diff --git a/expression.go b/internal/jet/expression.go similarity index 83% rename from expression.go rename to internal/jet/expression.go index 4e5b2e4..791d3d9 100644 --- a/expression.go +++ b/internal/jet/expression.go @@ -13,8 +13,8 @@ type Expression interface { } type expression interface { - clause - projection + Clause + Projection groupByClause orderByClause @@ -29,7 +29,7 @@ type expression interface { NOT_IN(expressions ...Expression) BoolExpression // The temporary alias name to assign to the expression - AS(alias string) projection + AS(alias string) Projection // Expression will be used to sort query result in ascending order ASC() orderByClause @@ -41,7 +41,7 @@ type expressionInterfaceImpl struct { parent Expression } -func (e *expressionInterfaceImpl) from(subQuery SelectTable) projection { +func (e *expressionInterfaceImpl) fromImpl(subQuery SelectTable) Projection { return e.parent } @@ -61,7 +61,7 @@ func (e *expressionInterfaceImpl) NOT_IN(expressions ...Expression) BoolExpressi return newBinaryBoolOperator(e.parent, WRAP(expressions...), "NOT IN") } -func (e *expressionInterfaceImpl) AS(alias string) projection { +func (e *expressionInterfaceImpl) AS(alias string) Projection { return newAlias(e.parent, alias) } @@ -73,15 +73,15 @@ func (e *expressionInterfaceImpl) DESC() orderByClause { return newOrderByClause(e.parent, false) } -func (e *expressionInterfaceImpl) serializeForGroupBy(statement statementType, out *sqlBuilder) error { +func (e *expressionInterfaceImpl) serializeForGroupBy(statement StatementType, out *SqlBuilder) error { return e.parent.serialize(statement, out, noWrap) } -func (e *expressionInterfaceImpl) serializeForProjection(statement statementType, out *sqlBuilder) error { +func (e *expressionInterfaceImpl) serializeForProjection(statement StatementType, out *SqlBuilder) error { return e.parent.serialize(statement, out, noWrap) } -func (e *expressionInterfaceImpl) serializeForOrderBy(statement statementType, out *sqlBuilder) error { +func (e *expressionInterfaceImpl) serializeForOrderBy(statement StatementType, out *SqlBuilder) error { return e.parent.serialize(statement, out, noWrap) } @@ -106,7 +106,7 @@ func (c *binaryOpExpression) accept(visitor visitor) { c.rhs.accept(visitor) } -func (c *binaryOpExpression) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) (err error) { +func (c *binaryOpExpression) serialize(statement StatementType, out *SqlBuilder, options ...SerializeOption) (err error) { if c == nil { return errors.New("jet: binary Expression is nil") } @@ -120,10 +120,10 @@ func (c *binaryOpExpression) serialize(statement statementType, out *sqlBuilder, wrap := !contains(options, noWrap) if wrap { - out.writeString("(") + out.WriteString("(") } - if serializeOverride := out.dialect.serializeOverride(c.operator); serializeOverride != nil { + if serializeOverride := out.Dialect.SerializeOverride(c.operator); serializeOverride != nil { serializeOverrideFunc := serializeOverride(c.lhs, c.rhs) err = serializeOverrideFunc(statement, out, options...) @@ -133,7 +133,7 @@ func (c *binaryOpExpression) serialize(statement statementType, out *sqlBuilder, return err } - out.writeString(c.operator) + out.WriteString(c.operator) if err := c.rhs.serialize(statement, out); err != nil { return err @@ -141,7 +141,7 @@ func (c *binaryOpExpression) serialize(statement statementType, out *sqlBuilder, } if wrap { - out.writeString(")") + out.WriteString(")") } return err @@ -166,13 +166,13 @@ func (p *prefixOpExpression) accept(visitor visitor) { p.expression.accept(visitor) } -func (p *prefixOpExpression) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { +func (p *prefixOpExpression) serialize(statement StatementType, out *SqlBuilder, options ...SerializeOption) error { if p == nil { return errors.New("jet: Prefix Expression is nil") } - out.writeString("(") - out.writeString(p.operator) + out.WriteString("(") + out.WriteString(p.operator) if p.expression == nil { return errors.New("jet: nil prefix Expression") @@ -181,7 +181,7 @@ func (p *prefixOpExpression) serialize(statement statementType, out *sqlBuilder, return err } - out.writeString(")") + out.WriteString(")") return nil } @@ -205,7 +205,7 @@ func (p *postfixOpExpression) accept(visitor visitor) { p.expression.accept(visitor) } -func (p *postfixOpExpression) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { +func (p *postfixOpExpression) serialize(statement StatementType, out *SqlBuilder, options ...SerializeOption) error { if p == nil { return errors.New("jet: Postifx operator Expression is nil") } @@ -217,7 +217,7 @@ func (p *postfixOpExpression) serialize(statement statementType, out *sqlBuilder return err } - out.writeString(p.operator) + out.WriteString(p.operator) return nil } diff --git a/internal/jet/expression_test.go b/internal/jet/expression_test.go new file mode 100644 index 0000000..da0e033 --- /dev/null +++ b/internal/jet/expression_test.go @@ -0,0 +1,58 @@ +package jet + +import ( + "testing" +) + +func TestExpressionIS_NULL(t *testing.T) { + assertClauseSerialize(t, table2Col3.IS_NULL(), "table2.col3 IS NULL") + assertClauseSerialize(t, table2Col3.ADD(table2Col3).IS_NULL(), "(table2.col3 + table2.col3) IS NULL") + assertClauseSerializeErr(t, table2Col3.ADD(nil), "jet: nil rhs") +} + +func TestExpressionIS_NOT_NULL(t *testing.T) { + assertClauseSerialize(t, table2Col3.IS_NOT_NULL(), "table2.col3 IS NOT NULL") + assertClauseSerialize(t, table2Col3.ADD(table2Col3).IS_NOT_NULL(), "(table2.col3 + table2.col3) IS NOT NULL") +} + +func TestExpressionIS_DISTINCT_FROM(t *testing.T) { + assertClauseSerialize(t, table2Col3.IS_DISTINCT_FROM(table2Col4), "(table2.col3 IS DISTINCT FROM table2.col4)") + assertClauseSerialize(t, table2Col3.ADD(table2Col3).IS_DISTINCT_FROM(Int(23)), "((table2.col3 + table2.col3) IS DISTINCT FROM $1)", int64(23)) +} + +func TestExpressionIS_NOT_DISTINCT_FROM(t *testing.T) { + assertClauseSerialize(t, table2Col3.IS_NOT_DISTINCT_FROM(table2Col4), "(table2.col3 IS NOT DISTINCT FROM table2.col4)") + assertClauseSerialize(t, table2Col3.ADD(table2Col3).IS_NOT_DISTINCT_FROM(Int(23)), "((table2.col3 + table2.col3) IS NOT DISTINCT FROM $1)", int64(23)) +} + +func TestIN(t *testing.T) { + + assertClauseSerialize(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)), + `(ROW($1, table1.col1) IN (( + SELECT table2.col3 AS "table2.col3", + table3.col1 AS "table3.col1" + FROM db.table2 +)))`, int64(12)) +} + +func TestNOT_IN(t *testing.T) { + + assertClauseSerialize(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)), + `(ROW($1, table1.col1) NOT IN (( + SELECT table2.col3 AS "table2.col3", + table3.col1 AS "table3.col1" + FROM db.table2 +)))`, int64(12)) +} diff --git a/float_expression.go b/internal/jet/float_expression.go similarity index 100% rename from float_expression.go rename to internal/jet/float_expression.go diff --git a/internal/jet/float_expression_test.go b/internal/jet/float_expression_test.go new file mode 100644 index 0000000..e3d3d86 --- /dev/null +++ b/internal/jet/float_expression_test.go @@ -0,0 +1,82 @@ +package jet + +import ( + "testing" +) + +func TestFloatExpressionEQ(t *testing.T) { + assertClauseSerialize(t, table1ColFloat.EQ(table2ColFloat), "(table1.col_float = table2.col_float)") + assertClauseSerialize(t, table1ColFloat.EQ(Float(2.11)), "(table1.col_float = $1)", float64(2.11)) +} + +func TestFloatExpressionNOT_EQ(t *testing.T) { + assertClauseSerialize(t, table1ColFloat.NOT_EQ(table2ColFloat), "(table1.col_float != table2.col_float)") + assertClauseSerialize(t, table1ColFloat.NOT_EQ(Float(2.11)), "(table1.col_float != $1)", float64(2.11)) +} + +func TestFloatExpressionIS_DISTINCT_FROM(t *testing.T) { + assertClauseSerialize(t, table1ColFloat.IS_DISTINCT_FROM(table2ColFloat), "(table1.col_float IS DISTINCT FROM table2.col_float)") + assertClauseSerialize(t, table1ColFloat.IS_DISTINCT_FROM(Float(2.11)), "(table1.col_float IS DISTINCT FROM $1)", float64(2.11)) +} + +func TestFloatExpressionIS_NOT_DISTINCT_FROM(t *testing.T) { + assertClauseSerialize(t, table1ColFloat.IS_NOT_DISTINCT_FROM(table2ColFloat), "(table1.col_float IS NOT DISTINCT FROM table2.col_float)") + assertClauseSerialize(t, table1ColFloat.IS_NOT_DISTINCT_FROM(Float(2.11)), "(table1.col_float IS NOT DISTINCT FROM $1)", float64(2.11)) +} + +func TestFloatExpressionGT(t *testing.T) { + assertClauseSerialize(t, table1ColFloat.GT(table2ColFloat), "(table1.col_float > table2.col_float)") + assertClauseSerialize(t, table1ColFloat.GT(Float(2.11)), "(table1.col_float > $1)", float64(2.11)) +} + +func TestFloatExpressionGT_EQ(t *testing.T) { + assertClauseSerialize(t, table1ColFloat.GT_EQ(table2ColFloat), "(table1.col_float >= table2.col_float)") + assertClauseSerialize(t, table1ColFloat.GT_EQ(Float(2.11)), "(table1.col_float >= $1)", float64(2.11)) +} + +func TestFloatExpressionLT(t *testing.T) { + assertClauseSerialize(t, table1ColFloat.LT(table2ColFloat), "(table1.col_float < table2.col_float)") + assertClauseSerialize(t, table1ColFloat.LT(Float(2.11)), "(table1.col_float < $1)", float64(2.11)) +} + +func TestFloatExpressionLT_EQ(t *testing.T) { + assertClauseSerialize(t, table1ColFloat.LT_EQ(table2ColFloat), "(table1.col_float <= table2.col_float)") + assertClauseSerialize(t, table1ColFloat.LT_EQ(Float(2.11)), "(table1.col_float <= $1)", float64(2.11)) +} + +func TestFloatExpressionADD(t *testing.T) { + assertClauseSerialize(t, table1ColFloat.ADD(table2ColFloat), "(table1.col_float + table2.col_float)") + assertClauseSerialize(t, table1ColFloat.ADD(Float(2.11)), "(table1.col_float + $1)", float64(2.11)) +} + +func TestFloatExpressionSUB(t *testing.T) { + assertClauseSerialize(t, table1ColFloat.SUB(table2ColFloat), "(table1.col_float - table2.col_float)") + assertClauseSerialize(t, table1ColFloat.SUB(Float(2.11)), "(table1.col_float - $1)", float64(2.11)) +} + +func TestFloatExpressionMUL(t *testing.T) { + assertClauseSerialize(t, table1ColFloat.MUL(table2ColFloat), "(table1.col_float * table2.col_float)") + assertClauseSerialize(t, table1ColFloat.MUL(Float(2.11)), "(table1.col_float * $1)", float64(2.11)) +} + +func TestFloatExpressionDIV(t *testing.T) { + assertClauseSerialize(t, table1ColFloat.DIV(table2ColFloat), "(table1.col_float / table2.col_float)") + assertClauseSerialize(t, table1ColFloat.DIV(Float(2.11)), "(table1.col_float / $1)", float64(2.11)) +} + +func TestFloatExpressionMOD(t *testing.T) { + assertClauseSerialize(t, table1ColFloat.MOD(table2ColFloat), "(table1.col_float % table2.col_float)") + assertClauseSerialize(t, table1ColFloat.MOD(Float(2.11)), "(table1.col_float % $1)", float64(2.11)) +} + +func TestFloatExpressionPOW(t *testing.T) { + assertClauseSerialize(t, table1ColFloat.POW(table2ColFloat), "POW(table1.col_float, table2.col_float)") + assertClauseSerialize(t, table1ColFloat.POW(Float(2.11)), "POW(table1.col_float, $1)", float64(2.11)) +} + +func TestFloatExp(t *testing.T) { + assertClauseSerialize(t, FloatExp(table1ColInt), "table1.col_int") + assertClauseSerialize(t, FloatExp(table1ColInt.ADD(table3ColInt)), "(table1.col_int + table3.col_int)") + assertClauseSerialize(t, FloatExp(table1ColInt.ADD(table3ColInt)).ADD(Float(11.11)), + "((table1.col_int + table3.col_int) + $1)", float64(11.11)) +} diff --git a/func_expression.go b/internal/jet/func_expression.go similarity index 99% rename from func_expression.go rename to internal/jet/func_expression.go index 3b3965d..d8e269a 100644 --- a/func_expression.go +++ b/internal/jet/func_expression.go @@ -501,7 +501,7 @@ func (f *funcExpressionImpl) accept(visitor visitor) { } } -func (f *funcExpressionImpl) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { +func (f *funcExpressionImpl) serialize(statement StatementType, out *SqlBuilder, options ...SerializeOption) error { if f == nil { return errors.New("jet: Function expressions is nil. ") } @@ -509,9 +509,9 @@ func (f *funcExpressionImpl) serialize(statement statementType, out *sqlBuilder, addBrackets := !f.noBrackets || len(f.expressions) > 0 if addBrackets { - out.writeString(f.name + "(") + out.WriteString(f.name + "(") } else { - out.writeString(f.name) + out.WriteString(f.name) } err := serializeExpressionList(statement, f.expressions, ", ", out) @@ -520,7 +520,7 @@ func (f *funcExpressionImpl) serialize(statement statementType, out *sqlBuilder, } if addBrackets { - out.writeString(")") + out.WriteString(")") } return nil diff --git a/internal/jet/func_expression_test.go b/internal/jet/func_expression_test.go new file mode 100644 index 0000000..fa4a0a5 --- /dev/null +++ b/internal/jet/func_expression_test.go @@ -0,0 +1,162 @@ +package jet + +import ( + "testing" +) + +func TestFuncAVG(t *testing.T) { + assertClauseSerialize(t, AVG(table1ColFloat), "AVG(table1.col_float)") + assertClauseSerialize(t, AVG(table1ColInt), "AVG(table1.col_int)") +} + +func TestFuncBIT_AND(t *testing.T) { + assertClauseSerialize(t, BIT_AND(table1ColInt), "BIT_AND(table1.col_int)") +} + +func TestFuncBIT_OR(t *testing.T) { + assertClauseSerialize(t, BIT_OR(table1ColInt), "BIT_OR(table1.col_int)") +} + +func TestFuncBOOL_AND(t *testing.T) { + assertClauseSerialize(t, BOOL_AND(table1ColBool), "BOOL_AND(table1.col_bool)") +} + +func TestFuncBOOL_OR(t *testing.T) { + assertClauseSerialize(t, BOOL_OR(table1ColBool), "BOOL_OR(table1.col_bool)") +} + +func TestFuncEVERY(t *testing.T) { + assertClauseSerialize(t, EVERY(table1ColBool), "EVERY(table1.col_bool)") +} + +func TestFuncMIN(t *testing.T) { + t.Run("float", func(t *testing.T) { + assertClauseSerialize(t, MINf(table1ColFloat), "MIN(table1.col_float)") + }) + + t.Run("integer", func(t *testing.T) { + assertClauseSerialize(t, MINi(table1ColInt), "MIN(table1.col_int)") + }) +} + +func TestFuncMAX(t *testing.T) { + t.Run("float", func(t *testing.T) { + assertClauseSerialize(t, MAXf(table1ColFloat), "MAX(table1.col_float)") + assertClauseSerialize(t, MAXf(Float(11.2222)), "MAX($1)", float64(11.2222)) + }) + + t.Run("integer", func(t *testing.T) { + assertClauseSerialize(t, MAXi(table1ColInt), "MAX(table1.col_int)") + assertClauseSerialize(t, MAXi(Int(11)), "MAX($1)", int64(11)) + }) +} + +func TestFuncSUM(t *testing.T) { + t.Run("float", func(t *testing.T) { + assertClauseSerialize(t, SUMf(table1ColFloat), "SUM(table1.col_float)") + assertClauseSerialize(t, SUMf(Float(11.2222)), "SUM($1)", float64(11.2222)) + }) + + t.Run("integer", func(t *testing.T) { + assertClauseSerialize(t, SUMi(table1ColInt), "SUM(table1.col_int)") + assertClauseSerialize(t, SUMi(Int(11)), "SUM($1)", int64(11)) + }) +} + +func TestFuncCOUNT(t *testing.T) { + assertClauseSerialize(t, COUNT(STAR), "COUNT(*)") + assertClauseSerialize(t, COUNT(table1ColFloat), "COUNT(table1.col_float)") + assertClauseSerialize(t, COUNT(Float(11.2222)), "COUNT($1)", float64(11.2222)) +} + +func TestFuncABS(t *testing.T) { + t.Run("float", func(t *testing.T) { + assertClauseSerialize(t, ABSf(table1ColFloat), "ABS(table1.col_float)") + assertClauseSerialize(t, ABSf(Float(11.2222)), "ABS($1)", float64(11.2222)) + }) + + t.Run("integer", func(t *testing.T) { + assertClauseSerialize(t, ABSi(table1ColInt), "ABS(table1.col_int)") + assertClauseSerialize(t, ABSi(Int(11)), "ABS($1)", int64(11)) + }) +} + +func TestFuncSQRT(t *testing.T) { + assertClauseSerialize(t, SQRT(table1ColFloat), "SQRT(table1.col_float)") + assertClauseSerialize(t, SQRT(Float(11.2222)), "SQRT($1)", float64(11.2222)) + assertClauseSerialize(t, SQRT(table1ColInt), "SQRT(table1.col_int)") + assertClauseSerialize(t, SQRT(Int(11)), "SQRT($1)", int64(11)) +} + +func TestFuncCBRT(t *testing.T) { + assertClauseSerialize(t, CBRT(table1ColFloat), "CBRT(table1.col_float)") + assertClauseSerialize(t, CBRT(Float(11.2222)), "CBRT($1)", float64(11.2222)) + assertClauseSerialize(t, CBRT(table1ColInt), "CBRT(table1.col_int)") + assertClauseSerialize(t, CBRT(Int(11)), "CBRT($1)", int64(11)) +} + +func TestFuncCEIL(t *testing.T) { + assertClauseSerialize(t, CEIL(table1ColFloat), "CEIL(table1.col_float)") + assertClauseSerialize(t, CEIL(Float(11.2222)), "CEIL($1)", float64(11.2222)) +} + +func TestFuncFLOOR(t *testing.T) { + assertClauseSerialize(t, FLOOR(table1ColFloat), "FLOOR(table1.col_float)") + assertClauseSerialize(t, FLOOR(Float(11.2222)), "FLOOR($1)", float64(11.2222)) +} + +func TestFuncROUND(t *testing.T) { + assertClauseSerialize(t, ROUND(table1ColFloat), "ROUND(table1.col_float)") + assertClauseSerialize(t, ROUND(Float(11.2222)), "ROUND($1)", float64(11.2222)) + + assertClauseSerialize(t, ROUND(table1ColFloat, Int(2)), "ROUND(table1.col_float, $1)", int64(2)) + assertClauseSerialize(t, ROUND(Float(11.2222), Int(1)), "ROUND($1, $2)", float64(11.2222), int64(1)) +} + +func TestFuncSIGN(t *testing.T) { + assertClauseSerialize(t, SIGN(table1ColFloat), "SIGN(table1.col_float)") + assertClauseSerialize(t, SIGN(Float(11.2222)), "SIGN($1)", float64(11.2222)) +} + +func TestFuncTRUNC(t *testing.T) { + assertClauseSerialize(t, TRUNC(table1ColFloat), "TRUNC(table1.col_float)") + assertClauseSerialize(t, TRUNC(Float(11.2222)), "TRUNC($1)", float64(11.2222)) + + assertClauseSerialize(t, TRUNC(table1ColFloat, Int(2)), "TRUNC(table1.col_float, $1)", int64(2)) + assertClauseSerialize(t, TRUNC(Float(11.2222), Int(1)), "TRUNC($1, $2)", float64(11.2222), int64(1)) +} + +func TestFuncLN(t *testing.T) { + assertClauseSerialize(t, LN(table1ColFloat), "LN(table1.col_float)") + assertClauseSerialize(t, LN(Float(11.2222)), "LN($1)", float64(11.2222)) +} + +func TestFuncLOG(t *testing.T) { + assertClauseSerialize(t, LOG(table1ColFloat), "LOG(table1.col_float)") + assertClauseSerialize(t, LOG(Float(11.2222)), "LOG($1)", float64(11.2222)) +} + +func TestFuncCOALESCE(t *testing.T) { + assertClauseSerialize(t, COALESCE(table1ColFloat), "COALESCE(table1.col_float)") + assertClauseSerialize(t, COALESCE(Float(11.2222), NULL, String("str")), "COALESCE($1, NULL, $2)", float64(11.2222), "str") +} + +func TestFuncNULLIF(t *testing.T) { + assertClauseSerialize(t, NULLIF(table1ColFloat, table2ColInt), "NULLIF(table1.col_float, table2.col_int)") + assertClauseSerialize(t, NULLIF(Float(11.2222), NULL), "NULLIF($1, NULL)", float64(11.2222)) +} + +func TestFuncGREATEST(t *testing.T) { + assertClauseSerialize(t, GREATEST(table1ColFloat), "GREATEST(table1.col_float)") + assertClauseSerialize(t, GREATEST(Float(11.2222), NULL, String("str")), "GREATEST($1, NULL, $2)", float64(11.2222), "str") +} + +func TestFuncLEAST(t *testing.T) { + assertClauseSerialize(t, LEAST(table1ColFloat), "LEAST(table1.col_float)") + assertClauseSerialize(t, LEAST(Float(11.2222), NULL, String("str")), "LEAST($1, NULL, $2)", float64(11.2222), "str") +} + +func TestTO_ASCII(t *testing.T) { + assertClauseSerialize(t, TO_ASCII(String("Karel")), `TO_ASCII($1)`, "Karel") + assertClauseSerialize(t, TO_ASCII(String("Karel")), `TO_ASCII($1)`, "Karel") +} diff --git a/internal/jet/group_by_clause.go b/internal/jet/group_by_clause.go new file mode 100644 index 0000000..a8602b8 --- /dev/null +++ b/internal/jet/group_by_clause.go @@ -0,0 +1,5 @@ +package jet + +type groupByClause interface { + serializeForGroupBy(statement StatementType, out *SqlBuilder) error +} diff --git a/insert_statement.go b/internal/jet/insert_statement.go similarity index 79% rename from insert_statement.go rename to internal/jet/insert_statement.go index 2a49543..8dae633 100644 --- a/insert_statement.go +++ b/internal/jet/insert_statement.go @@ -22,10 +22,10 @@ type InsertStatement interface { QUERY(selectStatement SelectStatement) InsertStatement - RETURNING(projections ...projection) InsertStatement + RETURNING(projections ...Projection) InsertStatement } -func newInsertStatement(t WritableTable, columns []column) InsertStatement { +func newInsertStatement(t WritableTable, columns []IColumn) InsertStatement { return &insertStatementImpl{ table: t, columns: columns, @@ -34,10 +34,10 @@ func newInsertStatement(t WritableTable, columns []column) InsertStatement { type insertStatementImpl struct { table WritableTable - columns []column - rows [][]clause + columns []IColumn + rows [][]Clause query SelectStatement - returning []projection + returning []Projection } func (i *insertStatementImpl) VALUES(value interface{}, values ...interface{}) InsertStatement { @@ -55,7 +55,7 @@ func (i *insertStatementImpl) MODELS(data interface{}) InsertStatement { return i } -func (i *insertStatementImpl) RETURNING(projections ...projection) InsertStatement { +func (i *insertStatementImpl) RETURNING(projections ...Projection) InsertStatement { i.returning = projections return i } @@ -65,7 +65,7 @@ func (i *insertStatementImpl) QUERY(selectStatement SelectStatement) InsertState return i } -func (i *insertStatementImpl) getColumns() []column { +func (i *insertStatementImpl) getColumns() []IColumn { if len(i.columns) > 0 { return i.columns } @@ -84,33 +84,33 @@ func (i *insertStatementImpl) DebugSql(dialect ...Dialect) (query string, err er } func (i *insertStatementImpl) Sql(dialect ...Dialect) (query string, args []interface{}, err error) { - out := &sqlBuilder{ - dialect: detectDialect(i, dialect...), + out := &SqlBuilder{ + Dialect: detectDialect(i, dialect...), } out.newLine() - out.writeString("INSERT INTO") + out.WriteString("INSERT INTO") if utils.IsNil(i.table) { return "", nil, errors.New("jet: table is nil") } - err = i.table.serialize(insertStatement, out) + err = i.table.serialize(InsertStatementType, out) if err != nil { return } if len(i.columns) > 0 { - out.writeString("(") + out.WriteString("(") - err = serializeColumnNames(i.columns, out) + err = SerializeColumnNames(i.columns, out) if err != nil { return } - out.writeString(")") + out.WriteString(")") } if len(i.rows) == 0 && i.query == nil { @@ -122,18 +122,18 @@ func (i *insertStatementImpl) Sql(dialect ...Dialect) (query string, args []inte } if len(i.rows) > 0 { - out.writeString("VALUES") + out.WriteString("VALUES") for rowIndex, row := range i.rows { if rowIndex > 0 { - out.writeString(",") + out.WriteString(",") } out.increaseIdent() out.newLine() - out.writeString("(") + out.WriteString("(") - err = serializeClauseList(insertStatement, row, out) + err = SerializeClauseList(InsertStatementType, row, out) if err != nil { return "", nil, err @@ -145,14 +145,14 @@ func (i *insertStatementImpl) Sql(dialect ...Dialect) (query string, args []inte } if i.query != nil { - err = i.query.serialize(insertStatement, out) + err = i.query.serialize(InsertStatementType, out) if err != nil { return } } - if err = out.writeReturning(insertStatement, i.returning); err != nil { + if err = out.writeReturning(InsertStatementType, i.returning); err != nil { return } diff --git a/insert_statement_test.go b/internal/jet/insert_statement_test.go similarity index 98% rename from insert_statement_test.go rename to internal/jet/insert_statement_test.go index 2c724f5..414d323 100644 --- a/insert_statement_test.go +++ b/internal/jet/insert_statement_test.go @@ -26,7 +26,7 @@ INSERT INTO db.table1 (col1) VALUES } func TestInsertWithColumnList(t *testing.T) { - columnList := ColumnList{table3ColInt, table3StrCol} + columnList := ColumnList(table3ColInt, table3StrCol) assertStatement(t, table3.INSERT(columnList).VALUES(1, 3), ` INSERT INTO db.table3 (col_int, col2) VALUES diff --git a/integer_expression.go b/internal/jet/integer_expression.go similarity index 100% rename from integer_expression.go rename to internal/jet/integer_expression.go diff --git a/internal/jet/integer_expression_test.go b/internal/jet/integer_expression_test.go new file mode 100644 index 0000000..c184984 --- /dev/null +++ b/internal/jet/integer_expression_test.go @@ -0,0 +1,106 @@ +package jet + +import ( + "testing" +) + +func TestIntegerExpressionEQ(t *testing.T) { + assertClauseSerialize(t, table1ColInt.EQ(table2ColInt), "(table1.col_int = table2.col_int)") + assertClauseSerialize(t, table1ColInt.EQ(Int(11)), "(table1.col_int = $1)", int64(11)) +} + +func TestIntegerExpressionNOT_EQ(t *testing.T) { + assertClauseSerialize(t, table1ColInt.NOT_EQ(table2ColInt), "(table1.col_int != table2.col_int)") + assertClauseSerialize(t, table1ColInt.NOT_EQ(Int(11)), "(table1.col_int != $1)", int64(11)) +} + +func TestIntegerExpressionGT(t *testing.T) { + assertClauseSerialize(t, table1ColInt.GT(table2ColInt), "(table1.col_int > table2.col_int)") + assertClauseSerialize(t, table1ColInt.GT(Int(11)), "(table1.col_int > $1)", int64(11)) +} + +func TestIntegerExpressionGT_EQ(t *testing.T) { + assertClauseSerialize(t, table1ColInt.GT_EQ(table2ColInt), "(table1.col_int >= table2.col_int)") + assertClauseSerialize(t, table1ColInt.GT_EQ(Int(11)), "(table1.col_int >= $1)", int64(11)) +} + +func TestIntegerExpressionLT(t *testing.T) { + assertClauseSerialize(t, table1ColInt.LT(table2ColInt), "(table1.col_int < table2.col_int)") + assertClauseSerialize(t, table1ColInt.LT(Int(11)), "(table1.col_int < $1)", int64(11)) +} + +func TestIntegerExpressionLT_EQ(t *testing.T) { + assertClauseSerialize(t, table1ColInt.LT_EQ(table2ColInt), "(table1.col_int <= table2.col_int)") + assertClauseSerialize(t, table1ColInt.LT_EQ(Int(11)), "(table1.col_int <= $1)", int64(11)) +} + +func TestIntegerExpressionADD(t *testing.T) { + assertClauseSerialize(t, table1ColInt.ADD(table2ColInt), "(table1.col_int + table2.col_int)") + assertClauseSerialize(t, table1ColInt.ADD(Int(11)), "(table1.col_int + $1)", int64(11)) +} + +func TestIntegerExpressionSUB(t *testing.T) { + assertClauseSerialize(t, table1ColInt.SUB(table2ColInt), "(table1.col_int - table2.col_int)") + assertClauseSerialize(t, table1ColInt.SUB(Int(11)), "(table1.col_int - $1)", int64(11)) +} + +func TestIntegerExpressionMUL(t *testing.T) { + assertClauseSerialize(t, table1ColInt.MUL(table2ColInt), "(table1.col_int * table2.col_int)") + assertClauseSerialize(t, table1ColInt.MUL(Int(11)), "(table1.col_int * $1)", int64(11)) +} + +func TestIntegerExpressionDIV(t *testing.T) { + assertClauseSerialize(t, table1ColInt.DIV(table2ColInt), "(table1.col_int / table2.col_int)") + assertClauseSerialize(t, table1ColInt.DIV(Int(11)), "(table1.col_int / $1)", int64(11)) +} + +func TestIntExpressionMOD(t *testing.T) { + assertClauseSerialize(t, table1ColInt.MOD(table2ColInt), "(table1.col_int % table2.col_int)") + assertClauseSerialize(t, table1ColInt.MOD(Int(11)), "(table1.col_int % $1)", int64(11)) +} + +func TestIntExpressionPOW(t *testing.T) { + assertClauseSerialize(t, table1ColInt.POW(table2ColInt), "POW(table1.col_int, table2.col_int)") + assertClauseSerialize(t, table1ColInt.POW(Int(11)), "POW(table1.col_int, $1)", int64(11)) +} + +func TestIntExpressionBIT_NOT(t *testing.T) { + assertClauseSerialize(t, BIT_NOT(table2ColInt), "(~ table2.col_int)") + assertClauseSerialize(t, BIT_NOT(Int(11)), "(~ $1)", int64(11)) +} + +func TestIntExpressionBIT_AND(t *testing.T) { + assertClauseSerialize(t, table1ColInt.BIT_AND(table2ColInt), "(table1.col_int & table2.col_int)") + assertClauseSerialize(t, table1ColInt.BIT_AND(Int(11)), "(table1.col_int & $1)", int64(11)) +} + +func TestIntExpressionBIT_OR(t *testing.T) { + assertClauseSerialize(t, table1ColInt.BIT_OR(table2ColInt), "(table1.col_int | table2.col_int)") + assertClauseSerialize(t, table1ColInt.BIT_OR(Int(11)), "(table1.col_int | $1)", int64(11)) +} + +func TestIntExpressionBIT_XOR(t *testing.T) { + assertClauseSerialize(t, table1ColInt.BIT_XOR(table2ColInt), "(table1.col_int # table2.col_int)") + assertClauseSerialize(t, table1ColInt.BIT_XOR(Int(11)), "(table1.col_int # $1)", int64(11)) +} + +func TestIntExpressionBIT_SHIFT_LEFT(t *testing.T) { + assertClauseSerialize(t, table1ColInt.BIT_SHIFT_LEFT(table2ColInt), "(table1.col_int << table2.col_int)") + assertClauseSerialize(t, table1ColInt.BIT_SHIFT_LEFT(Int(11)), "(table1.col_int << $1)", int64(11)) +} + +func TestIntExpressionBIT_SHIFT_RIGHT(t *testing.T) { + assertClauseSerialize(t, table1ColInt.BIT_SHIFT_RIGHT(table2ColInt), "(table1.col_int >> table2.col_int)") + assertClauseSerialize(t, table1ColInt.BIT_SHIFT_RIGHT(Int(11)), "(table1.col_int >> $1)", int64(11)) +} + +func TestIntExpressionIntExp(t *testing.T) { + assertClauseSerialize(t, IntExp(table1ColFloat), "table1.col_float") + assertClauseSerialize(t, IntExp(table1ColFloat.ADD(table2ColFloat)).ADD(Int(11)), + "((table1.col_float + table2.col_float) + $1)", int64(11)) +} + +func TestIntExpression_MINUSi(t *testing.T) { + assertClauseSerialize(t, MINUSi(table2ColInt), "(- table2.col_int)") + assertClauseSerialize(t, MINUSi(Int(3)), "(- $1)", int64(3)) +} diff --git a/keyword.go b/internal/jet/keyword.go similarity index 66% rename from keyword.go rename to internal/jet/keyword.go index 988ae0a..be04d02 100644 --- a/keyword.go +++ b/internal/jet/keyword.go @@ -14,8 +14,8 @@ var ( type keywordClause string -func (k keywordClause) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { - out.writeString(string(k)) +func (k keywordClause) serialize(statement StatementType, out *SqlBuilder, options ...SerializeOption) error { + out.WriteString(string(k)) return nil } diff --git a/literal_expression.go b/internal/jet/literal_expression.go similarity index 86% rename from literal_expression.go rename to internal/jet/literal_expression.go index 7628d94..ba5b692 100644 --- a/literal_expression.go +++ b/internal/jet/literal_expression.go @@ -30,7 +30,7 @@ func constLiteral(value interface{}) *literalExpression { return exp } -func (l literalExpression) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { +func (l literalExpression) serialize(statement StatementType, out *SqlBuilder, options ...SerializeOption) error { if l.constant { out.insertConstantArgument(l.value) } else { @@ -110,8 +110,8 @@ func newNullLiteral() Expression { return nullExpression } -func (n *nullLiteral) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { - out.writeString("NULL") +func (n *nullLiteral) serialize(statement StatementType, out *SqlBuilder, options ...SerializeOption) error { + out.WriteString("NULL") return nil } @@ -129,8 +129,8 @@ func newStarLiteral() Expression { return starExpression } -func (n *starLiteral) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { - out.writeString("*") +func (n *starLiteral) serialize(statement StatementType, out *SqlBuilder, options ...SerializeOption) error { + out.WriteString("*") return nil } @@ -147,10 +147,10 @@ func (n *wrap) accept(visitor visitor) { } } -func (n *wrap) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { - out.writeString("(") +func (n *wrap) serialize(statement StatementType, out *SqlBuilder, options ...SerializeOption) error { + out.WriteString("(") err := serializeExpressionList(statement, n.expressions, ", ", out) - out.writeString(")") + out.WriteString(")") return err } @@ -171,8 +171,8 @@ type rawExpression struct { raw string } -func (n *rawExpression) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { - out.writeString(n.raw) +func (n *rawExpression) serialize(statement StatementType, out *SqlBuilder, options ...SerializeOption) error { + out.WriteString(n.raw) return nil } diff --git a/internal/jet/literal_expression_test.go b/internal/jet/literal_expression_test.go new file mode 100644 index 0000000..4752ce2 --- /dev/null +++ b/internal/jet/literal_expression_test.go @@ -0,0 +1,7 @@ +package jet + +import "testing" + +func TestRawExpression(t *testing.T) { + assertClauseSerialize(t, RAW("current_database()"), "current_database()") +} diff --git a/lock_statement.go b/internal/jet/lock_statement.go similarity index 69% rename from lock_statement.go rename to internal/jet/lock_statement.go index ba7105e..397d5f5 100644 --- a/lock_statement.go +++ b/internal/jet/lock_statement.go @@ -10,29 +10,17 @@ import ( // TableLockMode is a type of possible SQL table lock type TableLockMode string -// Lock types for LockStatement. -const ( - LOCK_ACCESS_SHARE = "ACCESS SHARE" - LOCK_ROW_SHARE = "ROW SHARE" - LOCK_ROW_EXCLUSIVE = "ROW EXCLUSIVE" - LOCK_SHARE_UPDATE_EXCLUSIVE = "SHARE UPDATE EXCLUSIVE" - LOCK_SHARE = "SHARE" - LOCK_SHARE_ROW_EXCLUSIVE = "SHARE ROW EXCLUSIVE" - LOCK_EXCLUSIVE = "EXCLUSIVE" - LOCK_ACCESS_EXCLUSIVE = "ACCESS EXCLUSIVE" -) - // LockStatement interface for SQL LOCK statement type LockStatement interface { Statement - IN(lockMode TableLockMode) LockStatement + IN(lockMode string) LockStatement NOWAIT() LockStatement } type lockStatementImpl struct { tables []WritableTable - lockMode TableLockMode + lockMode string nowait bool } @@ -43,7 +31,7 @@ func LOCK(tables ...WritableTable) LockStatement { } } -func (l *lockStatementImpl) IN(lockMode TableLockMode) LockStatement { +func (l *lockStatementImpl) IN(lockMode string) LockStatement { l.lockMode = lockMode return l } @@ -74,19 +62,19 @@ func (l *lockStatementImpl) Sql(dialect ...Dialect) (query string, args []interf return "", nil, errors.New("jet: There is no table selected to be locked") } - out := &sqlBuilder{ - dialect: detectDialect(l, dialect...), + out := &SqlBuilder{ + Dialect: detectDialect(l, dialect...), } out.newLine() - out.writeString("LOCK TABLE") + out.WriteString("LOCK TABLE") for i, table := range l.tables { if i > 0 { - out.writeString(", ") + out.WriteString(", ") } - err := table.serialize(lockStatement, out) + err := table.serialize(LockStatementType, out) if err != nil { return "", nil, err @@ -94,13 +82,13 @@ func (l *lockStatementImpl) Sql(dialect ...Dialect) (query string, args []interf } if l.lockMode != "" { - out.writeString("IN") - out.writeString(string(l.lockMode)) - out.writeString("MODE") + out.WriteString("IN") + out.WriteString(string(l.lockMode)) + out.WriteString("MODE") } if l.nowait { - out.writeString("NOWAIT") + out.WriteString("NOWAIT") } query, args = out.finalize() diff --git a/numeric_expression.go b/internal/jet/numeric_expression.go similarity index 100% rename from numeric_expression.go rename to internal/jet/numeric_expression.go diff --git a/operators.go b/internal/jet/operators.go similarity index 94% rename from operators.go rename to internal/jet/operators.go index 4fe94b7..d233a2b 100644 --- a/operators.go +++ b/internal/jet/operators.go @@ -138,12 +138,12 @@ func (c *caseOperatorImpl) accept(visitor visitor) { } } -func (c *caseOperatorImpl) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { +func (c *caseOperatorImpl) serialize(statement StatementType, out *SqlBuilder, options ...SerializeOption) error { if c == nil { return errors.New("jet: Case Expression is nil. ") } - out.writeString("(CASE") + out.WriteString("(CASE") if c.expression != nil { err := c.expression.serialize(statement, out) @@ -162,14 +162,14 @@ func (c *caseOperatorImpl) serialize(statement statementType, out *sqlBuilder, o } for i, when := range c.when { - out.writeString("WHEN") + out.WriteString("WHEN") err := when.serialize(statement, out, noWrap) if err != nil { return err } - out.writeString("THEN") + out.WriteString("THEN") err = c.then[i].serialize(statement, out, noWrap) if err != nil { @@ -178,7 +178,7 @@ func (c *caseOperatorImpl) serialize(statement statementType, out *sqlBuilder, o } if c.els != nil { - out.writeString("ELSE") + out.WriteString("ELSE") err := c.els.serialize(statement, out, noWrap) if err != nil { @@ -186,7 +186,7 @@ func (c *caseOperatorImpl) serialize(statement statementType, out *sqlBuilder, o } } - out.writeString("END)") + out.WriteString("END)") return nil } diff --git a/operators_test.go b/internal/jet/operators_test.go similarity index 53% rename from operators_test.go rename to internal/jet/operators_test.go index 4f517d6..86c7801 100644 --- a/operators_test.go +++ b/internal/jet/operators_test.go @@ -5,10 +5,10 @@ import "testing" func TestOperatorNOT(t *testing.T) { notExpression := NOT(Int(2).EQ(Int(1))) - AssertPostgreClauseSerialize(t, NOT(table1ColBool), "(NOT table1.col_bool)") - AssertPostgreClauseSerialize(t, notExpression, "(NOT ($1 = $2))", int64(2), int64(1)) + assertClauseSerialize(t, NOT(table1ColBool), "(NOT table1.col_bool)") + assertClauseSerialize(t, notExpression, "(NOT ($1 = $2))", int64(2), int64(1)) assertProjectionSerialize(t, notExpression.AS("alias_not_expression"), `(NOT ($1 = $2)) AS "alias_not_expression"`, int64(2), int64(1)) - AssertPostgreClauseSerialize(t, notExpression.AND(Int(4).EQ(Int(5))), `((NOT ($1 = $2)) AND ($3 = $4))`, int64(2), int64(1), int64(4), int64(5)) + assertClauseSerialize(t, notExpression.AND(Int(4).EQ(Int(5))), `((NOT ($1 = $2)) AND ($3 = $4))`, int64(2), int64(1), int64(4), int64(5)) } func TestCase1(t *testing.T) { @@ -16,7 +16,7 @@ func TestCase1(t *testing.T) { WHEN(table3Col1.EQ(Int(1))).THEN(table3Col1.ADD(Int(1))). WHEN(table3Col1.EQ(Int(2))).THEN(table3Col1.ADD(Int(2))) - AssertPostgreClauseSerialize(t, query, `(CASE WHEN table3.col1 = $1 THEN table3.col1 + $2 WHEN table3.col1 = $3 THEN table3.col1 + $4 END)`, + assertClauseSerialize(t, query, `(CASE WHEN table3.col1 = $1 THEN table3.col1 + $2 WHEN table3.col1 = $3 THEN table3.col1 + $4 END)`, int64(1), int64(1), int64(2), int64(2)) } @@ -26,6 +26,6 @@ func TestCase2(t *testing.T) { WHEN(Int(2)).THEN(table3Col1.ADD(Int(2))). ELSE(Int(0)) - AssertPostgreClauseSerialize(t, query, `(CASE table3.col1 WHEN $1 THEN table3.col1 + $2 WHEN $3 THEN table3.col1 + $4 ELSE $5 END)`, + assertClauseSerialize(t, query, `(CASE table3.col1 WHEN $1 THEN table3.col1 + $2 WHEN $3 THEN table3.col1 + $4 ELSE $5 END)`, int64(1), int64(1), int64(2), int64(2), int64(0)) } diff --git a/order_by_clause.go b/internal/jet/order_by_clause.go similarity index 70% rename from order_by_clause.go rename to internal/jet/order_by_clause.go index b09d8c9..32fdb2e 100644 --- a/order_by_clause.go +++ b/internal/jet/order_by_clause.go @@ -4,7 +4,7 @@ import "errors" // OrderByClause type orderByClause interface { - serializeForOrderBy(statement statementType, out *sqlBuilder) error + serializeForOrderBy(statement StatementType, out *SqlBuilder) error } type orderByClauseImpl struct { @@ -12,7 +12,7 @@ type orderByClauseImpl struct { ascent bool } -func (o *orderByClauseImpl) serializeForOrderBy(statement statementType, out *sqlBuilder) error { +func (o *orderByClauseImpl) serializeForOrderBy(statement StatementType, out *SqlBuilder) error { if o.expression == nil { return errors.New("jet: nil orderBy by clause") } @@ -22,9 +22,9 @@ func (o *orderByClauseImpl) serializeForOrderBy(statement statementType, out *sq } if o.ascent { - out.writeString("ASC") + out.WriteString("ASC") } else { - out.writeString("DESC") + out.WriteString("DESC") } return nil diff --git a/internal/jet/projection.go b/internal/jet/projection.go new file mode 100644 index 0000000..0b5505c --- /dev/null +++ b/internal/jet/projection.go @@ -0,0 +1,33 @@ +package jet + +type Projection interface { + serializeForProjection(statement StatementType, out *SqlBuilder) error + fromImpl(subQuery SelectTable) Projection +} + +func SerializeForProjection(projection Projection, statementType StatementType, out *SqlBuilder) error { + return projection.serializeForProjection(statementType, out) +} + +// ProjectionList is a redefined type, so that ProjectionList can be used as a Projection. +type ProjectionList []Projection + +func (cl ProjectionList) fromImpl(subQuery SelectTable) Projection { + newProjectionList := ProjectionList{} + + for _, projection := range cl { + newProjectionList = append(newProjectionList, projection.fromImpl(subQuery)) + } + + return newProjectionList +} + +func (cl ProjectionList) serializeForProjection(statement StatementType, out *SqlBuilder) error { + err := SerializeProjectionList(statement, cl, out) + + if err != nil { + return err + } + + return nil +} diff --git a/select_statement.go b/internal/jet/select_statement.go similarity index 81% rename from select_statement.go rename to internal/jet/select_statement.go index ad94c71..6923034 100644 --- a/select_statement.go +++ b/internal/jet/select_statement.go @@ -31,12 +31,12 @@ type SelectStatement interface { AsTable(alias string) SelectTable - projections() []projection + projections() []Projection } //SELECT creates new SelectStatement with list of projections -func SELECT(projection1 projection, projections ...projection) SelectStatement { - return newSelectStatement(nil, append([]projection{projection1}, projections...)) +func SELECT(projection1 Projection, projections ...Projection) SelectStatement { + return newSelectStatement(nil, append([]Projection{projection1}, projections...)) } type selectStatementImpl struct { @@ -45,7 +45,7 @@ type selectStatementImpl struct { table ReadableTable distinct bool - projectionList []projection + projectionList []Projection where BoolExpression groupBy []groupByClause having BoolExpression @@ -56,7 +56,7 @@ type selectStatementImpl struct { lockFor SelectLock } -func newSelectStatement(table ReadableTable, projections []projection) SelectStatement { +func newSelectStatement(table ReadableTable, projections []Projection) SelectStatement { newSelect := &selectStatementImpl{ table: table, projectionList: projections, @@ -144,15 +144,15 @@ func (s *selectStatementImpl) EXCEPT_ALL(rhs SelectStatement) SelectStatement { return EXCEPT_ALL(s.parent, rhs) } -func (s *selectStatementImpl) projections() []projection { +func (s *selectStatementImpl) projections() []Projection { return s.projectionList } -func (s *selectStatementImpl) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { +func (s *selectStatementImpl) serialize(statement StatementType, out *SqlBuilder, options ...SerializeOption) error { if s == nil { return errors.New("jet: Select expression is nil. ") } - out.writeString("(") + out.WriteString("(") out.increaseIdent() err := s.serializeImpl(out) @@ -163,41 +163,41 @@ func (s *selectStatementImpl) serialize(statement statementType, out *sqlBuilder } out.newLine() - out.writeString(")") + out.WriteString(")") return nil } -func (s *selectStatementImpl) serializeImpl(out *sqlBuilder) error { +func (s *selectStatementImpl) serializeImpl(out *SqlBuilder) error { if s == nil { return errors.New("jet: Select expression is nil. ") } out.newLine() - out.writeString("SELECT") + out.WriteString("SELECT") if s.distinct { - out.writeString("DISTINCT") + out.WriteString("DISTINCT") } if len(s.projectionList) == 0 { - return errors.New("jet: no column selected for projection") + return errors.New("jet: no column selected for Projection") } - err := out.writeProjections(selectStatement, s.projectionList) + err := out.writeProjections(SelectStatementType, s.projectionList) if err != nil { return err } if s.table != nil { - if err := out.writeFrom(selectStatement, s.table); err != nil { + if err := out.writeFrom(SelectStatementType, s.table); err != nil { return err } } if s.where != nil { - err := out.writeWhere(selectStatement, s.where) + err := out.writeWhere(SelectStatementType, s.where) if err != nil { return nil @@ -205,7 +205,7 @@ func (s *selectStatementImpl) serializeImpl(out *sqlBuilder) error { } if s.groupBy != nil && len(s.groupBy) > 0 { - err := out.writeGroupBy(selectStatement, s.groupBy) + err := out.writeGroupBy(SelectStatementType, s.groupBy) if err != nil { return err @@ -213,7 +213,7 @@ func (s *selectStatementImpl) serializeImpl(out *sqlBuilder) error { } if s.having != nil { - err := out.writeHaving(selectStatement, s.having) + err := out.writeHaving(SelectStatementType, s.having) if err != nil { return err @@ -221,7 +221,7 @@ func (s *selectStatementImpl) serializeImpl(out *sqlBuilder) error { } if s.orderBy != nil { - err := out.writeOrderBy(selectStatement, s.orderBy) + err := out.writeOrderBy(SelectStatementType, s.orderBy) if err != nil { return err @@ -230,20 +230,20 @@ func (s *selectStatementImpl) serializeImpl(out *sqlBuilder) error { if s.limit >= 0 { out.newLine() - out.writeString("LIMIT") + out.WriteString("LIMIT") out.insertParametrizedArgument(s.limit) } if s.offset >= 0 { out.newLine() - out.writeString("OFFSET") + out.WriteString("OFFSET") out.insertParametrizedArgument(s.offset) } if s.lockFor != nil { out.newLine() - out.writeString("FOR") - err := s.lockFor.serialize(selectStatement, out) + out.WriteString("FOR") + err := s.lockFor.serialize(SelectStatementType, out) if err != nil { return err @@ -271,8 +271,8 @@ func (s *selectStatementImpl) accept(visitor visitor) { func (s *selectStatementImpl) Sql(dialect ...Dialect) (query string, args []interface{}, err error) { - queryData := &sqlBuilder{ - dialect: detectDialect(s, dialect...), + queryData := &SqlBuilder{ + Dialect: detectDialect(s, dialect...), } err = s.serializeImpl(queryData) @@ -308,7 +308,7 @@ func (s *selectStatementImpl) ExecContext(context context.Context, db execution. // SelectLock is interface for SELECT statement locks type SelectLock interface { - clause + Clause NOWAIT() SelectLock SKIP_LOCKED() SelectLock @@ -339,15 +339,15 @@ func (s *selectLockImpl) SKIP_LOCKED() SelectLock { return s } -func (s *selectLockImpl) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { - out.writeString(s.lockStrength) +func (s *selectLockImpl) serialize(statement StatementType, out *SqlBuilder, options ...SerializeOption) error { + out.WriteString(s.lockStrength) if s.noWait { - out.writeString("NOWAIT") + out.WriteString("NOWAIT") } if s.skipLocked { - out.writeString("SKIP LOCKED") + out.WriteString("SKIP LOCKED") } return nil diff --git a/select_statement_test.go b/internal/jet/select_statement_test.go similarity index 93% rename from select_statement_test.go rename to internal/jet/select_statement_test.go index 520f49c..219eb79 100644 --- a/select_statement_test.go +++ b/internal/jet/select_statement_test.go @@ -3,11 +3,11 @@ package jet import "testing" func TestInvalidSelect(t *testing.T) { - assertStatementErr(t, SELECT(nil), "jet: projection is nil") + assertStatementErr(t, SELECT(nil), "jet: Projection is nil") } func TestSelectColumnList(t *testing.T) { - columnList := ColumnList{table2ColInt, table2ColFloat, table3ColInt} + columnList := ColumnList(table2ColInt, table2ColFloat, table3ColInt) assertStatement(t, SELECT(columnList).FROM(table2), ` SELECT table2.col_int AS "table2.col_int", @@ -17,6 +17,15 @@ FROM db.table2; `) } +func TestSelectLiterals(t *testing.T) { + assertStatement(t, SELECT(Int(1), Float(2.2), Bool(false)).FROM(table1), ` +SELECT 1, + 2.2, + FALSE +FROM db.table1; +`) +} + func TestSelectDistinct(t *testing.T) { assertStatement(t, SELECT(table1ColBool).DISTINCT(), ` SELECT DISTINCT table1.col_bool AS "table1.col_bool"; diff --git a/select_table.go b/internal/jet/select_table.go similarity index 81% rename from select_table.go rename to internal/jet/select_table.go index 00e5fdc..2d4113b 100644 --- a/select_table.go +++ b/internal/jet/select_table.go @@ -16,7 +16,7 @@ type selectTableImpl struct { selectStmt SelectStatement alias string - projections []projection + projections []Projection } func newSelectTable(selectStmt SelectStatement, alias string) SelectTable { @@ -25,7 +25,7 @@ func newSelectTable(selectStmt SelectStatement, alias string) SelectTable { expTable.readableTableInterfaceImpl.parent = expTable for _, projection := range selectStmt.projections() { - newProjection := projection.from(expTable) + newProjection := projection.fromImpl(expTable) expTable.projections = append(expTable.projections, newProjection) } @@ -37,7 +37,7 @@ func (s *selectTableImpl) Alias() string { return s.alias } -func (s *selectTableImpl) columns() []column { +func (s *selectTableImpl) columns() []IColumn { return nil } @@ -54,7 +54,7 @@ func (s *selectTableImpl) AllColumns() ProjectionList { return s.projections } -func (s *selectTableImpl) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { +func (s *selectTableImpl) serialize(statement StatementType, out *SqlBuilder, options ...SerializeOption) error { if s == nil { return errors.New("jet: Expression table is nil. ") } @@ -65,7 +65,7 @@ func (s *selectTableImpl) serialize(statement statementType, out *sqlBuilder, op return err } - out.writeString("AS") + out.WriteString("AS") out.writeIdentifier(s.alias) return nil diff --git a/set_statement.go b/internal/jet/set_statement.go similarity index 86% rename from set_statement.go rename to internal/jet/set_statement.go index c81fca5..a0add2e 100644 --- a/set_statement.go +++ b/internal/jet/set_statement.go @@ -82,14 +82,14 @@ func (s *setStatementImpl) accept(visitor visitor) { } } -func (s *setStatementImpl) projections() []projection { +func (s *setStatementImpl) projections() []Projection { if len(s.selects) > 0 { return s.selects[0].projections() } - return []projection{} + return []Projection{} } -func (s *setStatementImpl) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { +func (s *setStatementImpl) serialize(statement StatementType, out *SqlBuilder, options ...SerializeOption) error { if s == nil { return errors.New("jet: Set expression is nil. ") } @@ -97,7 +97,7 @@ func (s *setStatementImpl) serialize(statement statementType, out *sqlBuilder, o wrap := s.orderBy != nil || s.limit >= 0 || s.offset >= 0 if wrap { - out.writeString("(") + out.WriteString("(") out.increaseIdent() } @@ -110,13 +110,13 @@ func (s *setStatementImpl) serialize(statement statementType, out *sqlBuilder, o if wrap { out.decreaseIdent() out.newLine() - out.writeString(")") + out.WriteString(")") } return nil } -func (s *setStatementImpl) serializeImpl(out *sqlBuilder) error { +func (s *setStatementImpl) serializeImpl(out *SqlBuilder) error { if s == nil { return errors.New("jet: Set expression is nil. ") } @@ -126,16 +126,16 @@ func (s *setStatementImpl) serializeImpl(out *sqlBuilder) error { } out.newLine() - out.writeString("(") + out.WriteString("(") out.increaseIdent() for i, selectStmt := range s.selects { out.newLine() if i > 0 { - out.writeString(s.operator) + out.WriteString(s.operator) if s.all { - out.writeString("ALL") + out.WriteString("ALL") } out.newLine() } @@ -144,7 +144,7 @@ func (s *setStatementImpl) serializeImpl(out *sqlBuilder) error { return errors.New("jet: select statement is nil") } - err := selectStmt.serialize(setStatement, out) + err := selectStmt.serialize(SetStatementType, out) if err != nil { return err @@ -153,10 +153,10 @@ func (s *setStatementImpl) serializeImpl(out *sqlBuilder) error { out.decreaseIdent() out.newLine() - out.writeString(")") + out.WriteString(")") if s.orderBy != nil { - err := out.writeOrderBy(setStatement, s.orderBy) + err := out.writeOrderBy(SetStatementType, s.orderBy) if err != nil { return err } @@ -164,13 +164,13 @@ func (s *setStatementImpl) serializeImpl(out *sqlBuilder) error { if s.limit >= 0 { out.newLine() - out.writeString("LIMIT") + out.WriteString("LIMIT") out.insertParametrizedArgument(s.limit) } if s.offset >= 0 { out.newLine() - out.writeString("OFFSET") + out.WriteString("OFFSET") out.insertParametrizedArgument(s.offset) } @@ -178,8 +178,8 @@ func (s *setStatementImpl) serializeImpl(out *sqlBuilder) error { } func (s *setStatementImpl) Sql(dialect ...Dialect) (query string, args []interface{}, err error) { - queryData := &sqlBuilder{ - dialect: detectDialect(s, dialect...), + queryData := &SqlBuilder{ + Dialect: detectDialect(s, dialect...), } err = s.serializeImpl(queryData) diff --git a/set_statement_test.go b/internal/jet/set_statement_test.go similarity index 100% rename from set_statement_test.go rename to internal/jet/set_statement_test.go diff --git a/statement.go b/internal/jet/statement.go similarity index 84% rename from statement.go rename to internal/jet/statement.go index a5ece84..97f4cf9 100644 --- a/statement.go +++ b/internal/jet/statement.go @@ -39,14 +39,26 @@ func debugSql(statement Statement, overrideDialect ...Dialect) (string, error) { return "", err } + //debugSQLQuery := sqlQuery + // + //for i, arg := range args { + // argPlaceholder := dialect.ArgumentPlaceholder()(i + 1) + // debugSQLQuery = strings.Replace(debugSQLQuery, argPlaceholder, argToString(arg), 1) + //} + // + //return debugSQLQuery, nil + return queryStringToDebugString(sqlQuery, args, dialect), nil +} + +func queryStringToDebugString(sqlQuery string, args []interface{}, dialect Dialect) string { debugSQLQuery := sqlQuery for i, arg := range args { - argPlaceholder := dialect.ArgumentPlaceholder(i + 1) + argPlaceholder := dialect.ArgumentPlaceholder()(i + 1) debugSQLQuery = strings.Replace(debugSQLQuery, argPlaceholder, argToString(arg), 1) } - return debugSQLQuery, nil + return debugSQLQuery } func query(statement Statement, db execution.DB, destination interface{}) error { diff --git a/string_expression.go b/internal/jet/string_expression.go similarity index 100% rename from string_expression.go rename to internal/jet/string_expression.go diff --git a/internal/jet/string_expression_test.go b/internal/jet/string_expression_test.go new file mode 100644 index 0000000..a1209ce --- /dev/null +++ b/internal/jet/string_expression_test.go @@ -0,0 +1,82 @@ +package jet + +import ( + "testing" +) + +func TestStringEQ(t *testing.T) { + exp := table3StrCol.EQ(table2ColStr) + assertClauseSerialize(t, exp, "(table3.col2 = table2.col_str)") + exp = table3StrCol.EQ(String("JOHN")) + assertClauseSerialize(t, exp, "(table3.col2 = $1)", "JOHN") +} + +func TestStringNOT_EQ(t *testing.T) { + exp := table3StrCol.NOT_EQ(table2ColStr) + assertClauseSerialize(t, exp, "(table3.col2 != table2.col_str)") + assertClauseSerialize(t, table3StrCol.NOT_EQ(String("JOHN")), "(table3.col2 != $1)", "JOHN") +} + +func TestStringExpressionIS_DISTINCT_FROM(t *testing.T) { + assertClauseSerialize(t, table3StrCol.IS_DISTINCT_FROM(table2ColStr), "(table3.col2 IS DISTINCT FROM table2.col_str)") + assertClauseSerialize(t, table3StrCol.IS_DISTINCT_FROM(String("JOHN")), "(table3.col2 IS DISTINCT FROM $1)", "JOHN") +} + +func TestStringExpressionIS_NOT_DISTINCT_FROM(t *testing.T) { + assertClauseSerialize(t, table3StrCol.IS_NOT_DISTINCT_FROM(table2ColStr), "(table3.col2 IS NOT DISTINCT FROM table2.col_str)") + assertClauseSerialize(t, table3StrCol.IS_NOT_DISTINCT_FROM(String("JOHN")), "(table3.col2 IS NOT DISTINCT FROM $1)", "JOHN") +} + +func TestStringGT(t *testing.T) { + exp := table3StrCol.GT(table2ColStr) + assertClauseSerialize(t, exp, "(table3.col2 > table2.col_str)") + assertClauseSerialize(t, table3StrCol.GT(String("JOHN")), "(table3.col2 > $1)", "JOHN") +} + +func TestStringGT_EQ(t *testing.T) { + exp := table3StrCol.GT_EQ(table2ColStr) + assertClauseSerialize(t, exp, "(table3.col2 >= table2.col_str)") + assertClauseSerialize(t, table3StrCol.GT_EQ(String("JOHN")), "(table3.col2 >= $1)", "JOHN") +} + +func TestStringLT(t *testing.T) { + exp := table3StrCol.LT(table2ColStr) + assertClauseSerialize(t, exp, "(table3.col2 < table2.col_str)") + assertClauseSerialize(t, table3StrCol.LT(String("JOHN")), "(table3.col2 < $1)", "JOHN") +} + +func TestStringLT_EQ(t *testing.T) { + exp := table3StrCol.LT_EQ(table2ColStr) + assertClauseSerialize(t, exp, "(table3.col2 <= table2.col_str)") + assertClauseSerialize(t, table3StrCol.LT_EQ(String("JOHN")), "(table3.col2 <= $1)", "JOHN") +} + +func TestStringCONCAT(t *testing.T) { + assertClauseSerialize(t, table3StrCol.CONCAT(table2ColStr), "(table3.col2 || table2.col_str)") + assertClauseSerialize(t, table3StrCol.CONCAT(String("JOHN")), "(table3.col2 || $1)", "JOHN") +} + +func TestStringLIKE(t *testing.T) { + assertClauseSerialize(t, table3StrCol.LIKE(table2ColStr), "(table3.col2 LIKE table2.col_str)") + assertClauseSerialize(t, table3StrCol.LIKE(String("JOHN")), "(table3.col2 LIKE $1)", "JOHN") +} + +func TestStringNOT_LIKE(t *testing.T) { + assertClauseSerialize(t, table3StrCol.NOT_LIKE(table2ColStr), "(table3.col2 NOT LIKE table2.col_str)") + assertClauseSerialize(t, table3StrCol.NOT_LIKE(String("JOHN")), "(table3.col2 NOT LIKE $1)", "JOHN") +} + +func TestStringSIMILAR_TO(t *testing.T) { + assertClauseSerialize(t, table3StrCol.SIMILAR_TO(table2ColStr), "(table3.col2 SIMILAR TO table2.col_str)") + assertClauseSerialize(t, table3StrCol.SIMILAR_TO(String("JOHN")), "(table3.col2 SIMILAR TO $1)", "JOHN") +} + +func TestStringNOT_SIMILAR_TO(t *testing.T) { + assertClauseSerialize(t, table3StrCol.NOT_SIMILAR_TO(table2ColStr), "(table3.col2 NOT SIMILAR TO table2.col_str)") + assertClauseSerialize(t, table3StrCol.NOT_SIMILAR_TO(String("JOHN")), "(table3.col2 NOT SIMILAR TO $1)", "JOHN") +} + +func TestStringExp(t *testing.T) { + assertClauseSerialize(t, StringExp(table2ColFloat), "table2.col_float") + assertClauseSerialize(t, StringExp(table2ColFloat).NOT_LIKE(String("abc")), "(table2.col_float NOT LIKE $1)", "abc") +} diff --git a/table.go b/internal/jet/table.go similarity index 80% rename from table.go rename to internal/jet/table.go index 413087a..7d5b46c 100644 --- a/table.go +++ b/internal/jet/table.go @@ -7,12 +7,12 @@ import ( type table interface { dialect() Dialect - columns() []column + columns() []IColumn } type readableTable interface { // Generates a select query on the current tableName. - SELECT(projection projection, projections ...projection) SelectStatement + SELECT(projection Projection, projections ...Projection) SelectStatement // Creates a inner join tableName Expression using onCondition. INNER_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable @@ -31,8 +31,8 @@ type readableTable interface { } type writableTable interface { - INSERT(columns ...column) InsertStatement - UPDATE(column column, columns ...column) UpdateStatement + INSERT(columns ...IColumn) InsertStatement + UPDATE(column IColumn, columns ...IColumn) UpdateStatement DELETE() DeleteStatement LOCK() LockStatement @@ -42,7 +42,7 @@ type writableTable interface { type ReadableTable interface { table readableTable - clause + Clause acceptsVisitor } @@ -50,7 +50,7 @@ type ReadableTable interface { type WritableTable interface { table writableTable - clause + Clause acceptsVisitor } @@ -59,7 +59,7 @@ type Table interface { table readableTable writableTable - clause + Clause acceptsVisitor SchemaName() string @@ -72,8 +72,8 @@ type readableTableInterfaceImpl struct { } // Generates a select query on the current tableName. -func (r *readableTableInterfaceImpl) SELECT(projection1 projection, projections ...projection) SelectStatement { - return newSelectStatement(r.parent, append([]projection{projection1}, projections...)) +func (r *readableTableInterfaceImpl) SELECT(projection1 Projection, projections ...Projection) SelectStatement { + return newSelectStatement(r.parent, append([]Projection{projection1}, projections...)) } // Creates a inner join tableName Expression using onCondition. @@ -103,11 +103,11 @@ type writableTableInterfaceImpl struct { parent WritableTable } -func (w *writableTableInterfaceImpl) INSERT(columns ...column) InsertStatement { +func (w *writableTableInterfaceImpl) INSERT(columns ...IColumn) InsertStatement { return newInsertStatement(w.parent, unwidColumnList(columns)) } -func (w *writableTableInterfaceImpl) UPDATE(column column, columns ...column) UpdateStatement { +func (w *writableTableInterfaceImpl) UPDATE(column IColumn, columns ...IColumn) UpdateStatement { return newUpdateStatement(w.parent, unwindColumns(column, columns...)) } @@ -129,7 +129,7 @@ func NewTable(Dialect Dialect, schemaName, name string, columns ...Column) Table columnList: columns, } for _, c := range columns { - c.setTableName(name) + c.SetTableName(name) } t.readableTableInterfaceImpl.parent = t @@ -153,7 +153,7 @@ func (t *tableImpl) AS(alias string) { t.alias = alias for _, c := range t.columnList { - c.setTableName(alias) + c.SetTableName(alias) } } @@ -165,8 +165,8 @@ func (t *tableImpl) TableName() string { return t.name } -func (t *tableImpl) columns() []column { - ret := []column{} +func (t *tableImpl) columns() []IColumn { + ret := []IColumn{} for _, col := range t.columnList { ret = append(ret, col) @@ -183,17 +183,17 @@ func (t *tableImpl) accept(visitor visitor) { visitor.visit(t) } -func (t *tableImpl) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error { +func (t *tableImpl) serialize(statement StatementType, out *SqlBuilder, options ...SerializeOption) error { if t == nil { return errors.New("jet: tableImpl is nil. ") } out.writeIdentifier(t.schemaName) - out.writeString(".") + out.WriteString(".") out.writeIdentifier(t.name) if len(t.alias) > 0 { - out.writeString("AS") + out.WriteString("AS") out.writeIdentifier(t.alias) } @@ -246,7 +246,7 @@ func (t *joinTable) TableName() string { return "" } -func (t *joinTable) columns() []column { +func (t *joinTable) columns() []IColumn { return append(t.lhs.columns(), t.rhs.columns()...) } @@ -259,7 +259,7 @@ func (t *joinTable) dialect() Dialect { return detectDialect(t) } -func (t *joinTable) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) (err error) { +func (t *joinTable) serialize(statement StatementType, out *SqlBuilder, options ...SerializeOption) (err error) { if t == nil { return errors.New("jet: Join table is nil. ") } @@ -276,15 +276,15 @@ func (t *joinTable) serialize(statement statementType, out *sqlBuilder, options switch t.joinType { case innerJoin: - out.writeString("INNER JOIN") + out.WriteString("INNER JOIN") case leftJoin: - out.writeString("LEFT JOIN") + out.WriteString("LEFT JOIN") case rightJoin: - out.writeString("RIGHT JOIN") + out.WriteString("RIGHT JOIN") case fullJoin: - out.writeString("FULL JOIN") + out.WriteString("FULL JOIN") case crossJoin: - out.writeString("CROSS JOIN") + out.WriteString("CROSS JOIN") } if utils.IsNil(t.rhs) { @@ -300,7 +300,7 @@ func (t *joinTable) serialize(statement statementType, out *sqlBuilder, options } if t.onCondition != nil { - out.writeString("ON") + out.WriteString("ON") if err = t.onCondition.serialize(statement, out); err != nil { return } @@ -309,11 +309,11 @@ func (t *joinTable) serialize(statement statementType, out *sqlBuilder, options return nil } -func unwindColumns(column1 column, columns ...column) []column { - columnList := []column{} +func unwindColumns(column1 IColumn, columns ...IColumn) []IColumn { + columnList := []IColumn{} - if val, ok := column1.(ColumnList); ok { - for _, col := range val { + if val, ok := column1.(IColumnList); ok { + for _, col := range val.Columns() { columnList = append(columnList, col) } columnList = append(columnList, columns...) @@ -325,12 +325,12 @@ func unwindColumns(column1 column, columns ...column) []column { return columnList } -func unwidColumnList(columns []column) []column { - ret := []column{} +func unwidColumnList(columns []IColumn) []IColumn { + ret := []IColumn{} for _, col := range columns { - if columnList, ok := col.(ColumnList); ok { - for _, c := range columnList { + if columnList, ok := col.(IColumnList); ok { + for _, c := range columnList.Columns() { ret = append(ret, c) } } else { diff --git a/table_test.go b/internal/jet/table_test.go similarity index 83% rename from table_test.go rename to internal/jet/table_test.go index 31f29ff..9a90da6 100644 --- a/table_test.go +++ b/internal/jet/table_test.go @@ -12,17 +12,17 @@ func TestJoinNilInputs(t *testing.T) { } func TestINNER_JOIN(t *testing.T) { - AssertPostgreClauseSerialize(t, table1. + assertClauseSerialize(t, table1. INNER_JOIN(table2, table1ColInt.EQ(table2ColInt)), `db.table1 INNER JOIN db.table2 ON (table1.col_int = table2.col_int)`) - AssertPostgreClauseSerialize(t, table1. + assertClauseSerialize(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)`) - AssertPostgreClauseSerialize(t, table1. + assertClauseSerialize(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) { - AssertPostgreClauseSerialize(t, table1. + assertClauseSerialize(t, table1. LEFT_JOIN(table2, table1ColInt.EQ(table2ColInt)), `db.table1 LEFT JOIN db.table2 ON (table1.col_int = table2.col_int)`) - AssertPostgreClauseSerialize(t, table1. + assertClauseSerialize(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)`) - AssertPostgreClauseSerialize(t, table1. + assertClauseSerialize(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) { - AssertPostgreClauseSerialize(t, table1. + assertClauseSerialize(t, table1. RIGHT_JOIN(table2, table1ColInt.EQ(table2ColInt)), `db.table1 RIGHT JOIN db.table2 ON (table1.col_int = table2.col_int)`) - AssertPostgreClauseSerialize(t, table1. + assertClauseSerialize(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)`) - AssertPostgreClauseSerialize(t, table1. + assertClauseSerialize(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) { - AssertPostgreClauseSerialize(t, table1. + assertClauseSerialize(t, table1. FULL_JOIN(table2, table1ColInt.EQ(table2ColInt)), `db.table1 FULL JOIN db.table2 ON (table1.col_int = table2.col_int)`) - AssertPostgreClauseSerialize(t, table1. + assertClauseSerialize(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)`) - AssertPostgreClauseSerialize(t, table1. + assertClauseSerialize(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) { - AssertPostgreClauseSerialize(t, table1. + assertClauseSerialize(t, table1. CROSS_JOIN(table2), `db.table1 CROSS JOIN db.table2`) - AssertPostgreClauseSerialize(t, table1. + assertClauseSerialize(t, table1. CROSS_JOIN(table2). CROSS_JOIN(table3), `db.table1 diff --git a/testutils.go b/internal/jet/testutils.go similarity index 61% rename from testutils.go rename to internal/jet/testutils.go index 880e086..fc1fec0 100644 --- a/testutils.go +++ b/internal/jet/testutils.go @@ -1,6 +1,7 @@ package jet import ( + "fmt" "gotest.tools/assert" "testing" ) @@ -17,7 +18,7 @@ var table1ColBool = BoolColumn("col_bool") var table1ColDate = DateColumn("col_date") var table1 = NewTable( - PostgreSQL, + ANSII, "db", "table1", table1Col1, @@ -45,7 +46,7 @@ var table2ColTimestampz = TimestampzColumn("col_timestampz") var table2ColDate = DateColumn("col_date") var table2 = NewTable( - PostgreSQL, + ANSII, "db", "table2", table2Col3, @@ -65,73 +66,62 @@ var table3Col1 = IntegerColumn("col1") var table3ColInt = IntegerColumn("col_int") var table3StrCol = StringColumn("col2") var table3 = NewTable( - PostgreSQL, + ANSII, "db", "table3", table3Col1, table3ColInt, table3StrCol) -func AssertClauseSerialize(t *testing.T, clause clause, query string, args ...interface{}) { - out := sqlBuilder{dialect: Default} - err := clause.serialize(selectStatement, &out) +func assertClauseSerialize(t *testing.T, clause Clause, query string, args ...interface{}) { + out := SqlBuilder{Dialect: ANSII} + err := clause.serialize(SelectStatementType, &out) assert.NilError(t, err) - assert.DeepEqual(t, out.buff.String(), query) - assert.DeepEqual(t, out.args, args) + assert.DeepEqual(t, out.DebugSQL(), query) + + if len(args) > 0 { + assert.DeepEqual(t, out.Args, args) + } + } -func AssertPostgreClauseSerialize(t *testing.T, clause clause, query string, args ...interface{}) { - out := sqlBuilder{dialect: PostgreSQL} - err := clause.serialize(selectStatement, &out) - - assert.NilError(t, err) - - assert.DeepEqual(t, out.buff.String(), query) - assert.DeepEqual(t, out.args, args) -} - -func AssertMySQLClauseSerialize(t *testing.T, clause clause, query string, args ...interface{}) { - out := sqlBuilder{dialect: MySQL} - err := clause.serialize(selectStatement, &out) - - assert.NilError(t, err) - - assert.DeepEqual(t, out.buff.String(), query) - assert.DeepEqual(t, out.args, args) -} - -func assertClauseSerializeErr(t *testing.T, clause clause, errString string) { - out := sqlBuilder{dialect: PostgreSQL} - err := clause.serialize(selectStatement, &out) +func assertClauseSerializeErr(t *testing.T, clause Clause, errString string) { + out := SqlBuilder{Dialect: ANSII} + err := clause.serialize(SelectStatementType, &out) //fmt.Println(out.buff.String()) assert.Assert(t, err != nil) assert.Error(t, err, errString) } -func assertProjectionSerialize(t *testing.T, projection projection, query string, args ...interface{}) { - out := sqlBuilder{dialect: PostgreSQL} - err := projection.serializeForProjection(selectStatement, &out) +func assertProjectionSerialize(t *testing.T, projection Projection, query string, args ...interface{}) { + out := SqlBuilder{Dialect: ANSII} + err := projection.serializeForProjection(SelectStatementType, &out) assert.NilError(t, err) - assert.DeepEqual(t, out.buff.String(), query) - assert.DeepEqual(t, out.args, args) + assert.DeepEqual(t, out.DebugSQL(), query) + + if len(args) > 0 { + assert.DeepEqual(t, out.Args, args) + } } func assertStatement(t *testing.T, query Statement, expectedQuery string, expectedArgs ...interface{}) { - queryStr, args, err := query.Sql(PostgreSQL) + queryStr, err := query.DebugSql() assert.NilError(t, err) + fmt.Println(queryStr) + //fmt.Println(queryStr) assert.Equal(t, queryStr, expectedQuery) - assert.DeepEqual(t, args, expectedArgs) + //assert.DeepEqual(t, args, expectedArgs) } func assertStatementErr(t *testing.T, stmt Statement, errorStr string) { - _, _, err := stmt.Sql(PostgreSQL) + _, _, err := stmt.Sql(ANSII) assert.Assert(t, err != nil) assert.Error(t, err, errorStr) diff --git a/time_expression.go b/internal/jet/time_expression.go similarity index 100% rename from time_expression.go rename to internal/jet/time_expression.go diff --git a/internal/jet/time_expression_test.go b/internal/jet/time_expression_test.go new file mode 100644 index 0000000..8f595a2 --- /dev/null +++ b/internal/jet/time_expression_test.go @@ -0,0 +1,53 @@ +package jet + +import ( + "testing" +) + +var timeVar = Time(10, 20, 0, 0) + +func TestTimeExpressionEQ(t *testing.T) { + assertClauseSerialize(t, table1ColTime.EQ(table2ColTime), "(table1.col_time = table2.col_time)") + assertClauseSerialize(t, table1ColTime.EQ(timeVar), "(table1.col_time = $1)", "10:20:00.000") +} + +func TestTimeExpressionNOT_EQ(t *testing.T) { + assertClauseSerialize(t, table1ColTime.NOT_EQ(table2ColTime), "(table1.col_time != table2.col_time)") + assertClauseSerialize(t, table1ColTime.NOT_EQ(timeVar), "(table1.col_time != $1)", "10:20:00.000") +} + +func TestTimeExpressionIS_DISTINCT_FROM(t *testing.T) { + assertClauseSerialize(t, table1ColTime.IS_DISTINCT_FROM(table2ColTime), "(table1.col_time IS DISTINCT FROM table2.col_time)") + assertClauseSerialize(t, table1ColTime.IS_DISTINCT_FROM(timeVar), "(table1.col_time IS DISTINCT FROM $1)", "10:20:00.000") +} + +func TestTimeExpressionIS_NOT_DISTINCT_FROM(t *testing.T) { + assertClauseSerialize(t, table1ColTime.IS_NOT_DISTINCT_FROM(table2ColTime), "(table1.col_time IS NOT DISTINCT FROM table2.col_time)") + assertClauseSerialize(t, table1ColTime.IS_NOT_DISTINCT_FROM(timeVar), "(table1.col_time IS NOT DISTINCT FROM $1)", "10:20:00.000") +} + +func TestTimeExpressionLT(t *testing.T) { + assertClauseSerialize(t, table1ColTime.LT(table2ColTime), "(table1.col_time < table2.col_time)") + assertClauseSerialize(t, table1ColTime.LT(timeVar), "(table1.col_time < $1)", "10:20:00.000") +} + +func TestTimeExpressionLT_EQ(t *testing.T) { + assertClauseSerialize(t, table1ColTime.LT_EQ(table2ColTime), "(table1.col_time <= table2.col_time)") + assertClauseSerialize(t, table1ColTime.LT_EQ(timeVar), "(table1.col_time <= $1)", "10:20:00.000") +} + +func TestTimeExpressionGT(t *testing.T) { + assertClauseSerialize(t, table1ColTime.GT(table2ColTime), "(table1.col_time > table2.col_time)") + assertClauseSerialize(t, table1ColTime.GT(timeVar), "(table1.col_time > $1)", "10:20:00.000") +} + +func TestTimeExpressionGT_EQ(t *testing.T) { + assertClauseSerialize(t, table1ColTime.GT_EQ(table2ColTime), "(table1.col_time >= table2.col_time)") + assertClauseSerialize(t, table1ColTime.GT_EQ(timeVar), "(table1.col_time >= $1)", "10:20:00.000") +} + +func TestTimeExp(t *testing.T) { + assertClauseSerialize(t, TimeExp(table1ColFloat), "table1.col_float") + assertClauseSerialize(t, TimeExp(table1ColFloat).LT(Time(1, 1, 1, 1)), + "(table1.col_float < $1)", string("01:01:01.001")) +} diff --git a/timestamp_expression.go b/internal/jet/timestamp_expression.go similarity index 100% rename from timestamp_expression.go rename to internal/jet/timestamp_expression.go diff --git a/internal/jet/timestamp_expression_test.go b/internal/jet/timestamp_expression_test.go new file mode 100644 index 0000000..b49fc9f --- /dev/null +++ b/internal/jet/timestamp_expression_test.go @@ -0,0 +1,52 @@ +package jet + +import "testing" + +var timestamp = Timestamp(2000, 1, 31, 10, 20, 0, 0) + +func TestTimestampExpressionEQ(t *testing.T) { + assertClauseSerialize(t, table1ColTimestamp.EQ(table2ColTimestamp), "(table1.col_timestamp = table2.col_timestamp)") + assertClauseSerialize(t, table1ColTimestamp.EQ(timestamp), + "(table1.col_timestamp = $1)", "2000-01-31 10:20:00.000") +} + +func TestTimestampExpressionNOT_EQ(t *testing.T) { + assertClauseSerialize(t, table1ColTimestamp.NOT_EQ(table2ColTimestamp), "(table1.col_timestamp != table2.col_timestamp)") + assertClauseSerialize(t, table1ColTimestamp.NOT_EQ(timestamp), "(table1.col_timestamp != $1)", "2000-01-31 10:20:00.000") +} + +func TestTimestampExpressionIS_DISTINCT_FROM(t *testing.T) { + assertClauseSerialize(t, table1ColTimestamp.IS_DISTINCT_FROM(table2ColTimestamp), "(table1.col_timestamp IS DISTINCT FROM table2.col_timestamp)") + assertClauseSerialize(t, table1ColTimestamp.IS_DISTINCT_FROM(timestamp), "(table1.col_timestamp IS DISTINCT FROM $1)", "2000-01-31 10:20:00.000") +} + +func TestTimestampExpressionIS_NOT_DISTINCT_FROM(t *testing.T) { + assertClauseSerialize(t, table1ColTimestamp.IS_NOT_DISTINCT_FROM(table2ColTimestamp), "(table1.col_timestamp IS NOT DISTINCT FROM table2.col_timestamp)") + assertClauseSerialize(t, table1ColTimestamp.IS_NOT_DISTINCT_FROM(timestamp), "(table1.col_timestamp IS NOT DISTINCT FROM $1)", "2000-01-31 10:20:00.000") +} + +func TestTimestampExpressionLT(t *testing.T) { + assertClauseSerialize(t, table1ColTimestamp.LT(table2ColTimestamp), "(table1.col_timestamp < table2.col_timestamp)") + assertClauseSerialize(t, table1ColTimestamp.LT(timestamp), "(table1.col_timestamp < $1)", "2000-01-31 10:20:00.000") +} + +func TestTimestampExpressionLT_EQ(t *testing.T) { + assertClauseSerialize(t, table1ColTimestamp.LT_EQ(table2ColTimestamp), "(table1.col_timestamp <= table2.col_timestamp)") + assertClauseSerialize(t, table1ColTimestamp.LT_EQ(timestamp), "(table1.col_timestamp <= $1)", "2000-01-31 10:20:00.000") +} + +func TestTimestampExpressionGT(t *testing.T) { + assertClauseSerialize(t, table1ColTimestamp.GT(table2ColTimestamp), "(table1.col_timestamp > table2.col_timestamp)") + assertClauseSerialize(t, table1ColTimestamp.GT(timestamp), "(table1.col_timestamp > $1)", "2000-01-31 10:20:00.000") +} + +func TestTimestampExpressionGT_EQ(t *testing.T) { + assertClauseSerialize(t, table1ColTimestamp.GT_EQ(table2ColTimestamp), "(table1.col_timestamp >= table2.col_timestamp)") + assertClauseSerialize(t, table1ColTimestamp.GT_EQ(timestamp), "(table1.col_timestamp >= $1)", "2000-01-31 10:20:00.000") +} + +func TestTimestampExp(t *testing.T) { + assertClauseSerialize(t, TimestampExp(table1ColFloat), "table1.col_float") + assertClauseSerialize(t, TimestampExp(table1ColFloat).LT(timestamp), + "(table1.col_float < $1)", "2000-01-31 10:20:00.000") +} diff --git a/timestampz_expression.go b/internal/jet/timestampz_expression.go similarity index 100% rename from timestampz_expression.go rename to internal/jet/timestampz_expression.go diff --git a/internal/jet/timestampz_expression_test.go b/internal/jet/timestampz_expression_test.go new file mode 100644 index 0000000..d67b2b6 --- /dev/null +++ b/internal/jet/timestampz_expression_test.go @@ -0,0 +1,54 @@ +// +build todo + +package jet + +import "testing" + +var timestampz = Timestampz(2000, 1, 31, 10, 20, 0, 0, 2) + +func TestTimestampzExpressionEQ(t *testing.T) { + assertClauseSerialize(t, table1ColTimestampz.EQ(table2ColTimestampz), "(table1.col_timestampz = table2.col_timestampz)") + assertClauseSerialize(t, table1ColTimestampz.EQ(timestampz), + "(table1.col_timestampz = $1::timestamp with time zone)", "2000-01-31 10:20:00.000 +002") +} + +func TestTimestampzExpressionNOT_EQ(t *testing.T) { + assertClauseSerialize(t, table1ColTimestampz.NOT_EQ(table2ColTimestampz), "(table1.col_timestampz != table2.col_timestampz)") + assertClauseSerialize(t, table1ColTimestampz.NOT_EQ(timestampz), "(table1.col_timestampz != $1::timestamp with time zone)", "2000-01-31 10:20:00.000 +002") +} + +func TestTimestampzExpressionIS_DISTINCT_FROM(t *testing.T) { + assertClauseSerialize(t, table1ColTimestampz.IS_DISTINCT_FROM(table2ColTimestampz), "(table1.col_timestampz IS DISTINCT FROM table2.col_timestampz)") + assertClauseSerialize(t, table1ColTimestampz.IS_DISTINCT_FROM(timestampz), "(table1.col_timestampz IS DISTINCT FROM $1::timestamp with time zone)", "2000-01-31 10:20:00.000 +002") +} + +func TestTimestampzExpressionIS_NOT_DISTINCT_FROM(t *testing.T) { + assertClauseSerialize(t, table1ColTimestampz.IS_NOT_DISTINCT_FROM(table2ColTimestampz), "(table1.col_timestampz IS NOT DISTINCT FROM table2.col_timestampz)") + assertClauseSerialize(t, table1ColTimestampz.IS_NOT_DISTINCT_FROM(timestampz), "(table1.col_timestampz IS NOT DISTINCT FROM $1::timestamp with time zone)", "2000-01-31 10:20:00.000 +002") +} + +func TestTimestampzExpressionLT(t *testing.T) { + assertClauseSerialize(t, table1ColTimestampz.LT(table2ColTimestampz), "(table1.col_timestampz < table2.col_timestampz)") + assertClauseSerialize(t, table1ColTimestampz.LT(timestampz), "(table1.col_timestampz < $1::timestamp with time zone)", "2000-01-31 10:20:00.000 +002") +} + +func TestTimestampzExpressionLT_EQ(t *testing.T) { + assertClauseSerialize(t, table1ColTimestampz.LT_EQ(table2ColTimestampz), "(table1.col_timestampz <= table2.col_timestampz)") + assertClauseSerialize(t, table1ColTimestampz.LT_EQ(timestampz), "(table1.col_timestampz <= $1::timestamp with time zone)", "2000-01-31 10:20:00.000 +002") +} + +func TestTimestampzExpressionGT(t *testing.T) { + assertClauseSerialize(t, table1ColTimestampz.GT(table2ColTimestampz), "(table1.col_timestampz > table2.col_timestampz)") + assertClauseSerialize(t, table1ColTimestampz.GT(timestampz), "(table1.col_timestampz > $1::timestamp with time zone)", "2000-01-31 10:20:00.000 +002") +} + +func TestTimestampzExpressionGT_EQ(t *testing.T) { + assertClauseSerialize(t, table1ColTimestampz.GT_EQ(table2ColTimestampz), "(table1.col_timestampz >= table2.col_timestampz)") + assertClauseSerialize(t, table1ColTimestampz.GT_EQ(timestampz), "(table1.col_timestampz >= $1::timestamp with time zone)", "2000-01-31 10:20:00.000 +002") +} + +func TestTimestampzExp(t *testing.T) { + assertClauseSerialize(t, TimestampzExp(table1ColFloat), "table1.col_float") + assertClauseSerialize(t, TimestampzExp(table1ColFloat).LT(timestampz), + "(table1.col_float < $1::timestamp with time zone)", "2000-01-31 10:20:00.000 +002") +} diff --git a/timez_expression.go b/internal/jet/timez_expression.go similarity index 100% rename from timez_expression.go rename to internal/jet/timez_expression.go diff --git a/internal/jet/timez_expression_test.go b/internal/jet/timez_expression_test.go new file mode 100644 index 0000000..e60fc16 --- /dev/null +++ b/internal/jet/timez_expression_test.go @@ -0,0 +1,53 @@ +// +build TODO + +package jet + +import "testing" + +var timezVar = Timez(10, 20, 0, 0, 4) + +func TestTimezExpressionEQ(t *testing.T) { + assertClauseSerialize(t, table1ColTimez.EQ(table2ColTimez), "(table1.col_timez = table2.col_timez)") + assertClauseSerialize(t, table1ColTimez.EQ(timezVar), "(table1.col_timez = $1::time with time zone)", "10:20:00.000 +04") +} + +func TestTimezExpressionNOT_EQ(t *testing.T) { + assertClauseSerialize(t, table1ColTimez.NOT_EQ(table2ColTimez), "(table1.col_timez != table2.col_timez)") + assertClauseSerialize(t, table1ColTimez.NOT_EQ(timezVar), "(table1.col_timez != $1::time with time zone)", "10:20:00.000 +04") +} + +func TestTimezExpressionIS_DISTINCT_FROM(t *testing.T) { + assertClauseSerialize(t, table1ColTimez.IS_DISTINCT_FROM(table2ColTimez), "(table1.col_timez IS DISTINCT FROM table2.col_timez)") + assertClauseSerialize(t, table1ColTimez.IS_DISTINCT_FROM(timezVar), "(table1.col_timez IS DISTINCT FROM $1::time with time zone)", "10:20:00.000 +04") +} + +func TestTimezExpressionIS_NOT_DISTINCT_FROM(t *testing.T) { + assertClauseSerialize(t, table1ColTimez.IS_NOT_DISTINCT_FROM(table2ColTimez), "(table1.col_timez IS NOT DISTINCT FROM table2.col_timez)") + assertClauseSerialize(t, table1ColTimez.IS_NOT_DISTINCT_FROM(timezVar), "(table1.col_timez IS NOT DISTINCT FROM $1::time with time zone)", "10:20:00.000 +04") +} + +func TestTimezExpressionLT(t *testing.T) { + assertClauseSerialize(t, table1ColTimez.LT(table2ColTimez), "(table1.col_timez < table2.col_timez)") + assertClauseSerialize(t, table1ColTimez.LT(timezVar), "(table1.col_timez < $1::time with time zone)", "10:20:00.000 +04") +} + +func TestTimezExpressionLT_EQ(t *testing.T) { + assertClauseSerialize(t, table1ColTimez.LT_EQ(table2ColTimez), "(table1.col_timez <= table2.col_timez)") + assertClauseSerialize(t, table1ColTimez.LT_EQ(timezVar), "(table1.col_timez <= $1::time with time zone)", "10:20:00.000 +04") +} + +func TestTimezExpressionGT(t *testing.T) { + assertClauseSerialize(t, table1ColTimez.GT(table2ColTimez), "(table1.col_timez > table2.col_timez)") + assertClauseSerialize(t, table1ColTimez.GT(timezVar), "(table1.col_timez > $1::time with time zone)", "10:20:00.000 +04") +} + +func TestTimezExpressionGT_EQ(t *testing.T) { + assertClauseSerialize(t, table1ColTimez.GT_EQ(table2ColTimez), "(table1.col_timez >= table2.col_timez)") + assertClauseSerialize(t, table1ColTimez.GT_EQ(timezVar), "(table1.col_timez >= $1::time with time zone)", "10:20:00.000 +04") +} + +func TestTimezExp(t *testing.T) { + assertClauseSerialize(t, TimezExp(table1ColFloat), "table1.col_float") + assertClauseSerialize(t, TimezExp(table1ColFloat).LT(Timez(1, 1, 1, 1, 4)), + "(table1.col_float < $1::time with time zone)", string("01:01:01.001 +04")) +} diff --git a/update_statement.go b/internal/jet/update_statement.go similarity index 76% rename from update_statement.go rename to internal/jet/update_statement.go index 5855ee4..938c6ab 100644 --- a/update_statement.go +++ b/internal/jet/update_statement.go @@ -16,23 +16,23 @@ type UpdateStatement interface { MODEL(data interface{}) UpdateStatement WHERE(expression BoolExpression) UpdateStatement - RETURNING(projections ...projection) UpdateStatement + RETURNING(projections ...Projection) UpdateStatement } -func newUpdateStatement(table WritableTable, columns []column) UpdateStatement { +func newUpdateStatement(table WritableTable, columns []IColumn) UpdateStatement { return &updateStatementImpl{ table: table, columns: columns, - values: make([]clause, 0, len(columns)), + values: make([]Clause, 0, len(columns)), } } type updateStatementImpl struct { table WritableTable - columns []column - values []clause + columns []IColumn + values []Clause where BoolExpression - returning []projection + returning []Projection } func (u *updateStatementImpl) SET(value interface{}, values ...interface{}) UpdateStatement { @@ -52,7 +52,7 @@ func (u *updateStatementImpl) WHERE(expression BoolExpression) UpdateStatement { return u } -func (u *updateStatementImpl) RETURNING(projections ...projection) UpdateStatement { +func (u *updateStatementImpl) RETURNING(projections ...Projection) UpdateStatement { u.returning = projections return u } @@ -63,18 +63,18 @@ func (u *updateStatementImpl) accept(visitor visitor) { } func (u *updateStatementImpl) Sql(dialect ...Dialect) (query string, args []interface{}, err error) { - out := &sqlBuilder{ - dialect: detectDialect(u, dialect...), + out := &SqlBuilder{ + Dialect: detectDialect(u, dialect...), } out.newLine() - out.writeString("UPDATE") + out.WriteString("UPDATE") if utils.IsNil(u.table) { return "", nil, errors.New("jet: table to update is nil") } - if err = u.table.serialize(updateStatement, out); err != nil { + if err = u.table.serialize(UpdateStatementType, out); err != nil { return } @@ -87,9 +87,9 @@ func (u *updateStatementImpl) Sql(dialect ...Dialect) (query string, args []inte } out.newLine() - out.writeString("SET") + out.WriteString("SET") - if err = out.dialect.UpdateAssigment(u.columns, u.values, out); err != nil { + if err = out.Dialect.UpdateAssigment()(u.columns, u.values, out); err != nil { return } @@ -97,11 +97,11 @@ func (u *updateStatementImpl) Sql(dialect ...Dialect) (query string, args []inte return "", nil, errors.New("jet: WHERE clause not set") } - if err = out.writeWhere(updateStatement, u.where); err != nil { + if err = out.writeWhere(UpdateStatementType, u.where); err != nil { return } - if err = out.writeReturning(updateStatement, u.returning); err != nil { + if err = out.writeReturning(UpdateStatementType, u.returning); err != nil { return } diff --git a/update_statement_test.go b/internal/jet/update_statement_test.go similarity index 100% rename from update_statement_test.go rename to internal/jet/update_statement_test.go diff --git a/utils.go b/internal/jet/utils.go similarity index 68% rename from utils.go rename to internal/jet/utils.go index 1c26b6f..3afdeaa 100644 --- a/utils.go +++ b/internal/jet/utils.go @@ -7,11 +7,11 @@ import ( "strings" ) -func serializeOrderByClauseList(statement statementType, orderByClauses []orderByClause, out *sqlBuilder) error { +func serializeOrderByClauseList(statement StatementType, orderByClauses []orderByClause, out *SqlBuilder) error { for i, value := range orderByClauses { if i > 0 { - out.writeString(", ") + out.WriteString(", ") } err := value.serializeForOrderBy(statement, out) @@ -24,11 +24,11 @@ func serializeOrderByClauseList(statement statementType, orderByClauses []orderB return nil } -func serializeGroupByClauseList(statement statementType, clauses []groupByClause, out *sqlBuilder) (err error) { +func serializeGroupByClauseList(statement StatementType, clauses []groupByClause, out *SqlBuilder) (err error) { for i, c := range clauses { if i > 0 { - out.writeString(", ") + out.WriteString(", ") } if c == nil { @@ -43,11 +43,11 @@ func serializeGroupByClauseList(statement statementType, clauses []groupByClause return nil } -func serializeClauseList(statement statementType, clauses []clause, out *sqlBuilder) (err error) { +func SerializeClauseList(statement StatementType, clauses []Clause, out *SqlBuilder) (err error) { for i, c := range clauses { if i > 0 { - out.writeString(", ") + out.WriteString(", ") } if c == nil { @@ -62,11 +62,11 @@ func serializeClauseList(statement statementType, clauses []clause, out *sqlBuil return nil } -func serializeExpressionList(statement statementType, expressions []Expression, separator string, out *sqlBuilder) error { +func serializeExpressionList(statement StatementType, expressions []Expression, separator string, out *SqlBuilder) error { for i, value := range expressions { if i > 0 { - out.writeString(separator) + out.WriteString(separator) } err := value.serialize(statement, out) @@ -79,15 +79,15 @@ func serializeExpressionList(statement statementType, expressions []Expression, return nil } -func serializeProjectionList(statement statementType, projections []projection, out *sqlBuilder) error { +func SerializeProjectionList(statement StatementType, projections []Projection, out *SqlBuilder) error { for i, col := range projections { if i > 0 { - out.writeString(",") + out.WriteString(",") out.newLine() } if col == nil { - return errors.New("jet: projection is nil") + return errors.New("jet: Projection is nil") } if err := col.serializeForProjection(statement, out); err != nil { @@ -98,24 +98,24 @@ func serializeProjectionList(statement statementType, projections []projection, return nil } -func serializeColumnNames(columns []column, out *sqlBuilder) error { +func SerializeColumnNames(columns []IColumn, out *SqlBuilder) error { for i, col := range columns { if i > 0 { - out.writeString(", ") + out.WriteString(", ") } if col == nil { return errors.New("jet: nil column in columns list") } - out.writeString(col.Name()) + out.WriteString(col.Name()) } return nil } -func columnListToProjectionList(columns []Column) []projection { - var ret []projection +func ColumnListToProjectionList(columns []Column) []Projection { + var ret []Projection for _, column := range columns { ret = append(ret, column) @@ -124,18 +124,18 @@ func columnListToProjectionList(columns []Column) []projection { return ret } -func valueToClause(value interface{}) clause { - if clause, ok := value.(clause); ok { +func valueToClause(value interface{}) Clause { + if clause, ok := value.(Clause); ok { return clause } return literal(value) } -func unwindRowFromModel(columns []column, data interface{}) []clause { +func unwindRowFromModel(columns []IColumn, data interface{}) []Clause { structValue := reflect.Indirect(reflect.ValueOf(data)) - row := []clause{} + row := []Clause{} mustBe(structValue, reflect.Struct) @@ -163,11 +163,11 @@ func unwindRowFromModel(columns []column, data interface{}) []clause { return row } -func unwindRowsFromModels(columns []column, data interface{}) [][]clause { +func unwindRowsFromModels(columns []IColumn, data interface{}) [][]Clause { sliceValue := reflect.Indirect(reflect.ValueOf(data)) mustBe(sliceValue, reflect.Slice) - rows := [][]clause{} + rows := [][]Clause{} for i := 0; i < sliceValue.Len(); i++ { structValue := sliceValue.Index(i) @@ -178,8 +178,8 @@ func unwindRowsFromModels(columns []column, data interface{}) [][]clause { return rows } -func unwindRowFromValues(value interface{}, values []interface{}) []clause { - row := []clause{} +func unwindRowFromValues(value interface{}, values []interface{}) []Clause { + row := []Clause{} allValues := append([]interface{}{value}, values...) diff --git a/visitor.go b/internal/jet/visitor.go similarity index 96% rename from visitor.go rename to internal/jet/visitor.go index 6532655..c513569 100644 --- a/visitor.go +++ b/internal/jet/visitor.go @@ -47,7 +47,7 @@ func (f *DialectFinder) visit(element acceptsVisitor) { if table, ok := element.(table); ok { dialect := table.dialect() - f.dialects[dialect.Name] = dialect + f.dialects[dialect.Name()] = dialect } } diff --git a/internal/testutils/test_utils.go b/internal/testutils/test_utils.go index 3032070..2998e6d 100644 --- a/internal/testutils/test_utils.go +++ b/internal/testutils/test_utils.go @@ -4,8 +4,8 @@ import ( "bytes" "encoding/json" "fmt" - "github.com/go-jet/jet" "github.com/go-jet/jet/execution" + "github.com/go-jet/jet/internal/jet" "gotest.tools/assert" "io/ioutil" "runtime" diff --git a/literal_expression_test.go b/literal_expression_test.go deleted file mode 100644 index 1d6b807..0000000 --- a/literal_expression_test.go +++ /dev/null @@ -1,7 +0,0 @@ -package jet - -import "testing" - -func TestRawExpression(t *testing.T) { - AssertPostgreClauseSerialize(t, RAW("current_database()"), "current_database()") -} diff --git a/lock_statement_test.go b/lock_statement_test.go deleted file mode 100644 index 8ae2376..0000000 --- a/lock_statement_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package jet - -import ( - "testing" -) - -func TestLockTable(t *testing.T) { - assertStatement(t, table1.LOCK().IN(LOCK_ACCESS_SHARE), ` -LOCK TABLE db.table1 IN ACCESS SHARE MODE; -`) - assertStatement(t, table1.LOCK().IN(LOCK_ROW_SHARE), ` -LOCK TABLE db.table1 IN ROW SHARE MODE; -`) - assertStatement(t, table1.LOCK().IN(LOCK_ROW_EXCLUSIVE), ` -LOCK TABLE db.table1 IN ROW EXCLUSIVE MODE; -`) - assertStatement(t, table1.LOCK().IN(LOCK_SHARE_UPDATE_EXCLUSIVE), ` -LOCK TABLE db.table1 IN SHARE UPDATE EXCLUSIVE MODE; -`) - assertStatement(t, table1.LOCK().IN(LOCK_SHARE), ` -LOCK TABLE db.table1 IN SHARE MODE; -`) - assertStatement(t, table1.LOCK().IN(LOCK_SHARE_ROW_EXCLUSIVE), ` -LOCK TABLE db.table1 IN SHARE ROW EXCLUSIVE MODE; -`) - assertStatement(t, table1.LOCK().IN(LOCK_EXCLUSIVE), ` -LOCK TABLE db.table1 IN EXCLUSIVE MODE; -`) - assertStatement(t, table1.LOCK().IN(LOCK_ACCESS_EXCLUSIVE), ` -LOCK TABLE db.table1 IN ACCESS EXCLUSIVE MODE; -`) -} diff --git a/mysql/bool_expression_test.go b/mysql/bool_expression_test.go new file mode 100644 index 0000000..60ef3e9 --- /dev/null +++ b/mysql/bool_expression_test.go @@ -0,0 +1,89 @@ +package mysql + +import ( + "testing" +) + +func TestBoolExpressionEQ(t *testing.T) { + assertClauseSerializeErr(t, table1ColBool.EQ(nil), "jet: nil rhs") + + assertClauseSerialize(t, table1ColBool.EQ(table2ColBool), "(table1.col_bool = table2.col_bool)") + assertClauseSerialize(t, table1ColBool.EQ(Bool(true)), "(table1.col_bool = ?)", true) +} + +func TestBoolExpressionNOT_EQ(t *testing.T) { + assertClauseSerialize(t, table1ColBool.NOT_EQ(table2ColBool), "(table1.col_bool != table2.col_bool)") + assertClauseSerialize(t, table1ColBool.NOT_EQ(Bool(true)), "(table1.col_bool != ?)", true) +} + +func TestBoolExpressionIS_DISTINCT_FROM(t *testing.T) { + assertClauseSerialize(t, table1ColBool.IS_DISTINCT_FROM(table2ColBool), "(NOT table1.col_bool <=> table2.col_bool)") + assertClauseSerialize(t, table1ColBool.IS_DISTINCT_FROM(Bool(false)), "(NOT table1.col_bool <=> ?)", false) +} + +func TestBoolExpressionIS_NOT_DISTINCT_FROM(t *testing.T) { + assertClauseSerialize(t, table1ColBool.IS_NOT_DISTINCT_FROM(table2ColBool), "(table1.col_bool <=> table2.col_bool)") + assertClauseSerialize(t, table1ColBool.IS_NOT_DISTINCT_FROM(Bool(false)), "(table1.col_bool <=> ?)", false) + +} + +func TestBoolExpressionIS_TRUE(t *testing.T) { + assertClauseSerialize(t, table1ColBool.IS_TRUE(), "table1.col_bool IS TRUE") + assertClauseSerialize(t, (Int(2).EQ(table1ColInt)).IS_TRUE(), + `(? = table1.col_int) IS TRUE`, int64(2)) + assertClauseSerialize(t, (Int(2).EQ(table1ColInt)).IS_TRUE().AND(Int(4).EQ(table2ColInt)), + `((? = table1.col_int) IS TRUE AND (? = table2.col_int))`, int64(2), int64(4)) +} + +func TestBoolExpressionIS_NOT_TRUE(t *testing.T) { + assertClauseSerialize(t, table1ColBool.IS_NOT_TRUE(), "table1.col_bool IS NOT TRUE") +} + +func TestBoolExpressionIS_FALSE(t *testing.T) { + assertClauseSerialize(t, table1ColBool.IS_FALSE(), "table1.col_bool IS FALSE") +} + +func TestBoolExpressionIS_NOT_FALSE(t *testing.T) { + assertClauseSerialize(t, table1ColBool.IS_NOT_FALSE(), "table1.col_bool IS NOT FALSE") +} + +func TestBoolExpressionIS_UNKNOWN(t *testing.T) { + assertClauseSerialize(t, table1ColBool.IS_UNKNOWN(), "table1.col_bool IS UNKNOWN") +} + +func TestBoolExpressionIS_NOT_UNKNOWN(t *testing.T) { + assertClauseSerialize(t, table1ColBool.IS_NOT_UNKNOWN(), "table1.col_bool IS NOT UNKNOWN") +} + +func TestBinaryBoolExpressionAsProjection(t *testing.T) { + boolExpression := Int(2).EQ(Int(3)) + + assertProjectionSerialize(t, boolExpression, "? = ?", int64(2), int64(3)) + assertProjectionSerialize(t, boolExpression.AS("alias_eq_expression"), + `(? = ?) AS "alias_eq_expression"`, int64(2), int64(3)) +} + +func TestBoolLiteral(t *testing.T) { + assertClauseSerialize(t, Bool(true), "?", true) + assertClauseSerialize(t, Bool(false), "?", false) +} + +// +//func TestExists(t *testing.T) { +// +// assertClauseSerialize(t, EXISTS( +// table2. +// SELECT(Int(1)). +// WHERE(table1Col1.EQ(table2Col3)), +// ), +// `(EXISTS ( +// SELECT ? +// FROM db.table2 +// WHERE table1.col1 = table2.col3 +//))`, int64(1)) +//} +// +//func TestBoolExp(t *testing.T) { +// assertClauseSerialize(t, BoolExp(String("true")), "?", "true") +// assertClauseSerialize(t, BoolExp(String("true")).IS_TRUE(), "? IS TRUE", "true") +//} diff --git a/mysql/mysql_cast.go b/mysql/cast.go similarity index 95% rename from mysql/mysql_cast.go rename to mysql/cast.go index bcb853f..2db3273 100644 --- a/mysql/mysql_cast.go +++ b/mysql/cast.go @@ -1,7 +1,7 @@ package mysql import ( - "github.com/go-jet/jet" + "github.com/go-jet/jet/internal/jet" ) type cast interface { diff --git a/mysql/cast_test.go b/mysql/cast_test.go new file mode 100644 index 0000000..26b6426 --- /dev/null +++ b/mysql/cast_test.go @@ -0,0 +1,9 @@ +package mysql + +import ( + "testing" +) + +func TestCAST_AS_DATE(t *testing.T) { + assertClauseSerialize(t, CAST(Int(22)).AS_DATE(), `CAST(? AS DATE)`, int64(22)) +} diff --git a/mysql/column.go b/mysql/column.go new file mode 100644 index 0000000..3727b1b --- /dev/null +++ b/mysql/column.go @@ -0,0 +1,9 @@ +package mysql + +import "github.com/go-jet/jet/internal/jet" + +type Column jet.Column + +type IColumnList jet.IColumnList + +var ColumnList = jet.ColumnList diff --git a/mysql/dialect.go b/mysql/dialect.go new file mode 100644 index 0000000..c653274 --- /dev/null +++ b/mysql/dialect.go @@ -0,0 +1,139 @@ +package mysql + +import ( + "errors" + "github.com/go-jet/jet/internal/jet" +) + +var Dialect = NewDialect() + +func NewDialect() jet.Dialect { + + serializeOverrides := map[string]jet.SerializeOverride{} + serializeOverrides["IS DISTINCT FROM"] = mysql_IS_DISTINCT_FROM + serializeOverrides["IS NOT DISTINCT FROM"] = mysql_IS_NOT_DISTINCT_FROM + serializeOverrides["/"] = mysql_DIVISION + serializeOverrides["#"] = mysql_BIT_XOR + + mySQLDialectParams := jet.DialectParams{ + Name: "MySQL", + PackageName: "mysql", + SerializeOverrides: serializeOverrides, + AliasQuoteChar: '"', + IdentifierQuoteChar: '`', + ArgumentPlaceholder: func(int) string { + return "?" + }, + UpdateAssigment: mysqlUpdateAssigment, + SupportsReturning: false, + } + + return jet.NewDialect(mySQLDialectParams) +} + +func mysqlUpdateAssigment(columns []jet.IColumn, values []jet.Clause, out *jet.SqlBuilder) (err error) { + + if len(columns) != len(values) { + return errors.New("jet: mismatch in numers of columns and values") + } + + for i, column := range columns { + if i > 0 { + out.WriteString(", ") + } + + out.WriteString(column.Name()) + + out.WriteString(" = ") + + if err = jet.Serialize(values[i], jet.UpdateStatementType, out); err != nil { + return err + } + } + + return nil +} + +func mysql_BIT_XOR(expressions ...jet.Expression) jet.SerializeFunc { + return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) error { + if len(expressions) != 2 { + return errors.New("jet: invalid number of expressions for operator") + } + + lhs := expressions[0] + rhs := expressions[1] + + if err := jet.Serialize(lhs, statement, out, options...); err != nil { + return err + } + + out.WriteString("^") + + if err := jet.Serialize(rhs, statement, out, options...); err != nil { + return err + } + return nil + } +} + +func mysql_DIVISION(expressions ...jet.Expression) jet.SerializeFunc { + return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) error { + if len(expressions) != 2 { + return errors.New("jet: invalid number of expressions for operator") + } + + lhs := expressions[0] + rhs := expressions[1] + + if err := jet.Serialize(lhs, statement, out, options...); err != nil { + return err + } + + _, isLhsInt := lhs.(IntegerExpression) + _, isRhsInt := rhs.(IntegerExpression) + + if isLhsInt && isRhsInt { + out.WriteString("DIV") + } else { + out.WriteString("/") + } + + if err := jet.Serialize(rhs, statement, out, options...); err != nil { + return err + } + return nil + } +} + +func mysql_IS_NOT_DISTINCT_FROM(expressions ...jet.Expression) jet.SerializeFunc { + return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) error { + if len(expressions) != 2 { + return errors.New("jet: invalid number of expressions for operator") + } + if err := jet.Serialize(expressions[0], statement, out); err != nil { + return err + } + + out.WriteString("<=>") + + if err := jet.Serialize(expressions[1], statement, out); err != nil { + return err + } + + return nil + } +} + +func mysql_IS_DISTINCT_FROM(expressions ...jet.Expression) jet.SerializeFunc { + return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) error { + out.WriteString("NOT") + + err := mysql_IS_NOT_DISTINCT_FROM(expressions...)(statement, out, options...) + + if err != nil { + return err + } + + return nil + } +} diff --git a/mysql/expressions.go b/mysql/expressions.go new file mode 100644 index 0000000..7fe386b --- /dev/null +++ b/mysql/expressions.go @@ -0,0 +1,21 @@ +package mysql + +import "github.com/go-jet/jet/internal/jet" + +type Expression jet.Expression + +type BoolExpression jet.BoolExpression + +type StringExpression jet.StringExpression + +type IntegerExpression jet.IntegerExpression + +type FloatExpression jet.FloatExpression + +type DateExpression jet.DateExpression + +type DateTimeExpression jet.TimestampExpression + +type TimestampExpression jet.TimestampExpression + +type TimeExpression jet.TimeExpression diff --git a/mysql/integer_expression_test.go b/mysql/integer_expression_test.go new file mode 100644 index 0000000..f7902e3 --- /dev/null +++ b/mysql/integer_expression_test.go @@ -0,0 +1,107 @@ +package mysql + +import ( + "testing" +) + +func TestIntegerExpressionEQ(t *testing.T) { + assertClauseSerialize(t, table1ColInt.EQ(table2ColInt), "(table1.col_int = table2.col_int)") + assertClauseSerialize(t, table1ColInt.EQ(Int(11)), "(table1.col_int = ?)", int64(11)) +} + +func TestIntegerExpressionNOT_EQ(t *testing.T) { + assertClauseSerialize(t, table1ColInt.NOT_EQ(table2ColInt), "(table1.col_int != table2.col_int)") + assertClauseSerialize(t, table1ColInt.NOT_EQ(Int(11)), "(table1.col_int != ?)", int64(11)) +} + +func TestIntegerExpressionGT(t *testing.T) { + assertClauseSerialize(t, table1ColInt.GT(table2ColInt), "(table1.col_int > table2.col_int)") + assertClauseSerialize(t, table1ColInt.GT(Int(11)), "(table1.col_int > ?)", int64(11)) +} + +func TestIntegerExpressionGT_EQ(t *testing.T) { + assertClauseSerialize(t, table1ColInt.GT_EQ(table2ColInt), "(table1.col_int >= table2.col_int)") + assertClauseSerialize(t, table1ColInt.GT_EQ(Int(11)), "(table1.col_int >= ?)", int64(11)) +} + +func TestIntegerExpressionLT(t *testing.T) { + assertClauseSerialize(t, table1ColInt.LT(table2ColInt), "(table1.col_int < table2.col_int)") + assertClauseSerialize(t, table1ColInt.LT(Int(11)), "(table1.col_int < ?)", int64(11)) +} + +func TestIntegerExpressionLT_EQ(t *testing.T) { + assertClauseSerialize(t, table1ColInt.LT_EQ(table2ColInt), "(table1.col_int <= table2.col_int)") + assertClauseSerialize(t, table1ColInt.LT_EQ(Int(11)), "(table1.col_int <= ?)", int64(11)) +} + +func TestIntegerExpressionADD(t *testing.T) { + assertClauseSerialize(t, table1ColInt.ADD(table2ColInt), "(table1.col_int + table2.col_int)") + assertClauseSerialize(t, table1ColInt.ADD(Int(11)), "(table1.col_int + ?)", int64(11)) +} + +func TestIntegerExpressionSUB(t *testing.T) { + assertClauseSerialize(t, table1ColInt.SUB(table2ColInt), "(table1.col_int - table2.col_int)") + assertClauseSerialize(t, table1ColInt.SUB(Int(11)), "(table1.col_int - ?)", int64(11)) +} + +func TestIntegerExpressionMUL(t *testing.T) { + assertClauseSerialize(t, table1ColInt.MUL(table2ColInt), "(table1.col_int * table2.col_int)") + assertClauseSerialize(t, table1ColInt.MUL(Int(11)), "(table1.col_int * ?)", int64(11)) +} + +func TestIntegerExpressionDIV(t *testing.T) { + assertClauseSerialize(t, table1ColInt.DIV(table2ColInt), "(table1.col_int DIV table2.col_int)") + assertClauseSerialize(t, table1ColInt.DIV(Int(11)), "(table1.col_int DIV ?)", int64(11)) +} + +func TestIntExpressionMOD(t *testing.T) { + assertClauseSerialize(t, table1ColInt.MOD(table2ColInt), "(table1.col_int % table2.col_int)") + assertClauseSerialize(t, table1ColInt.MOD(Int(11)), "(table1.col_int % ?)", int64(11)) +} + +func TestIntExpressionPOW(t *testing.T) { + assertClauseSerialize(t, table1ColInt.POW(table2ColInt), "POW(table1.col_int, table2.col_int)") + assertClauseSerialize(t, table1ColInt.POW(Int(11)), "POW(table1.col_int, ?)", int64(11)) +} + +func TestIntExpressionBIT_NOT(t *testing.T) { + assertClauseSerialize(t, BIT_NOT(table2ColInt), "(~ table2.col_int)") + assertClauseSerialize(t, BIT_NOT(Int(11)), "(~ ?)", int64(11)) +} + +func TestIntExpressionBIT_AND(t *testing.T) { + assertClauseSerialize(t, table1ColInt.BIT_AND(table2ColInt), "(table1.col_int & table2.col_int)") + assertClauseSerialize(t, table1ColInt.BIT_AND(Int(11)), "(table1.col_int & ?)", int64(11)) +} + +func TestIntExpressionBIT_OR(t *testing.T) { + assertClauseSerialize(t, table1ColInt.BIT_OR(table2ColInt), "(table1.col_int | table2.col_int)") + assertClauseSerialize(t, table1ColInt.BIT_OR(Int(11)), "(table1.col_int | ?)", int64(11)) +} + +func TestIntExpressionBIT_XOR(t *testing.T) { + assertClauseSerialize(t, table1ColInt.BIT_XOR(table2ColInt), "(table1.col_int ^ table2.col_int)") + assertClauseSerialize(t, table1ColInt.BIT_XOR(Int(11)), "(table1.col_int ^ ?)", int64(11)) +} + +func TestIntExpressionBIT_SHIFT_LEFT(t *testing.T) { + assertClauseSerialize(t, table1ColInt.BIT_SHIFT_LEFT(table2ColInt), "(table1.col_int << table2.col_int)") + assertClauseSerialize(t, table1ColInt.BIT_SHIFT_LEFT(Int(11)), "(table1.col_int << ?)", int64(11)) +} + +func TestIntExpressionBIT_SHIFT_RIGHT(t *testing.T) { + assertClauseSerialize(t, table1ColInt.BIT_SHIFT_RIGHT(table2ColInt), "(table1.col_int >> table2.col_int)") + assertClauseSerialize(t, table1ColInt.BIT_SHIFT_RIGHT(Int(11)), "(table1.col_int >> ?)", int64(11)) +} + +// +//func TestIntExpressionIntExp(t *testing.T) { +// assertClauseSerialize(t, IntExp(table1ColFloat), "table1.col_float") +// assertClauseSerialize(t, IntExp(table1ColFloat.ADD(table2ColFloat)).ADD(Int(11)), +// "((table1.col_float + table2.col_float) + ?)", int64(11)) +//} + +func TestIntExpression_MINUSi(t *testing.T) { + assertClauseSerialize(t, MINUSi(table2ColInt), "(- table2.col_int)") + assertClauseSerialize(t, MINUSi(Int(3)), "(- ?)", int64(3)) +} diff --git a/mysql/mysql_cast_test.go b/mysql/mysql_cast_test.go deleted file mode 100644 index bf544a1..0000000 --- a/mysql/mysql_cast_test.go +++ /dev/null @@ -1,11 +0,0 @@ -package mysql - -import ( - "github.com/go-jet/jet" - "testing" -) - -func TestCAST_AS_DATE(t *testing.T) { - - jet.AssertMySQLClauseSerialize(t, CAST(Int(22)).AS_DATE(), `CAST(? AS DATE)`, int64(22)) -} diff --git a/mysql/table.go b/mysql/table.go new file mode 100644 index 0000000..8eee2b2 --- /dev/null +++ b/mysql/table.go @@ -0,0 +1,9 @@ +package mysql + +import "github.com/go-jet/jet/internal/jet" + +type Table jet.Table + +func NewTable(schemaName, name string, columns ...jet.Column) Table { + return jet.NewTable(Dialect, schemaName, name, columns...) +} diff --git a/mysql/testutils.go b/mysql/testutils.go new file mode 100644 index 0000000..3ac9749 --- /dev/null +++ b/mysql/testutils.go @@ -0,0 +1,104 @@ +package mysql + +import ( + "github.com/go-jet/jet/internal/jet" + "gotest.tools/assert" + "testing" +) + +var table1Col1 = IntegerColumn("col1") +var table1ColInt = IntegerColumn("col_int") +var table1ColFloat = FloatColumn("col_float") +var table1Col3 = IntegerColumn("col3") +var table1ColTimestamp = TimestampColumn("col_timestamp") +var table1ColBool = BoolColumn("col_bool") +var table1ColDate = DateColumn("col_date") + +var table1 = NewTable( + "db", + "table1", + table1Col1, + table1ColInt, + table1ColFloat, + table1Col3, + table1ColBool, + table1ColDate, + table1ColTimestamp, +) + +var table2Col3 = IntegerColumn("col3") +var table2Col4 = IntegerColumn("col4") +var table2ColInt = IntegerColumn("col_int") +var table2ColFloat = FloatColumn("col_float") +var table2ColStr = StringColumn("col_str") +var table2ColBool = BoolColumn("col_bool") +var table2ColTimestamp = TimestampColumn("col_timestamp") +var table2ColDate = DateColumn("col_date") + +var table2 = NewTable( + "db", + "table2", + table2Col3, + table2Col4, + table2ColInt, + table2ColFloat, + table2ColStr, + table2ColBool, + table2ColDate, + table2ColTimestamp, +) + +var table3Col1 = IntegerColumn("col1") +var table3ColInt = IntegerColumn("col_int") +var table3StrCol = StringColumn("col2") +var table3 = NewTable( + "db", + "table3", + table3Col1, + table3ColInt, + table3StrCol) + +func assertClauseSerialize(t *testing.T, clause jet.Clause, query string, args ...interface{}) { + out := jet.SqlBuilder{Dialect: Dialect} + err := jet.Serialize(clause, jet.SelectStatementType, &out) + + assert.NilError(t, err) + + assert.DeepEqual(t, out.Buff.String(), query) + assert.DeepEqual(t, out.Args, args) +} + +func assertClauseSerializeErr(t *testing.T, clause jet.Clause, errString string) { + out := jet.SqlBuilder{Dialect: Dialect} + err := jet.Serialize(clause, jet.SelectStatementType, &out) + + //fmt.Println(out.buff.String()) + assert.Assert(t, err != nil) + assert.Error(t, err, errString) +} + +func assertProjectionSerialize(t *testing.T, projection jet.Projection, query string, args ...interface{}) { + out := jet.SqlBuilder{Dialect: Dialect} + err := jet.SerializeForProjection(projection, jet.SelectStatementType, &out) + + assert.NilError(t, err) + + assert.DeepEqual(t, out.Buff.String(), query) + assert.DeepEqual(t, out.Args, args) +} + +func assertStatement(t *testing.T, query jet.Statement, expectedQuery string, expectedArgs ...interface{}) { + queryStr, args, err := query.Sql() + assert.NilError(t, err) + + //fmt.Println(queryStr) + assert.Equal(t, queryStr, expectedQuery) + assert.DeepEqual(t, args, expectedArgs) +} + +func assertStatementErr(t *testing.T, stmt jet.Statement, errorStr string) { + _, _, err := stmt.Sql() + + assert.Assert(t, err != nil) + assert.Error(t, err, errorStr) +} diff --git a/mysql/mysql_types.go b/mysql/types.go similarity index 80% rename from mysql/mysql_types.go rename to mysql/types.go index 87b5612..b3652de 100644 --- a/mysql/mysql_types.go +++ b/mysql/types.go @@ -1,53 +1,42 @@ package mysql -import "github.com/go-jet/jet" - -type Expression jet.Expression +import "github.com/go-jet/jet/internal/jet" type ColumnBool jet.ColumnBool -type BoolExpression jet.BoolExpression var BoolColumn = jet.BoolColumn var Bool = jet.Bool type ColumnString jet.ColumnString -type StringExpression jet.StringExpression var StringColumn = jet.StringColumn var String = jet.String type ColumnInteger jet.ColumnInteger -type IntegerExpression jet.IntegerExpression var IntegerColumn = jet.IntegerColumn var Int = jet.Int type ColumnFloat jet.ColumnFloat -type FloatExpression jet.FloatExpression var FloatColumn = jet.FloatColumn var Float = jet.Float type ColumnDate jet.ColumnDate -type DateExpression jet.DateExpression var DateColumn = jet.DateColumn var Date = jet.Date type ColumnDateTime jet.ColumnTimestamp -type DateTimeExpression jet.TimestampExpression var DateTimeColumn = jet.TimestampColumn var DateTime = jet.Timestamp type ColumnTimestamp jet.ColumnTimestamp -type TimestampExpression jet.TimestampExpression var TimestampColumn = jet.TimestampColumn var Timestamp = jet.Timestamp -type TimeExpression jet.TimeExpression - // ----------------- FUNCTIONS ----------------------// var ABSf = jet.ABSf diff --git a/postgres/date_expression_test.go b/postgres/date_expression_test.go index ff37d76..2909278 100644 --- a/postgres/date_expression_test.go +++ b/postgres/date_expression_test.go @@ -1,48 +1,47 @@ package postgres import ( - "github.com/go-jet/jet" "testing" ) var dateVar = Date(2000, 12, 30) func TestDateExpressionEQ(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, table1ColDate.EQ(table2ColDate), "(table1.col_date = table2.col_date)") - jet.AssertPostgreClauseSerialize(t, table1ColDate.EQ(dateVar), "(table1.col_date = $1::DATE)", "2000-12-30") + assertClauseSerialize(t, table1ColDate.EQ(table2ColDate), "(table1.col_date = table2.col_date)") + assertClauseSerialize(t, table1ColDate.EQ(dateVar), "(table1.col_date = $1::DATE)", "2000-12-30") } func TestDateExpressionNOT_EQ(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, table1ColDate.NOT_EQ(table2ColDate), "(table1.col_date != table2.col_date)") - jet.AssertPostgreClauseSerialize(t, table1ColDate.NOT_EQ(dateVar), "(table1.col_date != $1::DATE)", "2000-12-30") + assertClauseSerialize(t, table1ColDate.NOT_EQ(table2ColDate), "(table1.col_date != table2.col_date)") + assertClauseSerialize(t, table1ColDate.NOT_EQ(dateVar), "(table1.col_date != $1::DATE)", "2000-12-30") } func TestDateExpressionIS_DISTINCT_FROM(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, table1ColDate.IS_DISTINCT_FROM(table2ColDate), "(table1.col_date IS DISTINCT FROM table2.col_date)") - jet.AssertPostgreClauseSerialize(t, table1ColDate.IS_DISTINCT_FROM(dateVar), "(table1.col_date IS DISTINCT FROM $1::DATE)", "2000-12-30") + assertClauseSerialize(t, table1ColDate.IS_DISTINCT_FROM(table2ColDate), "(table1.col_date IS DISTINCT FROM table2.col_date)") + assertClauseSerialize(t, table1ColDate.IS_DISTINCT_FROM(dateVar), "(table1.col_date IS DISTINCT FROM $1::DATE)", "2000-12-30") } func TestDateExpressionIS_NOT_DISTINCT_FROM(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, table1ColDate.IS_NOT_DISTINCT_FROM(table2ColDate), "(table1.col_date IS NOT DISTINCT FROM table2.col_date)") - jet.AssertPostgreClauseSerialize(t, table1ColDate.IS_NOT_DISTINCT_FROM(dateVar), "(table1.col_date IS NOT DISTINCT FROM $1::DATE)", "2000-12-30") + assertClauseSerialize(t, table1ColDate.IS_NOT_DISTINCT_FROM(table2ColDate), "(table1.col_date IS NOT DISTINCT FROM table2.col_date)") + assertClauseSerialize(t, table1ColDate.IS_NOT_DISTINCT_FROM(dateVar), "(table1.col_date IS NOT DISTINCT FROM $1::DATE)", "2000-12-30") } func TestDateExpressionGT(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, table1ColDate.GT(table2ColDate), "(table1.col_date > table2.col_date)") - jet.AssertPostgreClauseSerialize(t, table1ColDate.GT(dateVar), "(table1.col_date > $1::DATE)", "2000-12-30") + assertClauseSerialize(t, table1ColDate.GT(table2ColDate), "(table1.col_date > table2.col_date)") + assertClauseSerialize(t, table1ColDate.GT(dateVar), "(table1.col_date > $1::DATE)", "2000-12-30") } func TestDateExpressionGT_EQ(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, table1ColDate.GT_EQ(table2ColDate), "(table1.col_date >= table2.col_date)") - jet.AssertPostgreClauseSerialize(t, table1ColDate.GT_EQ(dateVar), "(table1.col_date >= $1::DATE)", "2000-12-30") + assertClauseSerialize(t, table1ColDate.GT_EQ(table2ColDate), "(table1.col_date >= table2.col_date)") + assertClauseSerialize(t, table1ColDate.GT_EQ(dateVar), "(table1.col_date >= $1::DATE)", "2000-12-30") } func TestDateExpressionLT(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, table1ColDate.LT(table2ColDate), "(table1.col_date < table2.col_date)") - jet.AssertPostgreClauseSerialize(t, table1ColDate.LT(dateVar), "(table1.col_date < $1::DATE)", "2000-12-30") + assertClauseSerialize(t, table1ColDate.LT(table2ColDate), "(table1.col_date < table2.col_date)") + assertClauseSerialize(t, table1ColDate.LT(dateVar), "(table1.col_date < $1::DATE)", "2000-12-30") } func TestDateExpressionLT_EQ(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, table1ColDate.LT_EQ(table2ColDate), "(table1.col_date <= table2.col_date)") - jet.AssertPostgreClauseSerialize(t, table1ColDate.LT_EQ(dateVar), "(table1.col_date <= $1::DATE)", "2000-12-30") + assertClauseSerialize(t, table1ColDate.LT_EQ(table2ColDate), "(table1.col_date <= table2.col_date)") + assertClauseSerialize(t, table1ColDate.LT_EQ(dateVar), "(table1.col_date <= $1::DATE)", "2000-12-30") } diff --git a/postgres/dialect.go b/postgres/dialect.go new file mode 100644 index 0000000..0c7b217 --- /dev/null +++ b/postgres/dialect.go @@ -0,0 +1,70 @@ +package postgres + +import ( + "github.com/go-jet/jet/internal/jet" + "strconv" +) + +var Dialect = NewDialect() + +func NewDialect() jet.Dialect { + + dialectParams := jet.DialectParams{ + Name: "PostgreSQL", + PackageName: "postgres", + CastOverride: castFunc, + AliasQuoteChar: '"', + IdentifierQuoteChar: '"', + ArgumentPlaceholder: func(ord int) string { + return "$" + strconv.Itoa(ord) + }, + UpdateAssigment: postgresUpdateAssigment, + SupportsReturning: true, + } + + return jet.NewDialect(dialectParams) +} + +func castFunc(expression jet.Expression, castType string) jet.SerializeFunc { + return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) error { + if err := jet.Serialize(expression, statement, out, options...); err != nil { + return err + } + out.WriteString("::" + castType) + return nil + } +} + +func postgresUpdateAssigment(columns []jet.IColumn, values []jet.Clause, out *jet.SqlBuilder) (err error) { + if len(columns) > 1 { + out.WriteString("(") + } + + err = jet.SerializeColumnNames(columns, out) + + if err != nil { + return + } + + if len(columns) > 1 { + out.WriteString(")") + } + + out.WriteString("=") + + if len(values) > 1 { + out.WriteString("(") + } + + err = jet.SerializeClauseList(jet.UpdateStatementType, values, out) + + if err != nil { + return + } + + if len(values) > 1 { + out.WriteString(")") + } + + return +} diff --git a/postgres/expressions.go b/postgres/expressions.go new file mode 100644 index 0000000..1b8faa9 --- /dev/null +++ b/postgres/expressions.go @@ -0,0 +1,5 @@ +package postgres + +import "github.com/go-jet/jet/internal/jet" + +type Expression jet.Expression diff --git a/postgres/postgres_cast.go b/postgres/postgres_cast.go index 2074f89..4f23530 100644 --- a/postgres/postgres_cast.go +++ b/postgres/postgres_cast.go @@ -2,7 +2,7 @@ package postgres import ( "fmt" - "github.com/go-jet/jet" + "github.com/go-jet/jet/internal/jet" ) type cast interface { @@ -37,7 +37,7 @@ type castImpl struct { jet.CastImpl } -func CAST(expr jet.Expression) cast { +func CAST(expr Expression) cast { castImpl := &castImpl{} castImpl.CastImpl = jet.NewCastImpl(expr) diff --git a/postgres/postgres_cast_test.go b/postgres/postgres_cast_test.go index 87a9e26..297e327 100644 --- a/postgres/postgres_cast_test.go +++ b/postgres/postgres_cast_test.go @@ -1,65 +1,64 @@ package postgres import ( - "github.com/go-jet/jet" "testing" ) func TestExpressionCAST_AS(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, CAST(String("test")).AS("text"), `$1::text`, "test") + assertClauseSerialize(t, CAST(String("test")).AS("text"), `$1::text`, "test") } func TestExpressionCAST_AS_BOOL(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, CAST(Int(1)).AS_BOOL(), "$1::boolean", int64(1)) - jet.AssertPostgreClauseSerialize(t, CAST(table2Col3).AS_BOOL(), "table2.col3::boolean") - jet.AssertPostgreClauseSerialize(t, CAST(table2Col3.ADD(table2Col3)).AS_BOOL(), "(table2.col3 + table2.col3)::boolean") + 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") } func TestExpressionCAST_AS_SMALLINT(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, CAST(table2Col3).AS_SMALLINT(), "table2.col3::smallint") + assertClauseSerialize(t, CAST(table2Col3).AS_SMALLINT(), "table2.col3::smallint") } func TestExpressionCAST_AS_INTEGER(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, CAST(table2Col3).AS_INTEGER(), "table2.col3::integer") + assertClauseSerialize(t, CAST(table2Col3).AS_INTEGER(), "table2.col3::integer") } func TestExpressionCAST_AS_BIGINT(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, CAST(table2Col3).AS_BIGINT(), "table2.col3::bigint") + assertClauseSerialize(t, CAST(table2Col3).AS_BIGINT(), "table2.col3::bigint") } func TestExpressionCAST_AS_NUMERIC(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, CAST(table2Col3).AS_NUMERIC(11, 11), "table2.col3::numeric(11, 11)") - jet.AssertPostgreClauseSerialize(t, CAST(table2Col3).AS_NUMERIC(11), "table2.col3::numeric(11)") + assertClauseSerialize(t, CAST(table2Col3).AS_NUMERIC(11, 11), "table2.col3::numeric(11, 11)") + assertClauseSerialize(t, CAST(table2Col3).AS_NUMERIC(11), "table2.col3::numeric(11)") } func TestExpressionCAST_AS_REAL(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, CAST(table2Col3).AS_REAL(), "table2.col3::real") + assertClauseSerialize(t, CAST(table2Col3).AS_REAL(), "table2.col3::real") } func TestExpressionCAST_AS_DOUBLE(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, CAST(table2Col3).AS_DOUBLE(), "table2.col3::double precision") + assertClauseSerialize(t, CAST(table2Col3).AS_DOUBLE(), "table2.col3::double precision") } func TestExpressionCAST_AS_TEXT(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, CAST(table2Col3).AS_TEXT(), "table2.col3::text") + assertClauseSerialize(t, CAST(table2Col3).AS_TEXT(), "table2.col3::text") } func TestExpressionCAST_AS_DATE(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, CAST(table2Col3).AS_DATE(), "table2.col3::DATE") + assertClauseSerialize(t, CAST(table2Col3).AS_DATE(), "table2.col3::DATE") } func TestExpressionCAST_AS_TIME(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, CAST(table2Col3).AS_TIME(), "table2.col3::time without time zone") + assertClauseSerialize(t, CAST(table2Col3).AS_TIME(), "table2.col3::time without time zone") } func TestExpressionCAST_AS_TIMEZ(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, CAST(table2Col3).AS_TIMEZ(), "table2.col3::time with time zone") + assertClauseSerialize(t, CAST(table2Col3).AS_TIMEZ(), "table2.col3::time with time zone") } func TestExpressionCAST_AS_TIMESTAMP(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, CAST(table2Col3).AS_TIMESTAMP(), "table2.col3::timestamp without time zone") + assertClauseSerialize(t, CAST(table2Col3).AS_TIMESTAMP(), "table2.col3::timestamp without time zone") } func TestExpressionCAST_AS_TIMESTAMPZ(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, CAST(table2Col3).AS_TIMESTAMPZ(), "table2.col3::timestamp with time zone") + assertClauseSerialize(t, CAST(table2Col3).AS_TIMESTAMPZ(), "table2.col3::timestamp with time zone") } diff --git a/postgres/postgres_column.go b/postgres/postgres_column.go new file mode 100644 index 0000000..a4ee133 --- /dev/null +++ b/postgres/postgres_column.go @@ -0,0 +1,9 @@ +package postgres + +import "github.com/go-jet/jet/internal/jet" + +type Column jet.Column + +type IColumnList jet.IColumnList + +var ColumnList = jet.ColumnList diff --git a/postgres/postgres_enum.go b/postgres/postgres_enum.go new file mode 100644 index 0000000..1d3ebc7 --- /dev/null +++ b/postgres/postgres_enum.go @@ -0,0 +1,5 @@ +package postgres + +import "github.com/go-jet/jet/internal/jet" + +var NewEnumValue = jet.NewEnumValue diff --git a/postgres/postgres_expressions.go b/postgres/postgres_expressions.go new file mode 100644 index 0000000..ca4d6ea --- /dev/null +++ b/postgres/postgres_expressions.go @@ -0,0 +1,5 @@ +package postgres + +import "github.com/go-jet/jet/internal/jet" + +var RAW = jet.RAW diff --git a/postgres/postgres_functions.go b/postgres/postgres_functions.go new file mode 100644 index 0000000..750a307 --- /dev/null +++ b/postgres/postgres_functions.go @@ -0,0 +1,93 @@ +package postgres + +import "github.com/go-jet/jet/internal/jet" + +var ROW = jet.ROW + +// ------------------ Mathematical functions ---------------// + +var ABSf = jet.ABSf +var ABSi = jet.ABSi +var POW = jet.POW +var POWER = jet.POWER +var SQRT = jet.SQRT +var CBRT = jet.CBRT +var CEIL = jet.CEIL +var FLOOR = jet.FLOOR +var ROUND = jet.ROUND +var SIGN = jet.SIGN +var TRUNC = jet.TRUNC +var LN = jet.LN +var LOG = jet.LOG + +// ----------------- Aggregate functions -------------------// + +var AVG = jet.AVG +var BIT_AND = jet.BIT_AND +var BIT_OR = jet.BIT_OR +var BOOL_AND = jet.BOOL_AND +var BOOL_OR = jet.BOOL_OR +var COUNT = jet.COUNT +var EVERY = jet.EVERY +var MAXf = jet.MAXf +var MAXi = jet.MAXi +var MINf = jet.MINf +var MINi = jet.MINi +var SUMf = jet.SUMf +var SUMi = jet.SUMi + +//--------------------- String functions ------------------// + +var BIT_LENGTH = jet.BIT_LENGTH +var CHAR_LENGTH = jet.CHAR_LENGTH +var OCTET_LENGTH = jet.OCTET_LENGTH +var LOWER = jet.LOWER +var UPPER = jet.UPPER +var BTRIM = jet.BTRIM +var LTRIM = jet.LTRIM +var RTRIM = jet.RTRIM +var CHR = jet.CHR +var CONVERT = jet.CONVERT +var CONVERT_FROM = jet.CONVERT_FROM +var CONVERT_TO = jet.CONVERT_TO +var ENCODE = jet.ENCODE +var DECODE = jet.DECODE +var INITCAP = jet.INITCAP +var LEFT = jet.LEFT +var RIGHT = jet.RIGHT +var LENGTH = jet.LENGTH +var LPAD = jet.LPAD +var RPAD = jet.RPAD +var MD5 = jet.MD5 +var REPEAT = jet.REPEAT +var REPLACE = jet.REPLACE +var REVERSE = jet.REVERSE +var STRPOS = jet.STRPOS +var SUBSTR = jet.SUBSTR +var TO_ASCII = jet.TO_ASCII +var TO_HEX = jet.TO_HEX + +//----------Data Type Formatting Functions ----------------------// + +var TO_CHAR = jet.TO_CHAR +var TO_DATE = jet.TO_DATE +var TO_NUMBER = jet.TO_NUMBER +var TO_TIMESTAMP = jet.TO_TIMESTAMP + +//----------------- Date/Time Functions and Operators ------------// + +var CURRENT_DATE = jet.CURRENT_DATE +var CURRENT_TIME = jet.CURRENT_TIME +var CURRENT_TIMESTAMP = jet.CURRENT_TIMESTAMP +var LOCALTIME = jet.LOCALTIME +var LOCALTIMESTAMP = jet.LOCALTIMESTAMP +var NOW = jet.NOW + +// --------------- Conditional Expressions Functions -------------// + +var COALESCE = jet.COALESCE +var NULLIF = jet.NULLIF +var GREATEST = jet.GREATEST +var LEAST = jet.LEAST +var EXISTS = jet.EXISTS +var CASE = jet.CASE diff --git a/postgres/postgres_keywords.go b/postgres/postgres_keywords.go new file mode 100644 index 0000000..7a06700 --- /dev/null +++ b/postgres/postgres_keywords.go @@ -0,0 +1,15 @@ +package postgres + +import "github.com/go-jet/jet/internal/jet" + +const ( + // DEFAULT is jet equivalent of SQL DEFAULT + DEFAULT = jet.DEFAULT +) + +var ( + // NULL is jet equivalent of SQL NULL + NULL = jet.NULL + // STAR is jet equivalent of SQL * + STAR = jet.STAR +) diff --git a/postgres/postgres_literal.go b/postgres/postgres_literal.go new file mode 100644 index 0000000..ac33b43 --- /dev/null +++ b/postgres/postgres_literal.go @@ -0,0 +1,27 @@ +package postgres + +import "github.com/go-jet/jet/internal/jet" + +var Bool = jet.Bool +var Int = jet.Int +var Float = jet.Float +var String = jet.String +var Date = func(year, month, day int) DateExpression { + return CAST(jet.Date(year, month, day)).AS_DATE() +} + +var Time = func(hour, minute, second, milliseconds int) TimeExpression { + return CAST(jet.Time(hour, minute, second, milliseconds)).AS_TIME() +} + +var Timez = func(hour, minute, second, milliseconds int, timezone int) TimezExpression { + return CAST(jet.Timez(hour, minute, second, milliseconds, timezone)).AS_TIMEZ() +} + +var Timestamp = func(year, month, day, hour, minute, second, milliseconds int) TimestampExpression { + return CAST(jet.Timestamp(year, month, day, hour, minute, second, milliseconds)).AS_TIMESTAMP() +} + +var Timestampz = func(year, month, day, hour, minute, second, milliseconds int, timezone int) TimestampzExpression { + return CAST(jet.Timestampz(year, month, day, hour, minute, second, milliseconds, timezone)).AS_TIMESTAMPZ() +} diff --git a/postgres/postgres_lock.go b/postgres/postgres_lock.go new file mode 100644 index 0000000..81f95d8 --- /dev/null +++ b/postgres/postgres_lock.go @@ -0,0 +1,21 @@ +package postgres + +import "github.com/go-jet/jet/internal/jet" + +type TableLockMode jet.TableLockMode + +// Lock types for LockStatement. +const ( + LOCK_ACCESS_SHARE = "ACCESS SHARE" + LOCK_ROW_SHARE = "ROW SHARE" + LOCK_ROW_EXCLUSIVE = "ROW EXCLUSIVE" + LOCK_SHARE_UPDATE_EXCLUSIVE = "SHARE UPDATE EXCLUSIVE" + LOCK_SHARE = "SHARE" + LOCK_SHARE_ROW_EXCLUSIVE = "SHARE ROW EXCLUSIVE" + LOCK_EXCLUSIVE = "EXCLUSIVE" + LOCK_ACCESS_EXCLUSIVE = "ACCESS EXCLUSIVE" +) + +type LockStatement jet.LockStatement + +var LOCK = jet.LOCK diff --git a/postgres/postgres_operators.go b/postgres/postgres_operators.go new file mode 100644 index 0000000..2c1eb47 --- /dev/null +++ b/postgres/postgres_operators.go @@ -0,0 +1,13 @@ +package postgres + +import "github.com/go-jet/jet/internal/jet" + +// --------- Arithmetic operators -------------// + +var MINUSi = jet.MINUSi +var MINUSf = jet.MINUSf + +//----------- Logical operators ---------------// + +var NOT = jet.NOT +var BIT_NOT = jet.BIT_NOT diff --git a/postgres/postgres_select.go b/postgres/postgres_select.go new file mode 100644 index 0000000..a7a2166 --- /dev/null +++ b/postgres/postgres_select.go @@ -0,0 +1,42 @@ +package postgres + +import "github.com/go-jet/jet/internal/jet" + +type SelectStatement jet.SelectStatement + +var SELECT = jet.SELECT + +func UNION(lhs, rhs SelectStatement, selects ...SelectStatement) SelectStatement { + return jet.UNION(lhs, rhs, toJetSelects(selects...)...) +} + +func UNION_ALL(lhs, rhs SelectStatement, selects ...SelectStatement) SelectStatement { + return jet.UNION_ALL(lhs, rhs, toJetSelects(selects...)...) +} + +func INTERSECT(lhs, rhs SelectStatement, selects ...SelectStatement) SelectStatement { + return jet.INTERSECT(lhs, rhs, toJetSelects(selects...)...) +} + +func INTERSECT_ALL(lhs, rhs SelectStatement, selects ...SelectStatement) SelectStatement { + return jet.INTERSECT_ALL(lhs, rhs, toJetSelects(selects...)...) +} + +func toJetSelects(selects ...SelectStatement) []jet.SelectStatement { + ret := []jet.SelectStatement{} + + for _, sel := range selects { + ret = append(ret, sel) + } + + return ret +} + +type SelectLock jet.SelectLock + +var ( + UPDATE = jet.NewSelectLock("UPDATE") + NO_KEY_UPDATE = jet.NewSelectLock("NO KEY UPDATE") + SHARE = jet.NewSelectLock("SHARE") + KEY_SHARE = jet.NewSelectLock("KEY SHARE") +) diff --git a/postgres/postgres_table.go b/postgres/postgres_table.go new file mode 100644 index 0000000..3f5bab8 --- /dev/null +++ b/postgres/postgres_table.go @@ -0,0 +1,9 @@ +package postgres + +import "github.com/go-jet/jet/internal/jet" + +type Table jet.Table + +func NewTable(schemaName, name string, columns ...jet.Column) Table { + return jet.NewTable(Dialect, schemaName, name, columns...) +} diff --git a/postgres/postgres_types.go b/postgres/postgres_types.go index e9340be..b9ba70b 100644 --- a/postgres/postgres_types.go +++ b/postgres/postgres_types.go @@ -1,55 +1,44 @@ package postgres -import "github.com/go-jet/jet" +import "github.com/go-jet/jet/internal/jet" type ColumnBool jet.ColumnBool type BoolExpression jet.BoolExpression var BoolColumn = jet.BoolColumn -var Bool = jet.Bool type ColumnString jet.ColumnString type StringExpression jet.StringExpression var StringColumn = jet.StringColumn -var String = jet.String type ColumnInteger jet.ColumnInteger type IntegerExpression jet.IntegerExpression var IntegerColumn = jet.IntegerColumn -var Int = jet.Int type ColumnFloat jet.ColumnFloat type FloatExpression jet.FloatExpression var FloatColumn = jet.FloatColumn -var Float = jet.Float + var FloatExp = jet.FloatExp type ColumnDate jet.ColumnDate type DateExpression jet.DateExpression var DateColumn = jet.DateColumn -var Date = func(year, month, day int) DateExpression { - return CAST(jet.Date(year, month, day)).AS_DATE() -} type ColumnDateTime jet.ColumnTimestamp type DateTimeExpression jet.TimestampExpression var DateTimeColumn = jet.TimestampColumn -var DateTime = func(year, month, day int) DateExpression { - return CAST(jet.Date(year, month, day)).AS_DATE() -} type TimeExpression jet.TimeExpression type ColumnTime jet.ColumnTime var TimeColumn = jet.TimeColumn -var Time = func(hour, minute, second, milliseconds int) TimeExpression { - return CAST(jet.Time(hour, minute, second, milliseconds)).AS_TIME() -} + var TimeExp = jet.TimeExp type TimezExpression jet.TimezExpression @@ -61,9 +50,7 @@ type ColumnTimestamp jet.ColumnTimestamp type TimestampExpression jet.TimestampExpression var TimestampColumn = jet.TimestampColumn -var Timestamp = func(year, month, day, hour, minute, second, milliseconds int) TimestampExpression { - return CAST(jet.Timestamp(year, month, day, hour, minute, second, milliseconds)).AS_TIMESTAMP() -} + var TimestampExp = jet.TimestampExp type TimestampzExpression jet.TimestampzExpression @@ -71,34 +58,6 @@ type ColumnTimestampz jet.ColumnTimestampz var TimestampzColumn = jet.TimestampzColumn -// ---------------- functions ------------------// - -var MAXf = jet.MAXf -var SUMf = jet.SUMf -var AVG = jet.AVG -var MINf = jet.MINf -var COUNT = jet.COUNT - -var CASE = jet.CASE +type SelectTable jet.SelectTable // ---------------- statements -----------------// - -type SelectStatement jet.SelectStatement - -var SELECT = jet.SELECT - -var UNION = jet.UNION -var UNION_ALL = jet.UNION_ALL -var INTERSECT = jet.INTERSECT -var INTERSECT_ALL = jet.INTERSECT_ALL - -type SelectLock jet.SelectLock - -var ( - UPDATE = jet.NewSelectLock("UPDATE") - NO_KEY_UPDATE = jet.NewSelectLock("NO KEY UPDATE") - SHARE = jet.NewSelectLock("SHARE") - KEY_SHARE = jet.NewSelectLock("KEY SHARE") -) - -var STAR = jet.STAR diff --git a/postgres/testutils.go b/postgres/testutils.go index d4f35ab..d9b6a33 100644 --- a/postgres/testutils.go +++ b/postgres/testutils.go @@ -1,7 +1,9 @@ package postgres import ( - "github.com/go-jet/jet" + "github.com/go-jet/jet/internal/jet" + "gotest.tools/assert" + "testing" ) var table1Col1 = IntegerColumn("col1") @@ -15,8 +17,7 @@ var table1ColTimestampz = TimestampzColumn("col_timestampz") var table1ColBool = BoolColumn("col_bool") var table1ColDate = DateColumn("col_date") -var table1 = jet.NewTable( - jet.PostgreSQL, +var table1 = NewTable( "db", "table1", table1Col1, @@ -43,8 +44,7 @@ var table2ColTimestamp = TimestampColumn("col_timestamp") var table2ColTimestampz = TimestampzColumn("col_timestampz") var table2ColDate = DateColumn("col_date") -var table2 = jet.NewTable( - jet.PostgreSQL, +var table2 = NewTable( "db", "table2", table2Col3, @@ -63,10 +63,54 @@ var table2 = jet.NewTable( var table3Col1 = IntegerColumn("col1") var table3ColInt = IntegerColumn("col_int") var table3StrCol = StringColumn("col2") -var table3 = jet.NewTable( - jet.PostgreSQL, +var table3 = NewTable( "db", "table3", table3Col1, table3ColInt, table3StrCol) + +func assertClauseSerialize(t *testing.T, clause jet.Clause, query string, args ...interface{}) { + out := jet.SqlBuilder{Dialect: Dialect} + err := jet.Serialize(clause, jet.SelectStatementType, &out) + + assert.NilError(t, err) + + assert.DeepEqual(t, out.Buff.String(), query) + assert.DeepEqual(t, out.Args, args) +} + +func assertClauseSerializeErr(t *testing.T, clause jet.Clause, errString string) { + out := jet.SqlBuilder{Dialect: Dialect} + err := jet.Serialize(clause, jet.SelectStatementType, &out) + + //fmt.Println(out.buff.String()) + assert.Assert(t, err != nil) + assert.Error(t, err, errString) +} + +func assertProjectionSerialize(t *testing.T, projection jet.Projection, query string, args ...interface{}) { + out := jet.SqlBuilder{Dialect: Dialect} + err := jet.SerializeForProjection(projection, jet.SelectStatementType, &out) + + assert.NilError(t, err) + + assert.DeepEqual(t, out.Buff.String(), query) + assert.DeepEqual(t, out.Args, args) +} + +func assertStatement(t *testing.T, query jet.Statement, expectedQuery string, expectedArgs ...interface{}) { + queryStr, args, err := query.Sql() + assert.NilError(t, err) + + //fmt.Println(queryStr) + assert.Equal(t, queryStr, expectedQuery) + assert.DeepEqual(t, args, expectedArgs) +} + +func assertStatementErr(t *testing.T, stmt jet.Statement, errorStr string) { + _, _, err := stmt.Sql() + + assert.Assert(t, err != nil) + assert.Error(t, err, errorStr) +} diff --git a/postgres/time_expression_test.go b/postgres/time_expression_test.go index 7d7688c..c7cbf0c 100644 --- a/postgres/time_expression_test.go +++ b/postgres/time_expression_test.go @@ -1,54 +1,53 @@ package postgres import ( - "github.com/go-jet/jet" "testing" ) var timeVar = Time(10, 20, 0, 0) func TestTimeExpressionEQ(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, table1ColTime.EQ(table2ColTime), "(table1.col_time = table2.col_time)") - jet.AssertPostgreClauseSerialize(t, table1ColTime.EQ(timeVar), "(table1.col_time = $1::time without time zone)", "10:20:00.000") + assertClauseSerialize(t, table1ColTime.EQ(table2ColTime), "(table1.col_time = table2.col_time)") + assertClauseSerialize(t, table1ColTime.EQ(timeVar), "(table1.col_time = $1::time without time zone)", "10:20:00.000") } func TestTimeExpressionNOT_EQ(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, table1ColTime.NOT_EQ(table2ColTime), "(table1.col_time != table2.col_time)") - jet.AssertPostgreClauseSerialize(t, table1ColTime.NOT_EQ(timeVar), "(table1.col_time != $1::time without time zone)", "10:20:00.000") + assertClauseSerialize(t, table1ColTime.NOT_EQ(table2ColTime), "(table1.col_time != table2.col_time)") + assertClauseSerialize(t, table1ColTime.NOT_EQ(timeVar), "(table1.col_time != $1::time without time zone)", "10:20:00.000") } func TestTimeExpressionIS_DISTINCT_FROM(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, table1ColTime.IS_DISTINCT_FROM(table2ColTime), "(table1.col_time IS DISTINCT FROM table2.col_time)") - jet.AssertPostgreClauseSerialize(t, table1ColTime.IS_DISTINCT_FROM(timeVar), "(table1.col_time IS DISTINCT FROM $1::time without time zone)", "10:20:00.000") + assertClauseSerialize(t, table1ColTime.IS_DISTINCT_FROM(table2ColTime), "(table1.col_time IS DISTINCT FROM table2.col_time)") + assertClauseSerialize(t, table1ColTime.IS_DISTINCT_FROM(timeVar), "(table1.col_time IS DISTINCT FROM $1::time without time zone)", "10:20:00.000") } func TestTimeExpressionIS_NOT_DISTINCT_FROM(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, table1ColTime.IS_NOT_DISTINCT_FROM(table2ColTime), "(table1.col_time IS NOT DISTINCT FROM table2.col_time)") - jet.AssertPostgreClauseSerialize(t, table1ColTime.IS_NOT_DISTINCT_FROM(timeVar), "(table1.col_time IS NOT DISTINCT FROM $1::time without time zone)", "10:20:00.000") + assertClauseSerialize(t, table1ColTime.IS_NOT_DISTINCT_FROM(table2ColTime), "(table1.col_time IS NOT DISTINCT FROM table2.col_time)") + assertClauseSerialize(t, table1ColTime.IS_NOT_DISTINCT_FROM(timeVar), "(table1.col_time IS NOT DISTINCT FROM $1::time without time zone)", "10:20:00.000") } func TestTimeExpressionLT(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, table1ColTime.LT(table2ColTime), "(table1.col_time < table2.col_time)") - jet.AssertPostgreClauseSerialize(t, table1ColTime.LT(timeVar), "(table1.col_time < $1::time without time zone)", "10:20:00.000") + assertClauseSerialize(t, table1ColTime.LT(table2ColTime), "(table1.col_time < table2.col_time)") + assertClauseSerialize(t, table1ColTime.LT(timeVar), "(table1.col_time < $1::time without time zone)", "10:20:00.000") } func TestTimeExpressionLT_EQ(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, table1ColTime.LT_EQ(table2ColTime), "(table1.col_time <= table2.col_time)") - jet.AssertPostgreClauseSerialize(t, table1ColTime.LT_EQ(timeVar), "(table1.col_time <= $1::time without time zone)", "10:20:00.000") + assertClauseSerialize(t, table1ColTime.LT_EQ(table2ColTime), "(table1.col_time <= table2.col_time)") + assertClauseSerialize(t, table1ColTime.LT_EQ(timeVar), "(table1.col_time <= $1::time without time zone)", "10:20:00.000") } func TestTimeExpressionGT(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, table1ColTime.GT(table2ColTime), "(table1.col_time > table2.col_time)") - jet.AssertPostgreClauseSerialize(t, table1ColTime.GT(timeVar), "(table1.col_time > $1::time without time zone)", "10:20:00.000") + assertClauseSerialize(t, table1ColTime.GT(table2ColTime), "(table1.col_time > table2.col_time)") + assertClauseSerialize(t, table1ColTime.GT(timeVar), "(table1.col_time > $1::time without time zone)", "10:20:00.000") } func TestTimeExpressionGT_EQ(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, table1ColTime.GT_EQ(table2ColTime), "(table1.col_time >= table2.col_time)") - jet.AssertPostgreClauseSerialize(t, table1ColTime.GT_EQ(timeVar), "(table1.col_time >= $1::time without time zone)", "10:20:00.000") + assertClauseSerialize(t, table1ColTime.GT_EQ(table2ColTime), "(table1.col_time >= table2.col_time)") + assertClauseSerialize(t, table1ColTime.GT_EQ(timeVar), "(table1.col_time >= $1::time without time zone)", "10:20:00.000") } func TestTimeExp(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, TimeExp(table1ColFloat), "table1.col_float") - jet.AssertPostgreClauseSerialize(t, TimeExp(table1ColFloat).LT(Time(1, 1, 1, 1)), + assertClauseSerialize(t, TimeExp(table1ColFloat), "table1.col_float") + assertClauseSerialize(t, TimeExp(table1ColFloat).LT(Time(1, 1, 1, 1)), "(table1.col_float < $1::time without time zone)", string("01:01:01.001")) } diff --git a/postgres/timestamp_expression_test.go b/postgres/timestamp_expression_test.go index 3b215f6..77f490d 100644 --- a/postgres/timestamp_expression_test.go +++ b/postgres/timestamp_expression_test.go @@ -1,55 +1,54 @@ package postgres import ( - "github.com/go-jet/jet" "testing" ) var timestamp = Timestamp(2000, 1, 31, 10, 20, 0, 0) func TestTimestampExpressionEQ(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, table1ColTimestamp.EQ(table2ColTimestamp), "(table1.col_timestamp = table2.col_timestamp)") - jet.AssertPostgreClauseSerialize(t, table1ColTimestamp.EQ(timestamp), + assertClauseSerialize(t, table1ColTimestamp.EQ(table2ColTimestamp), "(table1.col_timestamp = table2.col_timestamp)") + assertClauseSerialize(t, table1ColTimestamp.EQ(timestamp), "(table1.col_timestamp = $1::timestamp without time zone)", "2000-01-31 10:20:00.000") } func TestTimestampExpressionNOT_EQ(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, table1ColTimestamp.NOT_EQ(table2ColTimestamp), "(table1.col_timestamp != table2.col_timestamp)") - jet.AssertPostgreClauseSerialize(t, table1ColTimestamp.NOT_EQ(timestamp), "(table1.col_timestamp != $1::timestamp without time zone)", "2000-01-31 10:20:00.000") + assertClauseSerialize(t, table1ColTimestamp.NOT_EQ(table2ColTimestamp), "(table1.col_timestamp != table2.col_timestamp)") + assertClauseSerialize(t, table1ColTimestamp.NOT_EQ(timestamp), "(table1.col_timestamp != $1::timestamp without time zone)", "2000-01-31 10:20:00.000") } func TestTimestampExpressionIS_DISTINCT_FROM(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, table1ColTimestamp.IS_DISTINCT_FROM(table2ColTimestamp), "(table1.col_timestamp IS DISTINCT FROM table2.col_timestamp)") - jet.AssertPostgreClauseSerialize(t, table1ColTimestamp.IS_DISTINCT_FROM(timestamp), "(table1.col_timestamp IS DISTINCT FROM $1::timestamp without time zone)", "2000-01-31 10:20:00.000") + assertClauseSerialize(t, table1ColTimestamp.IS_DISTINCT_FROM(table2ColTimestamp), "(table1.col_timestamp IS DISTINCT FROM table2.col_timestamp)") + assertClauseSerialize(t, table1ColTimestamp.IS_DISTINCT_FROM(timestamp), "(table1.col_timestamp IS DISTINCT FROM $1::timestamp without time zone)", "2000-01-31 10:20:00.000") } func TestTimestampExpressionIS_NOT_DISTINCT_FROM(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, table1ColTimestamp.IS_NOT_DISTINCT_FROM(table2ColTimestamp), "(table1.col_timestamp IS NOT DISTINCT FROM table2.col_timestamp)") - jet.AssertPostgreClauseSerialize(t, table1ColTimestamp.IS_NOT_DISTINCT_FROM(timestamp), "(table1.col_timestamp IS NOT DISTINCT FROM $1::timestamp without time zone)", "2000-01-31 10:20:00.000") + assertClauseSerialize(t, table1ColTimestamp.IS_NOT_DISTINCT_FROM(table2ColTimestamp), "(table1.col_timestamp IS NOT DISTINCT FROM table2.col_timestamp)") + assertClauseSerialize(t, table1ColTimestamp.IS_NOT_DISTINCT_FROM(timestamp), "(table1.col_timestamp IS NOT DISTINCT FROM $1::timestamp without time zone)", "2000-01-31 10:20:00.000") } func TestTimestampExpressionLT(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, table1ColTimestamp.LT(table2ColTimestamp), "(table1.col_timestamp < table2.col_timestamp)") - jet.AssertPostgreClauseSerialize(t, table1ColTimestamp.LT(timestamp), "(table1.col_timestamp < $1::timestamp without time zone)", "2000-01-31 10:20:00.000") + assertClauseSerialize(t, table1ColTimestamp.LT(table2ColTimestamp), "(table1.col_timestamp < table2.col_timestamp)") + assertClauseSerialize(t, table1ColTimestamp.LT(timestamp), "(table1.col_timestamp < $1::timestamp without time zone)", "2000-01-31 10:20:00.000") } func TestTimestampExpressionLT_EQ(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, table1ColTimestamp.LT_EQ(table2ColTimestamp), "(table1.col_timestamp <= table2.col_timestamp)") - jet.AssertPostgreClauseSerialize(t, table1ColTimestamp.LT_EQ(timestamp), "(table1.col_timestamp <= $1::timestamp without time zone)", "2000-01-31 10:20:00.000") + assertClauseSerialize(t, table1ColTimestamp.LT_EQ(table2ColTimestamp), "(table1.col_timestamp <= table2.col_timestamp)") + assertClauseSerialize(t, table1ColTimestamp.LT_EQ(timestamp), "(table1.col_timestamp <= $1::timestamp without time zone)", "2000-01-31 10:20:00.000") } func TestTimestampExpressionGT(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, table1ColTimestamp.GT(table2ColTimestamp), "(table1.col_timestamp > table2.col_timestamp)") - jet.AssertPostgreClauseSerialize(t, table1ColTimestamp.GT(timestamp), "(table1.col_timestamp > $1::timestamp without time zone)", "2000-01-31 10:20:00.000") + assertClauseSerialize(t, table1ColTimestamp.GT(table2ColTimestamp), "(table1.col_timestamp > table2.col_timestamp)") + assertClauseSerialize(t, table1ColTimestamp.GT(timestamp), "(table1.col_timestamp > $1::timestamp without time zone)", "2000-01-31 10:20:00.000") } func TestTimestampExpressionGT_EQ(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, table1ColTimestamp.GT_EQ(table2ColTimestamp), "(table1.col_timestamp >= table2.col_timestamp)") - jet.AssertPostgreClauseSerialize(t, table1ColTimestamp.GT_EQ(timestamp), "(table1.col_timestamp >= $1::timestamp without time zone)", "2000-01-31 10:20:00.000") + assertClauseSerialize(t, table1ColTimestamp.GT_EQ(table2ColTimestamp), "(table1.col_timestamp >= table2.col_timestamp)") + assertClauseSerialize(t, table1ColTimestamp.GT_EQ(timestamp), "(table1.col_timestamp >= $1::timestamp without time zone)", "2000-01-31 10:20:00.000") } func TestTimestampExp(t *testing.T) { - jet.AssertPostgreClauseSerialize(t, TimestampExp(table1ColFloat), "table1.col_float") - jet.AssertPostgreClauseSerialize(t, TimestampExp(table1ColFloat).LT(timestamp), + assertClauseSerialize(t, TimestampExp(table1ColFloat), "table1.col_float") + assertClauseSerialize(t, TimestampExp(table1ColFloat).LT(timestamp), "(table1.col_float < $1::timestamp without time zone)", "2000-01-31 10:20:00.000") } diff --git a/projection.go b/projection.go deleted file mode 100644 index f81922b..0000000 --- a/projection.go +++ /dev/null @@ -1,29 +0,0 @@ -package jet - -type projection interface { - serializeForProjection(statement statementType, out *sqlBuilder) error - from(subQuery SelectTable) projection -} - -// ProjectionList is a redefined type, so that ProjectionList can be used as a projection. -type ProjectionList []projection - -func (cl ProjectionList) from(subQuery SelectTable) projection { - newProjectionList := ProjectionList{} - - for _, projection := range cl { - newProjectionList = append(newProjectionList, projection.from(subQuery)) - } - - return newProjectionList -} - -func (cl ProjectionList) serializeForProjection(statement statementType, out *sqlBuilder) error { - err := serializeProjectionList(statement, cl, out) - - if err != nil { - return err - } - - return nil -} diff --git a/string_expression_test.go b/string_expression_test.go deleted file mode 100644 index a81d9cb..0000000 --- a/string_expression_test.go +++ /dev/null @@ -1,82 +0,0 @@ -package jet - -import ( - "testing" -) - -func TestStringEQ(t *testing.T) { - exp := table3StrCol.EQ(table2ColStr) - AssertPostgreClauseSerialize(t, exp, "(table3.col2 = table2.col_str)") - exp = table3StrCol.EQ(String("JOHN")) - AssertPostgreClauseSerialize(t, exp, "(table3.col2 = $1)", "JOHN") -} - -func TestStringNOT_EQ(t *testing.T) { - exp := table3StrCol.NOT_EQ(table2ColStr) - AssertPostgreClauseSerialize(t, exp, "(table3.col2 != table2.col_str)") - AssertPostgreClauseSerialize(t, table3StrCol.NOT_EQ(String("JOHN")), "(table3.col2 != $1)", "JOHN") -} - -func TestStringExpressionIS_DISTINCT_FROM(t *testing.T) { - AssertPostgreClauseSerialize(t, table3StrCol.IS_DISTINCT_FROM(table2ColStr), "(table3.col2 IS DISTINCT FROM table2.col_str)") - AssertPostgreClauseSerialize(t, table3StrCol.IS_DISTINCT_FROM(String("JOHN")), "(table3.col2 IS DISTINCT FROM $1)", "JOHN") -} - -func TestStringExpressionIS_NOT_DISTINCT_FROM(t *testing.T) { - AssertPostgreClauseSerialize(t, table3StrCol.IS_NOT_DISTINCT_FROM(table2ColStr), "(table3.col2 IS NOT DISTINCT FROM table2.col_str)") - AssertPostgreClauseSerialize(t, table3StrCol.IS_NOT_DISTINCT_FROM(String("JOHN")), "(table3.col2 IS NOT DISTINCT FROM $1)", "JOHN") -} - -func TestStringGT(t *testing.T) { - exp := table3StrCol.GT(table2ColStr) - AssertPostgreClauseSerialize(t, exp, "(table3.col2 > table2.col_str)") - AssertPostgreClauseSerialize(t, table3StrCol.GT(String("JOHN")), "(table3.col2 > $1)", "JOHN") -} - -func TestStringGT_EQ(t *testing.T) { - exp := table3StrCol.GT_EQ(table2ColStr) - AssertPostgreClauseSerialize(t, exp, "(table3.col2 >= table2.col_str)") - AssertPostgreClauseSerialize(t, table3StrCol.GT_EQ(String("JOHN")), "(table3.col2 >= $1)", "JOHN") -} - -func TestStringLT(t *testing.T) { - exp := table3StrCol.LT(table2ColStr) - AssertPostgreClauseSerialize(t, exp, "(table3.col2 < table2.col_str)") - AssertPostgreClauseSerialize(t, table3StrCol.LT(String("JOHN")), "(table3.col2 < $1)", "JOHN") -} - -func TestStringLT_EQ(t *testing.T) { - exp := table3StrCol.LT_EQ(table2ColStr) - AssertPostgreClauseSerialize(t, exp, "(table3.col2 <= table2.col_str)") - AssertPostgreClauseSerialize(t, table3StrCol.LT_EQ(String("JOHN")), "(table3.col2 <= $1)", "JOHN") -} - -func TestStringCONCAT(t *testing.T) { - AssertPostgreClauseSerialize(t, table3StrCol.CONCAT(table2ColStr), "(table3.col2 || table2.col_str)") - AssertPostgreClauseSerialize(t, table3StrCol.CONCAT(String("JOHN")), "(table3.col2 || $1)", "JOHN") -} - -func TestStringLIKE(t *testing.T) { - AssertPostgreClauseSerialize(t, table3StrCol.LIKE(table2ColStr), "(table3.col2 LIKE table2.col_str)") - AssertPostgreClauseSerialize(t, table3StrCol.LIKE(String("JOHN")), "(table3.col2 LIKE $1)", "JOHN") -} - -func TestStringNOT_LIKE(t *testing.T) { - AssertPostgreClauseSerialize(t, table3StrCol.NOT_LIKE(table2ColStr), "(table3.col2 NOT LIKE table2.col_str)") - AssertPostgreClauseSerialize(t, table3StrCol.NOT_LIKE(String("JOHN")), "(table3.col2 NOT LIKE $1)", "JOHN") -} - -func TestStringSIMILAR_TO(t *testing.T) { - AssertPostgreClauseSerialize(t, table3StrCol.SIMILAR_TO(table2ColStr), "(table3.col2 SIMILAR TO table2.col_str)") - AssertPostgreClauseSerialize(t, table3StrCol.SIMILAR_TO(String("JOHN")), "(table3.col2 SIMILAR TO $1)", "JOHN") -} - -func TestStringNOT_SIMILAR_TO(t *testing.T) { - AssertPostgreClauseSerialize(t, table3StrCol.NOT_SIMILAR_TO(table2ColStr), "(table3.col2 NOT SIMILAR TO table2.col_str)") - AssertPostgreClauseSerialize(t, table3StrCol.NOT_SIMILAR_TO(String("JOHN")), "(table3.col2 NOT SIMILAR TO $1)", "JOHN") -} - -func TestStringExp(t *testing.T) { - AssertPostgreClauseSerialize(t, StringExp(table2ColFloat), "table2.col_float") - AssertPostgreClauseSerialize(t, StringExp(table2ColFloat).NOT_LIKE(String("abc")), "(table2.col_float NOT LIKE $1)", "abc") -} diff --git a/tests/mysql/delete_test.go b/tests/mysql/delete_test.go index 99ab41f..a46777e 100644 --- a/tests/mysql/delete_test.go +++ b/tests/mysql/delete_test.go @@ -2,8 +2,8 @@ package mysql import ( "context" - . "github.com/go-jet/jet" "github.com/go-jet/jet/internal/testutils" + . "github.com/go-jet/jet/mysql" "github.com/go-jet/jet/tests/.gentestdata/mysql/test_sample/model" . "github.com/go-jet/jet/tests/.gentestdata/mysql/test_sample/table" "gotest.tools/assert" diff --git a/tests/mysql/update_test.go b/tests/mysql/update_test.go index 7abd7f3..b65165a 100644 --- a/tests/mysql/update_test.go +++ b/tests/mysql/update_test.go @@ -2,8 +2,8 @@ package mysql import ( "context" - . "github.com/go-jet/jet" "github.com/go-jet/jet/internal/testutils" + . "github.com/go-jet/jet/mysql" "github.com/go-jet/jet/tests/.gentestdata/mysql/test_sample/model" . "github.com/go-jet/jet/tests/.gentestdata/mysql/test_sample/table" "gotest.tools/assert" @@ -123,7 +123,7 @@ func TestUpdateWithModelDataAndPredefinedColumnList(t *testing.T) { Name: "DuckDuckGo", } - updateColumnList := ColumnList{Link.Description, Link.Name, Link.URL} + updateColumnList := ColumnList(Link.Description, Link.Name, Link.URL) stmt := Link. UPDATE(updateColumnList). diff --git a/tests/postgres/alltypes_test.go b/tests/postgres/alltypes_test.go index 59027c5..3f5bf0b 100644 --- a/tests/postgres/alltypes_test.go +++ b/tests/postgres/alltypes_test.go @@ -2,9 +2,9 @@ package postgres import ( "fmt" - . "github.com/go-jet/jet" "github.com/go-jet/jet/internal/testutils" "github.com/go-jet/jet/postgres" + . "github.com/go-jet/jet/postgres" "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/model" . "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/table" "github.com/go-jet/jet/tests/testdata/common" diff --git a/tests/postgres/chinook_db_test.go b/tests/postgres/chinook_db_test.go index bd74cb1..8f39662 100644 --- a/tests/postgres/chinook_db_test.go +++ b/tests/postgres/chinook_db_test.go @@ -2,8 +2,8 @@ package postgres import ( "context" - . "github.com/go-jet/jet" "github.com/go-jet/jet/internal/testutils" + . "github.com/go-jet/jet/postgres" "github.com/go-jet/jet/tests/.gentestdata/jetdb/chinook/model" . "github.com/go-jet/jet/tests/.gentestdata/jetdb/chinook/table" "gotest.tools/assert" diff --git a/tests/postgres/delete_test.go b/tests/postgres/delete_test.go index 10ecb23..f8d264a 100644 --- a/tests/postgres/delete_test.go +++ b/tests/postgres/delete_test.go @@ -2,8 +2,8 @@ package postgres import ( "context" - . "github.com/go-jet/jet" "github.com/go-jet/jet/internal/testutils" + . "github.com/go-jet/jet/postgres" "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/model" . "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/table" "gotest.tools/assert" diff --git a/tests/postgres/insert_test.go b/tests/postgres/insert_test.go index cf344e9..ee402b8 100644 --- a/tests/postgres/insert_test.go +++ b/tests/postgres/insert_test.go @@ -2,8 +2,8 @@ package postgres import ( "context" - . "github.com/go-jet/jet" "github.com/go-jet/jet/internal/testutils" + . "github.com/go-jet/jet/postgres" "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/model" . "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/table" "gotest.tools/assert" @@ -24,7 +24,7 @@ RETURNING link.id AS "link.id", link.name AS "link.name", link.description AS "link.description"; ` - + Link.ID.Name() insertQuery := Link.INSERT(Link.ID, Link.URL, Link.Name, Link.Description). VALUES(100, "http://www.postgresqltutorial.com", "PostgreSQL Tutorial", DEFAULT). VALUES(101, "http://www.google.com", "Google", DEFAULT). diff --git a/tests/postgres/lock_test.go b/tests/postgres/lock_test.go index d10f7be..c62a169 100644 --- a/tests/postgres/lock_test.go +++ b/tests/postgres/lock_test.go @@ -7,7 +7,7 @@ import ( "testing" "time" - . "github.com/go-jet/jet" + . "github.com/go-jet/jet/postgres" . "github.com/go-jet/jet/tests/.gentestdata/jetdb/dvds/table" ) @@ -15,7 +15,7 @@ func TestLockTable(t *testing.T) { expectedSQL := ` LOCK TABLE dvds.address IN` - var testData = []TableLockMode{ + var testData = []string{ LOCK_ACCESS_SHARE, LOCK_ROW_SHARE, LOCK_ROW_EXCLUSIVE, diff --git a/tests/postgres/main_test.go b/tests/postgres/main_test.go index 7b77afb..4cffae0 100644 --- a/tests/postgres/main_test.go +++ b/tests/postgres/main_test.go @@ -66,7 +66,12 @@ func TestGeneratedModel(t *testing.T) { const genTestDir2 = "./.gentestdata2" func TestCmdGenerator(t *testing.T) { - err := os.RemoveAll(genTestDir2) + goInstallJet := exec.Command("sh", "-c", "go install github.com/go-jet/jet/cmd/jet") + goInstallJet.Stderr = os.Stderr + err := goInstallJet.Run() + assert.NilError(t, err) + + err = os.RemoveAll(genTestDir2) assert.NilError(t, err) cmd := exec.Command("jet", "-dbname=jetdb", "-host=localhost", "-port=5432", @@ -163,20 +168,20 @@ func assertFileNameEqual(t *testing.T, fileInfos []os.FileInfo, fileNames ...str var mpaaRatingEnumFile = ` package enum -import "github.com/go-jet/jet" +import "github.com/go-jet/jet/postgres" var MpaaRating = &struct { - G jet.StringExpression - Pg jet.StringExpression - Pg13 jet.StringExpression - R jet.StringExpression - Nc17 jet.StringExpression + G postgres.StringExpression + Pg postgres.StringExpression + Pg13 postgres.StringExpression + R postgres.StringExpression + Nc17 postgres.StringExpression }{ - G: jet.NewEnumValue("G"), - Pg: jet.NewEnumValue("PG"), - Pg13: jet.NewEnumValue("PG-13"), - R: jet.NewEnumValue("R"), - Nc17: jet.NewEnumValue("NC-17"), + G: postgres.NewEnumValue("G"), + Pg: postgres.NewEnumValue("PG"), + Pg13: postgres.NewEnumValue("PG-13"), + R: postgres.NewEnumValue("R"), + Nc17: postgres.NewEnumValue("NC-17"), } ` @@ -184,14 +189,13 @@ var actorSQLBuilderFile = ` package table import ( - "github.com/go-jet/jet" "github.com/go-jet/jet/postgres" ) var Actor = newActorTable() type ActorTable struct { - jet.Table + postgres.Table //Columns ActorID postgres.ColumnInteger @@ -199,8 +203,8 @@ type ActorTable struct { LastName postgres.ColumnString LastUpdate postgres.ColumnTimestamp - AllColumns jet.ColumnList - MutableColumns jet.ColumnList + AllColumns postgres.IColumnList + MutableColumns postgres.IColumnList } // creates new ActorTable with assigned alias @@ -221,7 +225,7 @@ func newActorTable() *ActorTable { ) return &ActorTable{ - Table: jet.NewTable(jet.PostgreSQL, "dvds", "actor", ActorIDColumn, FirstNameColumn, LastNameColumn, LastUpdateColumn), + Table: postgres.NewTable("dvds", "actor", ActorIDColumn, FirstNameColumn, LastNameColumn, LastUpdateColumn), //Columns ActorID: ActorIDColumn, @@ -229,8 +233,8 @@ func newActorTable() *ActorTable { LastName: LastNameColumn, LastUpdate: LastUpdateColumn, - AllColumns: jet.ColumnList{ActorIDColumn, FirstNameColumn, LastNameColumn, LastUpdateColumn}, - MutableColumns: jet.ColumnList{FirstNameColumn, LastNameColumn, LastUpdateColumn}, + AllColumns: postgres.ColumnList(ActorIDColumn, FirstNameColumn, LastNameColumn, LastUpdateColumn), + MutableColumns: postgres.ColumnList(FirstNameColumn, LastNameColumn, LastUpdateColumn), } } ` diff --git a/tests/postgres/sample_test.go b/tests/postgres/sample_test.go index 3e7c06e..f7c4d32 100644 --- a/tests/postgres/sample_test.go +++ b/tests/postgres/sample_test.go @@ -1,8 +1,8 @@ package postgres import ( - . "github.com/go-jet/jet" "github.com/go-jet/jet/internal/testutils" + . "github.com/go-jet/jet/postgres" "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/model" . "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/table" "github.com/google/uuid" diff --git a/tests/postgres/scan_test.go b/tests/postgres/scan_test.go index c0c4746..267d7be 100644 --- a/tests/postgres/scan_test.go +++ b/tests/postgres/scan_test.go @@ -1,8 +1,8 @@ package postgres import ( - . "github.com/go-jet/jet" "github.com/go-jet/jet/internal/testutils" + . "github.com/go-jet/jet/postgres" "github.com/go-jet/jet/tests/.gentestdata/jetdb/dvds/model" . "github.com/go-jet/jet/tests/.gentestdata/jetdb/dvds/table" "github.com/google/uuid" diff --git a/tests/postgres/select_test.go b/tests/postgres/select_test.go index 47aaa47..c0cedf9 100644 --- a/tests/postgres/select_test.go +++ b/tests/postgres/select_test.go @@ -1,7 +1,6 @@ package postgres import ( - "github.com/go-jet/jet" "github.com/go-jet/jet/internal/testutils" . "github.com/go-jet/jet/postgres" "github.com/go-jet/jet/tests/.gentestdata/jetdb/dvds/enum" @@ -1268,7 +1267,7 @@ func TestAllSetOperators(t *testing.T) { select1 := Payment.SELECT(Payment.AllColumns).WHERE(Payment.PaymentID.GT_EQ(Int(17600)).AND(Payment.PaymentID.LT(Int(17610)))) select2 := Payment.SELECT(Payment.AllColumns).WHERE(Payment.PaymentID.GT_EQ(Int(17620)).AND(Payment.PaymentID.LT(Int(17630)))) - type setOperator func(lhs, rhs jet.SelectStatement, selects ...jet.SelectStatement) jet.SelectStatement + type setOperator func(lhs, rhs SelectStatement, selects ...SelectStatement) SelectStatement operators := []setOperator{ UNION, UNION_ALL, diff --git a/tests/postgres/update_test.go b/tests/postgres/update_test.go index 08d483f..09ffaf0 100644 --- a/tests/postgres/update_test.go +++ b/tests/postgres/update_test.go @@ -2,8 +2,8 @@ package postgres import ( "context" - . "github.com/go-jet/jet" "github.com/go-jet/jet/internal/testutils" + . "github.com/go-jet/jet/postgres" "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/model" . "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/table" "gotest.tools/assert" @@ -191,7 +191,7 @@ func TestUpdateWithModelDataAndPredefinedColumnList(t *testing.T) { Name: "DuckDuckGo", } - updateColumnList := ColumnList{Link.Description, Link.Name, Link.URL} + updateColumnList := ColumnList(Link.Description, Link.Name, Link.URL) stmt := Link. UPDATE(updateColumnList). diff --git a/tests/postgres/util_test.go b/tests/postgres/util_test.go index 1041eca..88359e0 100644 --- a/tests/postgres/util_test.go +++ b/tests/postgres/util_test.go @@ -1,7 +1,7 @@ package postgres import ( - "github.com/go-jet/jet" + "github.com/go-jet/jet/internal/jet" "github.com/go-jet/jet/internal/testutils" "github.com/go-jet/jet/tests/.gentestdata/jetdb/dvds/model" "github.com/google/uuid" diff --git a/time_expression_test.go b/time_expression_test.go deleted file mode 100644 index eee14f1..0000000 --- a/time_expression_test.go +++ /dev/null @@ -1,53 +0,0 @@ -package jet - -import ( - "testing" -) - -var timeVar = Time(10, 20, 0, 0) - -func TestTimeExpressionEQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTime.EQ(table2ColTime), "(table1.col_time = table2.col_time)") - AssertPostgreClauseSerialize(t, table1ColTime.EQ(timeVar), "(table1.col_time = $1)", "10:20:00.000") -} - -func TestTimeExpressionNOT_EQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTime.NOT_EQ(table2ColTime), "(table1.col_time != table2.col_time)") - AssertPostgreClauseSerialize(t, table1ColTime.NOT_EQ(timeVar), "(table1.col_time != $1)", "10:20:00.000") -} - -func TestTimeExpressionIS_DISTINCT_FROM(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTime.IS_DISTINCT_FROM(table2ColTime), "(table1.col_time IS DISTINCT FROM table2.col_time)") - AssertPostgreClauseSerialize(t, table1ColTime.IS_DISTINCT_FROM(timeVar), "(table1.col_time IS DISTINCT FROM $1)", "10:20:00.000") -} - -func TestTimeExpressionIS_NOT_DISTINCT_FROM(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTime.IS_NOT_DISTINCT_FROM(table2ColTime), "(table1.col_time IS NOT DISTINCT FROM table2.col_time)") - AssertPostgreClauseSerialize(t, table1ColTime.IS_NOT_DISTINCT_FROM(timeVar), "(table1.col_time IS NOT DISTINCT FROM $1)", "10:20:00.000") -} - -func TestTimeExpressionLT(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTime.LT(table2ColTime), "(table1.col_time < table2.col_time)") - AssertPostgreClauseSerialize(t, table1ColTime.LT(timeVar), "(table1.col_time < $1)", "10:20:00.000") -} - -func TestTimeExpressionLT_EQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTime.LT_EQ(table2ColTime), "(table1.col_time <= table2.col_time)") - AssertPostgreClauseSerialize(t, table1ColTime.LT_EQ(timeVar), "(table1.col_time <= $1)", "10:20:00.000") -} - -func TestTimeExpressionGT(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTime.GT(table2ColTime), "(table1.col_time > table2.col_time)") - AssertPostgreClauseSerialize(t, table1ColTime.GT(timeVar), "(table1.col_time > $1)", "10:20:00.000") -} - -func TestTimeExpressionGT_EQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTime.GT_EQ(table2ColTime), "(table1.col_time >= table2.col_time)") - AssertPostgreClauseSerialize(t, table1ColTime.GT_EQ(timeVar), "(table1.col_time >= $1)", "10:20:00.000") -} - -func TestTimeExp(t *testing.T) { - AssertPostgreClauseSerialize(t, TimeExp(table1ColFloat), "table1.col_float") - AssertPostgreClauseSerialize(t, TimeExp(table1ColFloat).LT(Time(1, 1, 1, 1)), - "(table1.col_float < $1)", string("01:01:01.001")) -} diff --git a/timestamp_expression_test.go b/timestamp_expression_test.go deleted file mode 100644 index 44f6dbb..0000000 --- a/timestamp_expression_test.go +++ /dev/null @@ -1,52 +0,0 @@ -package jet - -import "testing" - -var timestamp = Timestamp(2000, 1, 31, 10, 20, 0, 0) - -func TestTimestampExpressionEQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTimestamp.EQ(table2ColTimestamp), "(table1.col_timestamp = table2.col_timestamp)") - AssertPostgreClauseSerialize(t, table1ColTimestamp.EQ(timestamp), - "(table1.col_timestamp = $1)", "2000-01-31 10:20:00.000") -} - -func TestTimestampExpressionNOT_EQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTimestamp.NOT_EQ(table2ColTimestamp), "(table1.col_timestamp != table2.col_timestamp)") - AssertPostgreClauseSerialize(t, table1ColTimestamp.NOT_EQ(timestamp), "(table1.col_timestamp != $1)", "2000-01-31 10:20:00.000") -} - -func TestTimestampExpressionIS_DISTINCT_FROM(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTimestamp.IS_DISTINCT_FROM(table2ColTimestamp), "(table1.col_timestamp IS DISTINCT FROM table2.col_timestamp)") - AssertPostgreClauseSerialize(t, table1ColTimestamp.IS_DISTINCT_FROM(timestamp), "(table1.col_timestamp IS DISTINCT FROM $1)", "2000-01-31 10:20:00.000") -} - -func TestTimestampExpressionIS_NOT_DISTINCT_FROM(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTimestamp.IS_NOT_DISTINCT_FROM(table2ColTimestamp), "(table1.col_timestamp IS NOT DISTINCT FROM table2.col_timestamp)") - AssertPostgreClauseSerialize(t, table1ColTimestamp.IS_NOT_DISTINCT_FROM(timestamp), "(table1.col_timestamp IS NOT DISTINCT FROM $1)", "2000-01-31 10:20:00.000") -} - -func TestTimestampExpressionLT(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTimestamp.LT(table2ColTimestamp), "(table1.col_timestamp < table2.col_timestamp)") - AssertPostgreClauseSerialize(t, table1ColTimestamp.LT(timestamp), "(table1.col_timestamp < $1)", "2000-01-31 10:20:00.000") -} - -func TestTimestampExpressionLT_EQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTimestamp.LT_EQ(table2ColTimestamp), "(table1.col_timestamp <= table2.col_timestamp)") - AssertPostgreClauseSerialize(t, table1ColTimestamp.LT_EQ(timestamp), "(table1.col_timestamp <= $1)", "2000-01-31 10:20:00.000") -} - -func TestTimestampExpressionGT(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTimestamp.GT(table2ColTimestamp), "(table1.col_timestamp > table2.col_timestamp)") - AssertPostgreClauseSerialize(t, table1ColTimestamp.GT(timestamp), "(table1.col_timestamp > $1)", "2000-01-31 10:20:00.000") -} - -func TestTimestampExpressionGT_EQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTimestamp.GT_EQ(table2ColTimestamp), "(table1.col_timestamp >= table2.col_timestamp)") - AssertPostgreClauseSerialize(t, table1ColTimestamp.GT_EQ(timestamp), "(table1.col_timestamp >= $1)", "2000-01-31 10:20:00.000") -} - -func TestTimestampExp(t *testing.T) { - AssertPostgreClauseSerialize(t, TimestampExp(table1ColFloat), "table1.col_float") - AssertPostgreClauseSerialize(t, TimestampExp(table1ColFloat).LT(timestamp), - "(table1.col_float < $1)", "2000-01-31 10:20:00.000") -} diff --git a/timestampz_expression_test.go b/timestampz_expression_test.go deleted file mode 100644 index 1a13fd0..0000000 --- a/timestampz_expression_test.go +++ /dev/null @@ -1,54 +0,0 @@ -// +build todo - -package jet - -import "testing" - -var timestampz = Timestampz(2000, 1, 31, 10, 20, 0, 0, 2) - -func TestTimestampzExpressionEQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTimestampz.EQ(table2ColTimestampz), "(table1.col_timestampz = table2.col_timestampz)") - AssertPostgreClauseSerialize(t, table1ColTimestampz.EQ(timestampz), - "(table1.col_timestampz = $1::timestamp with time zone)", "2000-01-31 10:20:00.000 +002") -} - -func TestTimestampzExpressionNOT_EQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTimestampz.NOT_EQ(table2ColTimestampz), "(table1.col_timestampz != table2.col_timestampz)") - AssertPostgreClauseSerialize(t, table1ColTimestampz.NOT_EQ(timestampz), "(table1.col_timestampz != $1::timestamp with time zone)", "2000-01-31 10:20:00.000 +002") -} - -func TestTimestampzExpressionIS_DISTINCT_FROM(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTimestampz.IS_DISTINCT_FROM(table2ColTimestampz), "(table1.col_timestampz IS DISTINCT FROM table2.col_timestampz)") - AssertPostgreClauseSerialize(t, table1ColTimestampz.IS_DISTINCT_FROM(timestampz), "(table1.col_timestampz IS DISTINCT FROM $1::timestamp with time zone)", "2000-01-31 10:20:00.000 +002") -} - -func TestTimestampzExpressionIS_NOT_DISTINCT_FROM(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTimestampz.IS_NOT_DISTINCT_FROM(table2ColTimestampz), "(table1.col_timestampz IS NOT DISTINCT FROM table2.col_timestampz)") - AssertPostgreClauseSerialize(t, table1ColTimestampz.IS_NOT_DISTINCT_FROM(timestampz), "(table1.col_timestampz IS NOT DISTINCT FROM $1::timestamp with time zone)", "2000-01-31 10:20:00.000 +002") -} - -func TestTimestampzExpressionLT(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTimestampz.LT(table2ColTimestampz), "(table1.col_timestampz < table2.col_timestampz)") - AssertPostgreClauseSerialize(t, table1ColTimestampz.LT(timestampz), "(table1.col_timestampz < $1::timestamp with time zone)", "2000-01-31 10:20:00.000 +002") -} - -func TestTimestampzExpressionLT_EQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTimestampz.LT_EQ(table2ColTimestampz), "(table1.col_timestampz <= table2.col_timestampz)") - AssertPostgreClauseSerialize(t, table1ColTimestampz.LT_EQ(timestampz), "(table1.col_timestampz <= $1::timestamp with time zone)", "2000-01-31 10:20:00.000 +002") -} - -func TestTimestampzExpressionGT(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTimestampz.GT(table2ColTimestampz), "(table1.col_timestampz > table2.col_timestampz)") - AssertPostgreClauseSerialize(t, table1ColTimestampz.GT(timestampz), "(table1.col_timestampz > $1::timestamp with time zone)", "2000-01-31 10:20:00.000 +002") -} - -func TestTimestampzExpressionGT_EQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTimestampz.GT_EQ(table2ColTimestampz), "(table1.col_timestampz >= table2.col_timestampz)") - AssertPostgreClauseSerialize(t, table1ColTimestampz.GT_EQ(timestampz), "(table1.col_timestampz >= $1::timestamp with time zone)", "2000-01-31 10:20:00.000 +002") -} - -func TestTimestampzExp(t *testing.T) { - AssertPostgreClauseSerialize(t, TimestampzExp(table1ColFloat), "table1.col_float") - AssertPostgreClauseSerialize(t, TimestampzExp(table1ColFloat).LT(timestampz), - "(table1.col_float < $1::timestamp with time zone)", "2000-01-31 10:20:00.000 +002") -} diff --git a/timez_expression_test.go b/timez_expression_test.go deleted file mode 100644 index 7263b72..0000000 --- a/timez_expression_test.go +++ /dev/null @@ -1,53 +0,0 @@ -// +build TODO - -package jet - -import "testing" - -var timezVar = Timez(10, 20, 0, 0, 4) - -func TestTimezExpressionEQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTimez.EQ(table2ColTimez), "(table1.col_timez = table2.col_timez)") - AssertPostgreClauseSerialize(t, table1ColTimez.EQ(timezVar), "(table1.col_timez = $1::time with time zone)", "10:20:00.000 +04") -} - -func TestTimezExpressionNOT_EQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTimez.NOT_EQ(table2ColTimez), "(table1.col_timez != table2.col_timez)") - AssertPostgreClauseSerialize(t, table1ColTimez.NOT_EQ(timezVar), "(table1.col_timez != $1::time with time zone)", "10:20:00.000 +04") -} - -func TestTimezExpressionIS_DISTINCT_FROM(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTimez.IS_DISTINCT_FROM(table2ColTimez), "(table1.col_timez IS DISTINCT FROM table2.col_timez)") - AssertPostgreClauseSerialize(t, table1ColTimez.IS_DISTINCT_FROM(timezVar), "(table1.col_timez IS DISTINCT FROM $1::time with time zone)", "10:20:00.000 +04") -} - -func TestTimezExpressionIS_NOT_DISTINCT_FROM(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTimez.IS_NOT_DISTINCT_FROM(table2ColTimez), "(table1.col_timez IS NOT DISTINCT FROM table2.col_timez)") - AssertPostgreClauseSerialize(t, table1ColTimez.IS_NOT_DISTINCT_FROM(timezVar), "(table1.col_timez IS NOT DISTINCT FROM $1::time with time zone)", "10:20:00.000 +04") -} - -func TestTimezExpressionLT(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTimez.LT(table2ColTimez), "(table1.col_timez < table2.col_timez)") - AssertPostgreClauseSerialize(t, table1ColTimez.LT(timezVar), "(table1.col_timez < $1::time with time zone)", "10:20:00.000 +04") -} - -func TestTimezExpressionLT_EQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTimez.LT_EQ(table2ColTimez), "(table1.col_timez <= table2.col_timez)") - AssertPostgreClauseSerialize(t, table1ColTimez.LT_EQ(timezVar), "(table1.col_timez <= $1::time with time zone)", "10:20:00.000 +04") -} - -func TestTimezExpressionGT(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTimez.GT(table2ColTimez), "(table1.col_timez > table2.col_timez)") - AssertPostgreClauseSerialize(t, table1ColTimez.GT(timezVar), "(table1.col_timez > $1::time with time zone)", "10:20:00.000 +04") -} - -func TestTimezExpressionGT_EQ(t *testing.T) { - AssertPostgreClauseSerialize(t, table1ColTimez.GT_EQ(table2ColTimez), "(table1.col_timez >= table2.col_timez)") - AssertPostgreClauseSerialize(t, table1ColTimez.GT_EQ(timezVar), "(table1.col_timez >= $1::time with time zone)", "10:20:00.000 +04") -} - -func TestTimezExp(t *testing.T) { - AssertPostgreClauseSerialize(t, TimezExp(table1ColFloat), "table1.col_float") - AssertPostgreClauseSerialize(t, TimezExp(table1ColFloat).LT(Timez(1, 1, 1, 1, 4)), - "(table1.col_float < $1::time with time zone)", string("01:01:01.001 +04")) -}