From 2b6288d31728d5bc5a756f45f460fcc9b61f2f11 Mon Sep 17 00:00:00 2001 From: zer0sub Date: Fri, 31 May 2019 12:59:57 +0200 Subject: [PATCH] Strictly type Integer and Real expressions. --- generator/postgres-metadata/column_info.go | 6 +- sqlbuilder/bool_expresion.go | 58 +++---- sqlbuilder/column_types.go | 16 +- sqlbuilder/column_types_test.go | 2 +- sqlbuilder/date_expression.go | 32 ++-- sqlbuilder/delete_statement.go | 6 +- sqlbuilder/execution/execution.go | 2 +- sqlbuilder/expression.go | 18 +-- sqlbuilder/expression_old_test.go | 6 +- sqlbuilder/expression_table.go | 8 +- sqlbuilder/float_expression.go | 123 +++++++++++++++ ...ssion_test.go => float_expression_test.go} | 18 +-- sqlbuilder/func_expression.go | 130 ++++------------ sqlbuilder/insert_statement_test.go | 26 ++-- sqlbuilder/integer_expression.go | 105 ++++++++++--- sqlbuilder/literal_expression.go | 28 ++-- sqlbuilder/numeric_expression.go | 123 --------------- sqlbuilder/operators.go | 146 +++++++++++++++--- sqlbuilder/select_statement.go | 16 +- sqlbuilder/statement_test.go | 36 ++--- sqlbuilder/string_expression.go | 32 ++-- sqlbuilder/table.go | 36 ++--- sqlbuilder/table_test.go | 4 +- sqlbuilder/test_utils.go | 4 +- sqlbuilder/time_expression.go | 32 ++-- sqlbuilder/timestamp_expression.go | 32 ++-- sqlbuilder/timestampz_expression.go | 32 ++-- sqlbuilder/timez_expression.go | 32 ++-- sqlbuilder/update_statement.go | 6 +- sqlbuilder/update_statement_test.go | 22 +-- tests/select_test.go | 24 +-- tests/types_test.go | 26 ++-- 32 files changed, 640 insertions(+), 547 deletions(-) create mode 100644 sqlbuilder/float_expression.go rename sqlbuilder/{numeric_expression_test.go => float_expression_test.go} (62%) delete mode 100644 sqlbuilder/numeric_expression.go diff --git a/generator/postgres-metadata/column_info.go b/generator/postgres-metadata/column_info.go index 88d2587..97e950f 100644 --- a/generator/postgres-metadata/column_info.go +++ b/generator/postgres-metadata/column_info.go @@ -33,8 +33,8 @@ func (c ColumnInfo) SqlBuilderColumnType() string { case "USER-DEFINED", "text", "character", "character varying", "bytea", "uuid", "tsvector", "bit", "bit varying", "money", "json", "jsonb", "xml", "point", "interval", "line", "ARRAY": return "StringColumn" - case "real", "numeric", "double precision": - return "NumericColumn" + case "real", "numeric", "decimal", "double precision": + return "FloatColumn" default: fmt.Println("Unknown sql type: " + c.DataType + ", using string column instead for sql builder.") return "StringColumn" @@ -62,7 +62,7 @@ func (c ColumnInfo) GoBaseType() string { return "string" case "real": return "float32" - case "numeric", "double precision": + case "numeric", "decimal", "double precision": return "float64" case "uuid": return "uuid.UUID" diff --git a/sqlbuilder/bool_expresion.go b/sqlbuilder/bool_expresion.go index ef50959..7f2f51b 100644 --- a/sqlbuilder/bool_expresion.go +++ b/sqlbuilder/bool_expresion.go @@ -1,73 +1,73 @@ package sqlbuilder -type boolExpression interface { +type BoolExpression interface { expression - EQ(expression boolExpression) boolExpression - NOT_EQ(expression boolExpression) boolExpression - IS_DISTINCT_FROM(rhs boolExpression) boolExpression - IS_NOT_DISTINCT_FROM(rhs boolExpression) boolExpression + EQ(expression BoolExpression) BoolExpression + NOT_EQ(expression BoolExpression) BoolExpression + IS_DISTINCT_FROM(rhs BoolExpression) BoolExpression + IS_NOT_DISTINCT_FROM(rhs BoolExpression) BoolExpression - IS_TRUE() boolExpression - IS_NOT_TRUE() boolExpression - IS_FALSE() boolExpression - IS_NOT_FALSE() boolExpression - IS_UNKNOWN() boolExpression - IS_NOT_UNKNOWN() boolExpression + IS_TRUE() BoolExpression + IS_NOT_TRUE() BoolExpression + IS_FALSE() BoolExpression + IS_NOT_FALSE() BoolExpression + IS_UNKNOWN() BoolExpression + IS_NOT_UNKNOWN() BoolExpression - AND(expression boolExpression) boolExpression - OR(expression boolExpression) boolExpression + AND(expression BoolExpression) BoolExpression + OR(expression BoolExpression) BoolExpression } type boolInterfaceImpl struct { - parent boolExpression + parent BoolExpression } -func (b *boolInterfaceImpl) EQ(expression boolExpression) boolExpression { +func (b *boolInterfaceImpl) EQ(expression BoolExpression) BoolExpression { return EQ(b.parent, expression) } -func (b *boolInterfaceImpl) NOT_EQ(expression boolExpression) boolExpression { +func (b *boolInterfaceImpl) NOT_EQ(expression BoolExpression) BoolExpression { return NOT_EQ(b.parent, expression) } -func (b *boolInterfaceImpl) IS_DISTINCT_FROM(rhs boolExpression) boolExpression { +func (b *boolInterfaceImpl) IS_DISTINCT_FROM(rhs BoolExpression) BoolExpression { return IS_DISTINCT_FROM(b.parent, rhs) } -func (b *boolInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs boolExpression) boolExpression { +func (b *boolInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs BoolExpression) BoolExpression { return IS_NOT_DISTINCT_FROM(b.parent, rhs) } -func (b *boolInterfaceImpl) AND(expression boolExpression) boolExpression { +func (b *boolInterfaceImpl) AND(expression BoolExpression) BoolExpression { return And(b.parent, expression) } -func (b *boolInterfaceImpl) OR(expression boolExpression) boolExpression { +func (b *boolInterfaceImpl) OR(expression BoolExpression) BoolExpression { return Or(b.parent, expression) } -func (b *boolInterfaceImpl) IS_TRUE() boolExpression { +func (b *boolInterfaceImpl) IS_TRUE() BoolExpression { return IS_TRUE(b.parent) } -func (b *boolInterfaceImpl) IS_NOT_TRUE() boolExpression { +func (b *boolInterfaceImpl) IS_NOT_TRUE() BoolExpression { return IS_NOT_TRUE(b.parent) } -func (b *boolInterfaceImpl) IS_FALSE() boolExpression { +func (b *boolInterfaceImpl) IS_FALSE() BoolExpression { return IS_FALSE(b.parent) } -func (b *boolInterfaceImpl) IS_NOT_FALSE() boolExpression { +func (b *boolInterfaceImpl) IS_NOT_FALSE() BoolExpression { return IS_NOT_FALSE(b.parent) } -func (b *boolInterfaceImpl) IS_UNKNOWN() boolExpression { +func (b *boolInterfaceImpl) IS_UNKNOWN() BoolExpression { return IS_UNKNOWN(b.parent) } -func (b *boolInterfaceImpl) IS_NOT_UNKNOWN() boolExpression { +func (b *boolInterfaceImpl) IS_NOT_UNKNOWN() BoolExpression { return IS_NOT_UNKNOWN(b.parent) } @@ -79,7 +79,7 @@ type binaryBoolExpression struct { binaryOpExpression } -func newBinaryBoolExpression(lhs, rhs expression, operator string) boolExpression { +func newBinaryBoolExpression(lhs, rhs expression, operator string) BoolExpression { boolExpression := binaryBoolExpression{} boolExpression.binaryOpExpression = newBinaryExpression(lhs, rhs, operator) @@ -97,7 +97,7 @@ type prefixBoolExpression struct { prefixOpExpression } -func newPrefixBoolExpression(expression expression, operator string) boolExpression { +func newPrefixBoolExpression(expression expression, operator string) BoolExpression { exp := prefixBoolExpression{} exp.prefixOpExpression = newPrefixExpression(expression, operator) @@ -115,7 +115,7 @@ type postfixBoolOpExpression struct { postfixOpExpression } -func newPostifxBoolExpression(expression expression, operator string) boolExpression { +func newPostifxBoolExpression(expression expression, operator string) BoolExpression { exp := postfixBoolOpExpression{} exp.postfixOpExpression = newPostfixOpExpression(expression, operator) diff --git a/sqlbuilder/column_types.go b/sqlbuilder/column_types.go index e484803..613bb4f 100644 --- a/sqlbuilder/column_types.go +++ b/sqlbuilder/column_types.go @@ -18,25 +18,24 @@ func NewBoolColumn(name string, nullable NullableColumn) *BoolColumn { } //------------------------------------------------------// -type NumericColumn struct { - numericInterfaceImpl +type FloatColumn struct { + floatInterfaceImpl baseColumn } -func NewNumericColumn(name string, nullable NullableColumn) *NumericColumn { +func NewFloatColumn(name string, nullable NullableColumn) *FloatColumn { - numericColumn := &NumericColumn{} + floatColumn := &FloatColumn{} - numericColumn.numericInterfaceImpl.parent = numericColumn + floatColumn.floatInterfaceImpl.parent = floatColumn - numericColumn.baseColumn = newBaseColumn(name, nullable, "", numericColumn) + floatColumn.baseColumn = newBaseColumn(name, nullable, "", floatColumn) - return numericColumn + return floatColumn } //------------------------------------------------------// type IntegerColumn struct { - numericInterfaceImpl integerInterfaceImpl baseColumn @@ -47,7 +46,6 @@ type IntegerColumn struct { func NewIntegerColumn(name string, nullable NullableColumn) *IntegerColumn { integerColumn := &IntegerColumn{} - integerColumn.numericInterfaceImpl.parent = integerColumn integerColumn.integerInterfaceImpl.parent = integerColumn integerColumn.baseColumn = newBaseColumn(name, nullable, "", integerColumn) diff --git a/sqlbuilder/column_types_test.go b/sqlbuilder/column_types_test.go index 0e60199..d127295 100644 --- a/sqlbuilder/column_types_test.go +++ b/sqlbuilder/column_types_test.go @@ -62,7 +62,7 @@ func TestNewIntColumn(t *testing.T) { } func TestNewNumericColumnColumn(t *testing.T) { - numericColumn := NewNumericColumn("col", Nullable) + numericColumn := NewFloatColumn("col", Nullable) out := queryData{} err := numericColumn.serialize(select_statement, &out) diff --git a/sqlbuilder/date_expression.go b/sqlbuilder/date_expression.go index 0b0dd21..52092ff 100644 --- a/sqlbuilder/date_expression.go +++ b/sqlbuilder/date_expression.go @@ -3,49 +3,49 @@ package sqlbuilder type DateExpression interface { expression - EQ(rhs DateExpression) boolExpression - NOT_EQ(rhs DateExpression) boolExpression - IS_DISTINCT_FROM(rhs DateExpression) boolExpression - IS_NOT_DISTINCT_FROM(rhs DateExpression) boolExpression + EQ(rhs DateExpression) BoolExpression + NOT_EQ(rhs DateExpression) BoolExpression + IS_DISTINCT_FROM(rhs DateExpression) BoolExpression + IS_NOT_DISTINCT_FROM(rhs DateExpression) BoolExpression - LT(rhs DateExpression) boolExpression - LT_EQ(rhs DateExpression) boolExpression - GT(rhs DateExpression) boolExpression - GT_EQ(rhs DateExpression) boolExpression + LT(rhs DateExpression) BoolExpression + LT_EQ(rhs DateExpression) BoolExpression + GT(rhs DateExpression) BoolExpression + GT_EQ(rhs DateExpression) BoolExpression } type dateInterfaceImpl struct { parent DateExpression } -func (t *dateInterfaceImpl) EQ(rhs DateExpression) boolExpression { +func (t *dateInterfaceImpl) EQ(rhs DateExpression) BoolExpression { return EQ(t.parent, rhs) } -func (t *dateInterfaceImpl) NOT_EQ(rhs DateExpression) boolExpression { +func (t *dateInterfaceImpl) NOT_EQ(rhs DateExpression) BoolExpression { return NOT_EQ(t.parent, rhs) } -func (t *dateInterfaceImpl) IS_DISTINCT_FROM(rhs DateExpression) boolExpression { +func (t *dateInterfaceImpl) IS_DISTINCT_FROM(rhs DateExpression) BoolExpression { return IS_DISTINCT_FROM(t.parent, rhs) } -func (t *dateInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs DateExpression) boolExpression { +func (t *dateInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs DateExpression) BoolExpression { return IS_NOT_DISTINCT_FROM(t.parent, rhs) } -func (t *dateInterfaceImpl) LT(rhs DateExpression) boolExpression { +func (t *dateInterfaceImpl) LT(rhs DateExpression) BoolExpression { return LT(t.parent, rhs) } -func (t *dateInterfaceImpl) LT_EQ(rhs DateExpression) boolExpression { +func (t *dateInterfaceImpl) LT_EQ(rhs DateExpression) BoolExpression { return LT_EQ(t.parent, rhs) } -func (t *dateInterfaceImpl) GT(rhs DateExpression) boolExpression { +func (t *dateInterfaceImpl) GT(rhs DateExpression) BoolExpression { return GT(t.parent, rhs) } -func (t *dateInterfaceImpl) GT_EQ(rhs DateExpression) boolExpression { +func (t *dateInterfaceImpl) GT_EQ(rhs DateExpression) BoolExpression { return GT_EQ(t.parent, rhs) } diff --git a/sqlbuilder/delete_statement.go b/sqlbuilder/delete_statement.go index 3c7934b..3cd20a9 100644 --- a/sqlbuilder/delete_statement.go +++ b/sqlbuilder/delete_statement.go @@ -9,7 +9,7 @@ import ( type deleteStatement interface { Statement - WHERE(expression boolExpression) deleteStatement + WHERE(expression BoolExpression) deleteStatement } func newDeleteStatement(table writableTable) deleteStatement { @@ -20,10 +20,10 @@ func newDeleteStatement(table writableTable) deleteStatement { type deleteStatementImpl struct { table writableTable - where boolExpression + where BoolExpression } -func (d *deleteStatementImpl) WHERE(expression boolExpression) deleteStatement { +func (d *deleteStatementImpl) WHERE(expression BoolExpression) deleteStatement { d.where = expression return d } diff --git a/sqlbuilder/execution/execution.go b/sqlbuilder/execution/execution.go index 3296473..ef09e7d 100644 --- a/sqlbuilder/execution/execution.go +++ b/sqlbuilder/execution/execution.go @@ -612,7 +612,7 @@ func newScanType(columnType *sql.ColumnType) reflect.Type { return nullStringType case "FLOAT4": return nullFloatType - case "FLOAT8", "NUMERIC": + case "FLOAT8", "NUMERIC", "DECIMAL": return nullFloat64Type case "BOOL": return nullBoolType diff --git a/sqlbuilder/expression.go b/sqlbuilder/expression.go index a964ab1..faaeefc 100644 --- a/sqlbuilder/expression.go +++ b/sqlbuilder/expression.go @@ -11,11 +11,11 @@ type expression interface { groupByClause orderByClause - IS_NULL() boolExpression - IS_NOT_NULL() boolExpression + IS_NULL() BoolExpression + IS_NOT_NULL() BoolExpression - IN(subQuery selectStatement) boolExpression - NOT_IN(subQuery selectStatement) boolExpression + IN(subQuery selectStatement) BoolExpression + NOT_IN(subQuery selectStatement) BoolExpression AS(alias string) projection @@ -27,19 +27,19 @@ type expressionInterfaceImpl struct { parent expression } -func (e *expressionInterfaceImpl) IS_NULL() boolExpression { +func (e *expressionInterfaceImpl) IS_NULL() BoolExpression { return newPostifxBoolExpression(e.parent, "IS NULL") } -func (e *expressionInterfaceImpl) IS_NOT_NULL() boolExpression { +func (e *expressionInterfaceImpl) IS_NOT_NULL() BoolExpression { return newPostifxBoolExpression(e.parent, "IS NOT NULL") } -func (e *expressionInterfaceImpl) IN(subQuery selectStatement) boolExpression { +func (e *expressionInterfaceImpl) IN(subQuery selectStatement) BoolExpression { return newBinaryBoolExpression(e.parent, subQuery, "IN") } -func (e *expressionInterfaceImpl) NOT_IN(subQuery selectStatement) boolExpression { +func (e *expressionInterfaceImpl) NOT_IN(subQuery selectStatement) BoolExpression { return newBinaryBoolExpression(e.parent, subQuery, "NOT IN") } @@ -90,7 +90,7 @@ func isSimpleOperand(expression expression) bool { if _, ok := expression.(column); ok { return true } - if _, ok := expression.(*numericFunc); ok { + if _, ok := expression.(*floatFunc); ok { return true } diff --git a/sqlbuilder/expression_old_test.go b/sqlbuilder/expression_old_test.go index ae913ec..4077a2c 100644 --- a/sqlbuilder/expression_old_test.go +++ b/sqlbuilder/expression_old_test.go @@ -77,7 +77,7 @@ func (s *ExprSuite) TestRegexExpr(c *gc.C) { } func (s *ExprSuite) TestAndExpr(c *gc.C) { - expr := And(EqL(table1Col1, 1), EqL(table1Col2, 2), EqL(table1Col3, 3)) + expr := And(EqL(table1Col1, 1), EqL(table1ColFloat, 2), EqL(table1Col3, 3)) buf := &bytes.Buffer{} @@ -92,7 +92,7 @@ func (s *ExprSuite) TestAndExpr(c *gc.C) { } func (s *ExprSuite) TestOrExpr(c *gc.C) { - expr := Or(EqL(table1Col1, 1), EqL(table1Col2, 2), EqL(table1Col3, 3)) + expr := Or(EqL(table1Col1, 1), EqL(table1ColFloat, 2), EqL(table1Col3, 3)) buf := &bytes.Buffer{} @@ -331,7 +331,7 @@ func (s *ExprSuite) TestSqlFuncExprEmptyArgList(c *gc.C) { } func (s *ExprSuite) TestSqlFuncExprNonEmptyArgList(c *gc.C) { - expr := SqlFunc("add", table1Col1, table1Col2) + expr := SqlFunc("add", table1Col1, table1ColFloat) buf := &bytes.Buffer{} diff --git a/sqlbuilder/expression_table.go b/sqlbuilder/expression_table.go index 3a57dcb..ad5d8c5 100644 --- a/sqlbuilder/expression_table.go +++ b/sqlbuilder/expression_table.go @@ -71,7 +71,7 @@ func (e *expressionTableImpl) SELECT(projections ...projection) selectStatement } // Creates a inner join tableName expression using onCondition. -func (e *expressionTableImpl) INNER_JOIN(table readableTable, onCondition boolExpression) readableTable { +func (e *expressionTableImpl) INNER_JOIN(table readableTable, onCondition BoolExpression) readableTable { return InnerJoinOn(e, table, onCondition) } @@ -80,16 +80,16 @@ func (e *expressionTableImpl) INNER_JOIN(table readableTable, onCondition boolEx //} // Creates a left join tableName expression using onCondition. -func (e *expressionTableImpl) LEFT_JOIN(table readableTable, onCondition boolExpression) readableTable { +func (e *expressionTableImpl) LEFT_JOIN(table readableTable, onCondition BoolExpression) readableTable { return LeftJoinOn(e, table, onCondition) } // Creates a right join tableName expression using onCondition. -func (e *expressionTableImpl) RIGHT_JOIN(table readableTable, onCondition boolExpression) readableTable { +func (e *expressionTableImpl) RIGHT_JOIN(table readableTable, onCondition BoolExpression) readableTable { return RightJoinOn(e, table, onCondition) } -func (e *expressionTableImpl) FULL_JOIN(table readableTable, onCondition boolExpression) readableTable { +func (e *expressionTableImpl) FULL_JOIN(table readableTable, onCondition BoolExpression) readableTable { return FullJoin(e, table, onCondition) } diff --git a/sqlbuilder/float_expression.go b/sqlbuilder/float_expression.go new file mode 100644 index 0000000..ae5b330 --- /dev/null +++ b/sqlbuilder/float_expression.go @@ -0,0 +1,123 @@ +package sqlbuilder + +import "errors" + +type FloatExpression interface { + expression + + EQ(rhs FloatExpression) BoolExpression + NOT_EQ(rhs FloatExpression) BoolExpression + IS_DISTINCT_FROM(rhs FloatExpression) BoolExpression + IS_NOT_DISTINCT_FROM(rhs FloatExpression) BoolExpression + + LT(rhs FloatExpression) BoolExpression + LT_EQ(rhs FloatExpression) BoolExpression + GT(rhs FloatExpression) BoolExpression + GT_EQ(rhs FloatExpression) BoolExpression + + ADD(rhs FloatExpression) FloatExpression + SUB(rhs FloatExpression) FloatExpression + MUL(rhs FloatExpression) FloatExpression + DIV(rhs FloatExpression) FloatExpression +} + +type floatInterfaceImpl struct { + parent FloatExpression +} + +func (n *floatInterfaceImpl) EQ(rhs FloatExpression) BoolExpression { + return EQ(n.parent, rhs) +} + +func (n *floatInterfaceImpl) NOT_EQ(rhs FloatExpression) BoolExpression { + return NOT_EQ(n.parent, rhs) +} + +func (n *floatInterfaceImpl) IS_DISTINCT_FROM(rhs FloatExpression) BoolExpression { + return IS_DISTINCT_FROM(n.parent, rhs) +} + +func (n *floatInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs FloatExpression) BoolExpression { + return IS_NOT_DISTINCT_FROM(n.parent, rhs) +} + +func (n *floatInterfaceImpl) GT(rhs FloatExpression) BoolExpression { + return GT(n.parent, rhs) +} + +func (n *floatInterfaceImpl) GT_EQ(rhs FloatExpression) BoolExpression { + return GT_EQ(n.parent, rhs) +} + +func (n *floatInterfaceImpl) LT(expression FloatExpression) BoolExpression { + return LT(n.parent, expression) +} + +func (n *floatInterfaceImpl) LT_EQ(expression FloatExpression) BoolExpression { + return LT_EQ(n.parent, expression) +} + +func (n *floatInterfaceImpl) ADD(expression FloatExpression) FloatExpression { + return newBinaryFloatExpression(n.parent, expression, "+") +} + +func (n *floatInterfaceImpl) SUB(expression FloatExpression) FloatExpression { + return newBinaryFloatExpression(n.parent, expression, "-") +} + +func (n *floatInterfaceImpl) MUL(expression FloatExpression) FloatExpression { + return newBinaryFloatExpression(n.parent, expression, "*") +} + +func (n *floatInterfaceImpl) DIV(expression FloatExpression) FloatExpression { + return newBinaryFloatExpression(n.parent, expression, "/") +} + +//---------------------------------------------------// +type binaryFloatExpression struct { + expressionInterfaceImpl + floatInterfaceImpl + + binaryOpExpression +} + +func newBinaryFloatExpression(lhs, rhs FloatExpression, operator string) FloatExpression { + floatExpression := binaryFloatExpression{} + + floatExpression.binaryOpExpression = newBinaryExpression(lhs, rhs, operator) + + floatExpression.expressionInterfaceImpl.parent = &floatExpression + floatExpression.floatInterfaceImpl.parent = &floatExpression + + return &floatExpression +} + +////---------------------------------------------------// +type floatExpressionWrapper struct { + expressionInterfaceImpl + floatInterfaceImpl + + expression expression +} + +func newFloatExpressionWrap(expression expression) FloatExpression { + floatExpressionWrap := floatExpressionWrapper{} + + floatExpressionWrap.expression = expression + + floatExpressionWrap.expressionInterfaceImpl.parent = &floatExpressionWrap + floatExpressionWrap.floatInterfaceImpl.parent = &floatExpressionWrap + + return &floatExpressionWrap +} + +func (n *floatExpressionWrapper) serialize(statement statementType, out *queryData) error { + if n == nil { + return errors.New("Float expression wrapper is nil. ") + } + //out.writeString("(") + err := n.expression.serialize(statement, out) + //out.writeString(")") + + return err +} diff --git a/sqlbuilder/numeric_expression_test.go b/sqlbuilder/float_expression_test.go similarity index 62% rename from sqlbuilder/numeric_expression_test.go rename to sqlbuilder/float_expression_test.go index a718be0..8f6fbd0 100644 --- a/sqlbuilder/numeric_expression_test.go +++ b/sqlbuilder/float_expression_test.go @@ -5,34 +5,34 @@ import ( "testing" ) -func TestNumericEQColumn(t *testing.T) { +func TestFloatExpressionEQColumn(t *testing.T) { assert.Equal(t, getTestSerialize(t, table1Col1.EQ(table2Col3)), "table1.col1 = table2.col3") } -func TestNumericEQInt(t *testing.T) { +func TestFloatExpressionEQInt(t *testing.T) { assert.Equal(t, getTestSerialize(t, table1Col1.EQ(Int(11))), "table1.col1 = $1") } -func TestNumericEQFloat(t *testing.T) { - assert.Equal(t, getTestSerialize(t, table1Col1.EQ(Float(22.333))), "table1.col1 = $1") +func TestFloatExpressionEQFloat(t *testing.T) { + assert.Equal(t, getTestSerialize(t, table1Col1.EQ(Int(22))), "table1.col1 = $1") } -func TestNumericNOT_EQ(t *testing.T) { +func TestFloatExpressionNOT_EQ(t *testing.T) { assert.Equal(t, getTestSerialize(t, table1Col1.NOT_EQ(table2Col3)), "table1.col1 != table2.col3") } -func TestNumericGT(t *testing.T) { +func TestFloatExpressionGT(t *testing.T) { assert.Equal(t, getTestSerialize(t, table1Col1.GT(table2Col3)), "table1.col1 > table2.col3") } -func TestNumericGT_EQ(t *testing.T) { +func TestFloatExpressionGT_EQ(t *testing.T) { assert.Equal(t, getTestSerialize(t, table1Col1.GT_EQ(table2Col3)), "table1.col1 >= table2.col3") } -func TestNumericLT(t *testing.T) { +func TestFloatExpressionLT(t *testing.T) { assert.Equal(t, getTestSerialize(t, table1Col1.LT(table2Col3)), "table1.col1 < table2.col3") } -func TestNumericLT_EQ(t *testing.T) { +func TestFloatExpressionLT_EQ(t *testing.T) { assert.Equal(t, getTestSerialize(t, table1Col1.LT_EQ(table2Col3)), "table1.col1 <= table2.col3") } diff --git a/sqlbuilder/func_expression.go b/sqlbuilder/func_expression.go index a4cc0ea..78cf8b2 100644 --- a/sqlbuilder/func_expression.go +++ b/sqlbuilder/func_expression.go @@ -44,126 +44,58 @@ func (f *funcExpressionImpl) serialize(statement statementType, out *queryData) return nil } -type numericFunc struct { +// ------------------- FLOAT FUNCTIONS --------------------------// + +type floatFunc struct { funcExpressionImpl - numericInterfaceImpl + floatInterfaceImpl } -func NewNumericFunc(name string, expressions ...expression) numericExpression { - numericFunc := &numericFunc{} +func newFloatFunc(name string, expressions ...expression) FloatExpression { + floatFunc := &floatFunc{} - numericFunc.funcExpressionImpl = *newFunc(name, expressions, numericFunc) - numericFunc.numericInterfaceImpl.parent = numericFunc + floatFunc.funcExpressionImpl = *newFunc(name, expressions, floatFunc) + floatFunc.floatInterfaceImpl.parent = floatFunc - return numericFunc + return floatFunc } -func COUNT(expression numericExpression) numericExpression { - return NewNumericFunc("COUNT", expression) +func COUNTf(floatExpression FloatExpression) FloatExpression { + return newFloatFunc("COUNT", floatExpression) } -func MAX(expression numericExpression) numericExpression { - return NewNumericFunc("MAX", expression) +func MAXf(floatExpression FloatExpression) FloatExpression { + return newFloatFunc("MAX", floatExpression) } -func SUM(expression numericExpression) numericExpression { - return NewNumericFunc("SUM", expression) +func SUMf(floatExpression FloatExpression) FloatExpression { + return newFloatFunc("SUM", floatExpression) } -type caseInterface interface { - expression +// ------------------- FLOAT FUNCTIONS --------------------------// - WHEN(condition expression) caseInterface - THEN(then expression) caseInterface - ELSE(els expression) caseInterface +type integerFunc struct { + funcExpressionImpl + integerInterfaceImpl } -type caseExpression struct { - expressionInterfaceImpl +func newIntegerFunc(name string, expressions ...expression) IntegerExpression { + floatFunc := &integerFunc{} - expression expression - when []expression - then []expression - els expression + floatFunc.funcExpressionImpl = *newFunc(name, expressions, floatFunc) + floatFunc.integerInterfaceImpl.parent = floatFunc + + return floatFunc } -func CASE(expression ...expression) caseInterface { - caseExp := &caseExpression{} - - if len(expression) == 1 { - caseExp.expression = expression[0] - } - - caseExp.expressionInterfaceImpl.parent = caseExp - - return caseExp +func COUNTi(integerExpression IntegerExpression) IntegerExpression { + return newIntegerFunc("COUNT", integerExpression) } -func (c *caseExpression) WHEN(when expression) caseInterface { - c.when = append(c.when, when) - return c +func MAXi(integerExpression IntegerExpression) IntegerExpression { + return newIntegerFunc("MAX", integerExpression) } -func (c *caseExpression) THEN(then expression) caseInterface { - c.then = append(c.then, then) - return c -} - -func (c *caseExpression) ELSE(els expression) caseInterface { - c.els = els - - return c -} - -func (c *caseExpression) serialize(statement statementType, out *queryData) error { - if c == nil { - return errors.New("Case expression is nil. ") - } - - out.writeString("(CASE") - - if c.expression != nil { - err := c.expression.serialize(statement, out) - - if err != nil { - return err - } - } - - if len(c.when) == 0 || len(c.then) == 0 { - return errors.New("Invalid case Statement. There should be at least one when/then expression pair. ") - } - - if len(c.when) != len(c.then) { - return errors.New("When and then expression count mismatch. ") - } - - for i, when := range c.when { - out.writeString("WHEN") - err := when.serialize(statement, out) - - if err != nil { - return err - } - - out.writeString("THEN") - err = c.then[i].serialize(statement, out) - - if err != nil { - return err - } - } - - if c.els != nil { - out.writeString("ELSE") - err := c.els.serialize(statement, out) - - if err != nil { - return err - } - } - - out.writeString("END)") - - return nil +func SUMi(integerExpression IntegerExpression) IntegerExpression { + return newIntegerFunc("SUM", integerExpression) } diff --git a/sqlbuilder/insert_statement_test.go b/sqlbuilder/insert_statement_test.go index 3ceb2da..931c8f0 100644 --- a/sqlbuilder/insert_statement_test.go +++ b/sqlbuilder/insert_statement_test.go @@ -20,7 +20,7 @@ func TestInsertNoRow(t *testing.T) { } func TestInsertColumnLengthMismatch(t *testing.T) { - _, _, err := table1.INSERT(table1Col1, table1Col2).VALUES(nil).Sql() + _, _, err := table1.INSERT(table1Col1, table1ColFloat).VALUES(nil).Sql() //fmt.Println(err) assert.Assert(t, err != nil) @@ -66,7 +66,7 @@ INSERT INTO db.table1 (colTime) VALUES } func TestInsertMultipleValues(t *testing.T) { - stmt := table1.INSERT(table1Col1, table1Col2, table1Col3) + stmt := table1.INSERT(table1Col1, table1ColFloat, table1Col3) stmt.VALUES(1, 2, 3) sql, _, err := stmt.Sql() @@ -75,7 +75,7 @@ func TestInsertMultipleValues(t *testing.T) { fmt.Println(sql) expectedSql := ` -INSERT INTO db.table1 (col1,col2,col3) VALUES +INSERT INTO db.table1 (col1,colFloat,col3) VALUES ($1, $2, $3); ` @@ -83,7 +83,7 @@ INSERT INTO db.table1 (col1,col2,col3) VALUES } func TestInsertMultipleRows(t *testing.T) { - stmt := table1.INSERT(table1Col1, table1Col2). + stmt := table1.INSERT(table1Col1, table1ColFloat). VALUES(1, 2). VALUES(11, 22). VALUES(111, 222) @@ -94,7 +94,7 @@ func TestInsertMultipleRows(t *testing.T) { fmt.Println(sql) expectedSql := ` -INSERT INTO db.table1 (col1,col2) VALUES +INSERT INTO db.table1 (col1,colFloat) VALUES ($1, $2), ($3, $4), ($5, $6); @@ -105,16 +105,16 @@ INSERT INTO db.table1 (col1,col2) VALUES func TestInsertValuesFromModel(t *testing.T) { type Table1Model struct { - Col1 int - Col2 string + Col1 int + ColFloat float64 } toInsert := Table1Model{ - Col1: 1, - Col2: "one", + Col1: 1, + ColFloat: 1.11, } - stmt := table1.INSERT(table1Col1, table1Col2). + stmt := table1.INSERT(table1Col1, table1ColFloat). VALUES_MAPPING(toInsert) sql, _, err := stmt.Sql() @@ -124,7 +124,7 @@ func TestInsertValuesFromModel(t *testing.T) { fmt.Println(sql) assert.Equal(t, sql, ` -INSERT INTO db.table1 (col1,col2) VALUES +INSERT INTO db.table1 (col1,colFloat) VALUES ($1, $2); `) } @@ -140,7 +140,7 @@ func TestInsertValuesFromModelColumnMismatch(t *testing.T) { Col2: "one", } - stmt := table1.INSERT(table1Col1, table1Col2). + stmt := table1.INSERT(table1Col1, table1ColFloat). VALUES_MAPPING(toInsert) _, _, err := stmt.Sql() @@ -162,7 +162,7 @@ func TestInsertQuery(t *testing.T) { } func TestInsertDefaultValue(t *testing.T) { - stmt := table1.INSERT(table1Col1, table1Col2). + stmt := table1.INSERT(table1Col1, table1ColFloat). VALUES(DEFAULT, "two") stmtStr, _, err := stmt.Sql() diff --git a/sqlbuilder/integer_expression.go b/sqlbuilder/integer_expression.go index 7050a03..c5e3b48 100644 --- a/sqlbuilder/integer_expression.go +++ b/sqlbuilder/integer_expression.go @@ -1,48 +1,109 @@ package sqlbuilder -type integerExpression interface { - numericExpression +type IntegerExpression interface { + expression - BitAnd(expression integerExpression) integerExpression - BitOr(expression integerExpression) integerExpression - BitXor(expression integerExpression) integerExpression - BitNot() integerExpression + EQ(rhs IntegerExpression) BoolExpression + NOT_EQ(rhs IntegerExpression) BoolExpression + IS_DISTINCT_FROM(rhs IntegerExpression) BoolExpression + IS_NOT_DISTINCT_FROM(rhs IntegerExpression) BoolExpression + + LT(rhs IntegerExpression) BoolExpression + LT_EQ(rhs IntegerExpression) BoolExpression + GT(rhs IntegerExpression) BoolExpression + GT_EQ(rhs IntegerExpression) BoolExpression + + ADD(rhs IntegerExpression) IntegerExpression + SUB(rhs IntegerExpression) IntegerExpression + MUL(rhs IntegerExpression) IntegerExpression + DIV(rhs IntegerExpression) IntegerExpression + + BitAnd(expression IntegerExpression) IntegerExpression + BitOr(expression IntegerExpression) IntegerExpression + BitXor(expression IntegerExpression) IntegerExpression + BitNot() IntegerExpression } type integerInterfaceImpl struct { - parent integerExpression + parent IntegerExpression } -func (i *integerInterfaceImpl) BitAnd(expression integerExpression) integerExpression { - return NewBinaryIntegerExpression(i.parent, expression, " & ") +func (i *integerInterfaceImpl) EQ(rhs IntegerExpression) BoolExpression { + return EQ(i.parent, rhs) } -func (i *integerInterfaceImpl) BitOr(expression integerExpression) integerExpression { - return NewBinaryIntegerExpression(i.parent, expression, " | ") +func (i *integerInterfaceImpl) NOT_EQ(rhs IntegerExpression) BoolExpression { + return NOT_EQ(i.parent, rhs) } -func (i *integerInterfaceImpl) BitXor(expression integerExpression) integerExpression { - return NewBinaryIntegerExpression(i.parent, expression, " # ") +func (i *integerInterfaceImpl) IS_DISTINCT_FROM(rhs IntegerExpression) BoolExpression { + return IS_DISTINCT_FROM(i.parent, rhs) } -func (i *integerInterfaceImpl) BitNot() integerExpression { - return NewPrefixIntegerExpression(i.parent, " ~") +func (i *integerInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs IntegerExpression) BoolExpression { + return IS_NOT_DISTINCT_FROM(i.parent, rhs) +} + +func (i *integerInterfaceImpl) GT(rhs IntegerExpression) BoolExpression { + return GT(i.parent, rhs) +} + +func (i *integerInterfaceImpl) GT_EQ(rhs IntegerExpression) BoolExpression { + return GT_EQ(i.parent, rhs) +} + +func (i *integerInterfaceImpl) LT(expression IntegerExpression) BoolExpression { + return LT(i.parent, expression) +} + +func (i *integerInterfaceImpl) LT_EQ(expression IntegerExpression) BoolExpression { + return LT_EQ(i.parent, expression) +} + +func (i *integerInterfaceImpl) ADD(expression IntegerExpression) IntegerExpression { + return NewBinaryIntegerExpression(i.parent, expression, "+") +} + +func (i *integerInterfaceImpl) SUB(expression IntegerExpression) IntegerExpression { + return NewBinaryIntegerExpression(i.parent, expression, "-") +} + +func (i *integerInterfaceImpl) MUL(expression IntegerExpression) IntegerExpression { + return NewBinaryIntegerExpression(i.parent, expression, "*") +} + +func (i *integerInterfaceImpl) DIV(expression IntegerExpression) IntegerExpression { + return NewBinaryIntegerExpression(i.parent, expression, "/") +} + +func (i *integerInterfaceImpl) BitAnd(expression IntegerExpression) IntegerExpression { + return NewBinaryIntegerExpression(i.parent, expression, "&") +} + +func (i *integerInterfaceImpl) BitOr(expression IntegerExpression) IntegerExpression { + return NewBinaryIntegerExpression(i.parent, expression, "|") +} + +func (i *integerInterfaceImpl) BitXor(expression IntegerExpression) IntegerExpression { + return NewBinaryIntegerExpression(i.parent, expression, "#") +} + +func (i *integerInterfaceImpl) BitNot() IntegerExpression { + return NewPrefixIntegerOpExpression(i.parent, "~") } //---------------------------------------------------// type binaryIntegerExpression struct { expressionInterfaceImpl - numericInterfaceImpl integerInterfaceImpl binaryOpExpression } -func NewBinaryIntegerExpression(lhs, rhs integerExpression, operator string) integerExpression { +func NewBinaryIntegerExpression(lhs, rhs IntegerExpression, operator string) IntegerExpression { integerExpression := binaryIntegerExpression{} integerExpression.expressionInterfaceImpl.parent = &integerExpression - integerExpression.numericInterfaceImpl.parent = &integerExpression integerExpression.integerInterfaceImpl.parent = &integerExpression integerExpression.binaryOpExpression = newBinaryExpression(lhs, rhs, operator) @@ -51,20 +112,18 @@ func NewBinaryIntegerExpression(lhs, rhs integerExpression, operator string) int } //---------------------------------------------------// -type prefixIntegerExpression struct { +type prefixIntegerOpExpression struct { expressionInterfaceImpl - numericInterfaceImpl integerInterfaceImpl prefixOpExpression } -func NewPrefixIntegerExpression(expression integerExpression, operator string) integerExpression { - integerExpression := prefixIntegerExpression{} +func NewPrefixIntegerOpExpression(expression IntegerExpression, operator string) IntegerExpression { + integerExpression := prefixIntegerOpExpression{} integerExpression.prefixOpExpression = newPrefixExpression(expression, operator) integerExpression.expressionInterfaceImpl.parent = &integerExpression - integerExpression.numericInterfaceImpl.parent = &integerExpression integerExpression.integerInterfaceImpl.parent = &integerExpression return &integerExpression diff --git a/sqlbuilder/literal_expression.go b/sqlbuilder/literal_expression.go index 7ee975d..d152d02 100644 --- a/sqlbuilder/literal_expression.go +++ b/sqlbuilder/literal_expression.go @@ -21,18 +21,18 @@ func (l literalExpression) serialize(statement statementType, out *queryData) er return nil } -type numLiteralExpression struct { +type integerLiteralExpression struct { literalExpression - numericInterfaceImpl + integerInterfaceImpl } -func Int(value int) numericExpression { - numLiteral := &numLiteralExpression{} +func Int(value int) IntegerExpression { + numLiteral := &integerLiteralExpression{} numLiteral.literalExpression = *Literal(value) - numLiteral.literalExpression.parent = numLiteral - numLiteral.numericInterfaceImpl.parent = numLiteral + numLiteral.literalExpression.parent = numLiteral + numLiteral.integerInterfaceImpl.parent = numLiteral return numLiteral } @@ -43,7 +43,7 @@ type boolLiteralExpression struct { literalExpression } -func Bool(value bool) boolExpression { +func Bool(value bool) BoolExpression { boolLiteralExpression := boolLiteralExpression{} boolLiteralExpression.literalExpression = *Literal(value) @@ -53,18 +53,18 @@ func Bool(value bool) boolExpression { } //---------------------------------------------------// -type numericLiteral struct { - numericInterfaceImpl +type floatLiteral struct { + floatInterfaceImpl literalExpression } -func Float(value float64) numericExpression { - numericLiteral := numericLiteral{} - numericLiteral.literalExpression = *Literal(value) +func Float(value float64) FloatExpression { + floatLiteral := floatLiteral{} + floatLiteral.literalExpression = *Literal(value) - numericLiteral.numericInterfaceImpl.parent = &numericLiteral + floatLiteral.floatInterfaceImpl.parent = &floatLiteral - return &numericLiteral + return &floatLiteral } //---------------------------------------------------// diff --git a/sqlbuilder/numeric_expression.go b/sqlbuilder/numeric_expression.go deleted file mode 100644 index 6d1b69d..0000000 --- a/sqlbuilder/numeric_expression.go +++ /dev/null @@ -1,123 +0,0 @@ -package sqlbuilder - -import "errors" - -type numericExpression interface { - expression - - EQ(rhs numericExpression) boolExpression - NOT_EQ(rhs numericExpression) boolExpression - IS_DISTINCT_FROM(rhs numericExpression) boolExpression - IS_NOT_DISTINCT_FROM(rhs numericExpression) boolExpression - - LT(rhs numericExpression) boolExpression - LT_EQ(rhs numericExpression) boolExpression - GT(rhs numericExpression) boolExpression - GT_EQ(rhs numericExpression) boolExpression - - ADD(rhs numericExpression) numericExpression - SUB(rhs numericExpression) numericExpression - MUL(rhs numericExpression) numericExpression - DIV(rhs numericExpression) numericExpression -} - -type numericInterfaceImpl struct { - parent numericExpression -} - -func (n *numericInterfaceImpl) EQ(rhs numericExpression) boolExpression { - return EQ(n.parent, rhs) -} - -func (n *numericInterfaceImpl) NOT_EQ(rhs numericExpression) boolExpression { - return NOT_EQ(n.parent, rhs) -} - -func (n *numericInterfaceImpl) IS_DISTINCT_FROM(rhs numericExpression) boolExpression { - return IS_DISTINCT_FROM(n.parent, rhs) -} - -func (n *numericInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs numericExpression) boolExpression { - return IS_NOT_DISTINCT_FROM(n.parent, rhs) -} - -func (n *numericInterfaceImpl) GT(rhs numericExpression) boolExpression { - return GT(n.parent, rhs) -} - -func (n *numericInterfaceImpl) GT_EQ(rhs numericExpression) boolExpression { - return GT_EQ(n.parent, rhs) -} - -func (n *numericInterfaceImpl) LT(expression numericExpression) boolExpression { - return LT(n.parent, expression) -} - -func (n *numericInterfaceImpl) LT_EQ(expression numericExpression) boolExpression { - return LT_EQ(n.parent, expression) -} - -func (n *numericInterfaceImpl) ADD(expression numericExpression) numericExpression { - return newBinaryNumericExpression(n.parent, expression, "+") -} - -func (n *numericInterfaceImpl) SUB(expression numericExpression) numericExpression { - return newBinaryNumericExpression(n.parent, expression, "-") -} - -func (n *numericInterfaceImpl) MUL(expression numericExpression) numericExpression { - return newBinaryNumericExpression(n.parent, expression, "*") -} - -func (n *numericInterfaceImpl) DIV(expression numericExpression) numericExpression { - return newBinaryNumericExpression(n.parent, expression, "/") -} - -//---------------------------------------------------// -type binaryNumericExpression struct { - expressionInterfaceImpl - numericInterfaceImpl - - binaryOpExpression -} - -func newBinaryNumericExpression(lhs, rhs expression, operator string) numericExpression { - numericExpression := binaryNumericExpression{} - - numericExpression.binaryOpExpression = newBinaryExpression(lhs, rhs, operator) - - numericExpression.expressionInterfaceImpl.parent = &numericExpression - numericExpression.numericInterfaceImpl.parent = &numericExpression - - return &numericExpression -} - -//---------------------------------------------------// -type numericExpressionWrapper struct { - expressionInterfaceImpl - numericInterfaceImpl - - expression expression -} - -func newNumericExpressionWrap(expression expression) numericExpression { - numericExpressionWrap := numericExpressionWrapper{} - - numericExpressionWrap.expression = expression - - numericExpressionWrap.expressionInterfaceImpl.parent = &numericExpressionWrap - numericExpressionWrap.numericInterfaceImpl.parent = &numericExpressionWrap - - return &numericExpressionWrap -} - -func (n *numericExpressionWrapper) serialize(statement statementType, out *queryData) error { - if n == nil { - return errors.New("Numeric expression wrapper is nil. ") - } - //out.writeString("(") - err := n.expression.serialize(statement, out) - //out.writeString(")") - - return err -} diff --git a/sqlbuilder/operators.go b/sqlbuilder/operators.go index 85abd55..631efd0 100644 --- a/sqlbuilder/operators.go +++ b/sqlbuilder/operators.go @@ -1,101 +1,203 @@ package sqlbuilder +import "errors" + //----------- Logical operators ---------------// // Returns a representation of "not expr" -func NOT(expr boolExpression) boolExpression { +func NOT(expr BoolExpression) BoolExpression { return newPrefixBoolExpression(expr, "NOT") } //----------- Comparison operators ---------------// // Returns a representation of "a=b" -func EQ(lhs, rhs expression) boolExpression { +func EQ(lhs, rhs expression) BoolExpression { return newBinaryBoolExpression(lhs, rhs, "=") } // Returns a representation of "a!=b" -func NOT_EQ(lhs, rhs expression) boolExpression { +func NOT_EQ(lhs, rhs expression) BoolExpression { return newBinaryBoolExpression(lhs, rhs, "!=") } -func IS_DISTINCT_FROM(lhs, rhs expression) boolExpression { +func IS_DISTINCT_FROM(lhs, rhs expression) BoolExpression { return newBinaryBoolExpression(lhs, rhs, "IS DISTINCT FROM") } -func IS_NOT_DISTINCT_FROM(lhs, rhs expression) boolExpression { +func IS_NOT_DISTINCT_FROM(lhs, rhs expression) BoolExpression { return newBinaryBoolExpression(lhs, rhs, "IS NOT DISTINCT FROM") } // Returns a representation of "ab" -func GT(lhs, rhs expression) boolExpression { +func GT(lhs, rhs expression) BoolExpression { return newBinaryBoolExpression(lhs, rhs, ">") } // Returns a representation of "a>=b" -func GT_EQ(lhs, rhs expression) boolExpression { +func GT_EQ(lhs, rhs expression) BoolExpression { return newBinaryBoolExpression(lhs, rhs, ">=") } -func IS_TRUE(expr boolExpression) boolExpression { +func IS_TRUE(expr BoolExpression) BoolExpression { return newPostifxBoolExpression(expr, "IS TRUE") } -func IS_NOT_TRUE(expr boolExpression) boolExpression { +func IS_NOT_TRUE(expr BoolExpression) BoolExpression { return newPostifxBoolExpression(expr, "IS NOT TRUE") } -func IS_FALSE(expr boolExpression) boolExpression { +func IS_FALSE(expr BoolExpression) BoolExpression { return newPostifxBoolExpression(expr, "IS FALSE") } -func IS_NOT_FALSE(expr boolExpression) boolExpression { +func IS_NOT_FALSE(expr BoolExpression) BoolExpression { return newPostifxBoolExpression(expr, "IS NOT FALSE") } -func IS_UNKNOWN(expr boolExpression) boolExpression { +func IS_UNKNOWN(expr BoolExpression) BoolExpression { return newPostifxBoolExpression(expr, "IS UNKNOWN") } -func IS_NOT_UNKNOWN(expr boolExpression) boolExpression { +func IS_NOT_UNKNOWN(expr BoolExpression) BoolExpression { return newPostifxBoolExpression(expr, "IS NOT UNKNOWN") } -func And(lhs, rhs expression) boolExpression { +func And(lhs, rhs expression) BoolExpression { return newBinaryBoolExpression(lhs, rhs, "AND") } // Returns a representation of "c[0] OR ... OR c[n-1]" for c in clauses -func Or(lhs, rhs expression) boolExpression { +func Or(lhs, rhs expression) BoolExpression { return newBinaryBoolExpression(lhs, rhs, "OR") } -func Like(lhs, rhs expression) boolExpression { +func Like(lhs, rhs expression) BoolExpression { return newBinaryBoolExpression(lhs, rhs, "LIKE") } -func LikeL(lhs expression, val string) boolExpression { +func LikeL(lhs expression, val string) BoolExpression { return Like(lhs, Literal(val)) } -func Regexp(lhs, rhs expression) boolExpression { +func Regexp(lhs, rhs expression) BoolExpression { return newBinaryBoolExpression(lhs, rhs, "REGEXP") } -func RegexpL(lhs expression, val string) boolExpression { +func RegexpL(lhs expression, val string) BoolExpression { return Regexp(lhs, Literal(val)) } -func EXISTS(subQuery selectStatement) boolExpression { +func EXISTS(subQuery selectStatement) BoolExpression { return newPrefixBoolExpression(subQuery, "EXISTS") } + +// --------------- CASE operator -------------------// + +type caseOperatorExpression interface { + expression + + WHEN(condition expression) caseOperatorExpression + THEN(then expression) caseOperatorExpression + ELSE(els expression) caseOperatorExpression +} + +type caseOperatorImpl struct { + expressionInterfaceImpl + + expression expression + when []expression + then []expression + els expression +} + +func CASE(expression ...expression) caseOperatorExpression { + caseExp := &caseOperatorImpl{} + + if len(expression) == 1 { + caseExp.expression = expression[0] + } + + caseExp.expressionInterfaceImpl.parent = caseExp + + return caseExp +} + +func (c *caseOperatorImpl) WHEN(when expression) caseOperatorExpression { + c.when = append(c.when, when) + return c +} + +func (c *caseOperatorImpl) THEN(then expression) caseOperatorExpression { + c.then = append(c.then, then) + return c +} + +func (c *caseOperatorImpl) ELSE(els expression) caseOperatorExpression { + c.els = els + + return c +} + +func (c *caseOperatorImpl) serialize(statement statementType, out *queryData) error { + if c == nil { + return errors.New("Case expression is nil. ") + } + + out.writeString("(CASE") + + if c.expression != nil { + err := c.expression.serialize(statement, out) + + if err != nil { + return err + } + } + + if len(c.when) == 0 || len(c.then) == 0 { + return errors.New("Invalid case Statement. There should be at least one when/then expression pair. ") + } + + if len(c.when) != len(c.then) { + return errors.New("When and then expression count mismatch. ") + } + + for i, when := range c.when { + out.writeString("WHEN") + err := when.serialize(statement, out) + + if err != nil { + return err + } + + out.writeString("THEN") + err = c.then[i].serialize(statement, out) + + if err != nil { + return err + } + } + + if c.els != nil { + out.writeString("ELSE") + err := c.els.serialize(statement, out) + + if err != nil { + return err + } + } + + out.writeString("END)") + + return nil +} diff --git a/sqlbuilder/select_statement.go b/sqlbuilder/select_statement.go index 1c0fbe9..bf9ca81 100644 --- a/sqlbuilder/select_statement.go +++ b/sqlbuilder/select_statement.go @@ -13,9 +13,9 @@ type selectStatement interface { DISTINCT() selectStatement FROM(table readableTable) selectStatement - WHERE(expression boolExpression) selectStatement + WHERE(expression BoolExpression) selectStatement GROUP_BY(groupByClauses ...groupByClause) selectStatement - HAVING(boolExpression boolExpression) selectStatement + HAVING(boolExpression BoolExpression) selectStatement ORDER_BY(orderByClauses ...orderByClause) selectStatement LIMIT(limit int64) selectStatement @@ -39,9 +39,9 @@ type selectStatementImpl struct { table readableTable distinct bool projections []projection - where boolExpression + where BoolExpression groupBy []groupByClause - having boolExpression + having BoolExpression orderBy []orderByClause limit, offset int64 @@ -217,7 +217,7 @@ func (s *selectStatementImpl) AsTable(alias string) expressionTable { } } -func (s *selectStatementImpl) WHERE(expression boolExpression) selectStatement { +func (s *selectStatementImpl) WHERE(expression BoolExpression) selectStatement { s.where = expression return s } @@ -227,7 +227,7 @@ func (s *selectStatementImpl) GROUP_BY(groupByClauses ...groupByClause) selectSt return s } -func (s *selectStatementImpl) HAVING(expression boolExpression) selectStatement { +func (s *selectStatementImpl) HAVING(expression BoolExpression) selectStatement { s.having = expression return s } @@ -267,6 +267,6 @@ func (s *selectStatementImpl) Execute(db execution.Db) (res sql.Result, err erro return Execute(s, db) } -func NumExp(expression expression) numericExpression { - return newNumericExpressionWrap(expression) +func NumExp(expression expression) FloatExpression { + return newFloatExpressionWrap(expression) } diff --git a/sqlbuilder/statement_test.go b/sqlbuilder/statement_test.go index 907feab..095603d 100644 --- a/sqlbuilder/statement_test.go +++ b/sqlbuilder/statement_test.go @@ -38,7 +38,7 @@ func (s *StmtSuite) TestSelectSingleColumn(c *gc.C) { } func (s *StmtSuite) TestSelectMultiColumns(c *gc.C) { - sql, err := table1.Select(table1Col1, table1Col2).String() + sql, err := table1.Select(table1Col1, table1ColFloat).String() c.Assert(err, gc.IsNil) c.Assert( @@ -130,9 +130,9 @@ func (s *StmtSuite) TestSelectLimitWithOffset(c *gc.C) { func (s *StmtSuite) TestSelectGroupBy(c *gc.C) { q := table1.Select( table1Col1, - table1Col2, + table1ColFloat, Alias("total", SqlFunc("sum", table1Col3))) - q.GroupBy(table1Col1, table1Col2) + q.GroupBy(table1Col1, table1ColFloat) sql, err := q.String() c.Assert(err, gc.IsNil) @@ -145,7 +145,7 @@ func (s *StmtSuite) TestSelectGroupBy(c *gc.C) { } func (s *StmtSuite) TestSelectSingleOrderBy(c *gc.C) { - q := table1.Select(table1Col1, table1Col2).OrderBy(table1Col2) + q := table1.Select(table1Col1, table1ColFloat).OrderBy(table1ColFloat) sql, err := q.String() c.Assert(err, gc.IsNil) @@ -157,7 +157,7 @@ func (s *StmtSuite) TestSelectSingleOrderBy(c *gc.C) { } func (s *StmtSuite) TestSelectOrderByAsc(c *gc.C) { - q := table1.Select(table1Col1, table1Col2).OrderBy(ASC(table1Col2)) + q := table1.Select(table1Col1, table1ColFloat).OrderBy(ASC(table1ColFloat)) sql, err := q.String() c.Assert(err, gc.IsNil) @@ -169,7 +169,7 @@ func (s *StmtSuite) TestSelectOrderByAsc(c *gc.C) { } func (s *StmtSuite) TestSelectOrderByDesc(c *gc.C) { - q := table1.Select(table1Col1, table1Col2).OrderBy(DESC(table1Col2)) + q := table1.Select(table1Col1, table1ColFloat).OrderBy(DESC(table1ColFloat)) sql, err := q.String() c.Assert(err, gc.IsNil) @@ -181,8 +181,8 @@ func (s *StmtSuite) TestSelectOrderByDesc(c *gc.C) { } func (s *StmtSuite) TestSelectMultiOrderBy(c *gc.C) { - q := table1.Select(table1Col1, table1Col2) - q.OrderBy(table1Col2, table1Col1) + q := table1.Select(table1Col1, table1ColFloat) + q.OrderBy(table1ColFloat, table1Col1) sql, err := q.String() c.Assert(err, gc.IsNil) @@ -249,7 +249,7 @@ func (s *StmtSuite) TestInsertNoRow(c *gc.C) { } func (s *StmtSuite) TestInsertColumnLengthMismatch(c *gc.C) { - _, err := table1.INSERT(table1Col1, table1Col2).Add(nil).String() + _, err := table1.INSERT(table1Col1, table1ColFloat).Add(nil).String() c.Assert(err, gc.NotNil) } @@ -301,7 +301,7 @@ func (s *StmtSuite) TestInsertIgnore(c *gc.C) { } func (s *StmtSuite) TestInsertMultipleValues(c *gc.C) { - stmt := table1.INSERT(table1Col1, table1Col2, table1Col3) + stmt := table1.INSERT(table1Col1, table1ColFloat, table1Col3) stmt.Add(Literal(1), Literal(2), Literal(3)) sql, err := stmt.String() @@ -316,7 +316,7 @@ func (s *StmtSuite) TestInsertMultipleValues(c *gc.C) { } func (s *StmtSuite) TestInsertMultipleRows(c *gc.C) { - stmt := table1.INSERT(table1Col1, table1Col2) + stmt := table1.INSERT(table1Col1, table1ColFloat) stmt.Add(Literal(1), Literal(2)) stmt.Add(Literal(11), Literal(22)) stmt.Add(Literal(111), Literal(222)) @@ -333,7 +333,7 @@ func (s *StmtSuite) TestInsertMultipleRows(c *gc.C) { } func (s *StmtSuite) TestOnDuplicateKeyUpdateNilCol(c *gc.C) { - stmt := table1.INSERT(table1Col1, table1Col2) + stmt := table1.INSERT(table1Col1, table1ColFloat) stmt.Add(Literal(1), Literal(2)) stmt.AddOnDuplicateKeyUpdate(nil, Literal(3)) @@ -342,7 +342,7 @@ func (s *StmtSuite) TestOnDuplicateKeyUpdateNilCol(c *gc.C) { } func (s *StmtSuite) TestOnDuplicateKeyUpdateNilExpr(c *gc.C) { - stmt := table1.INSERT(table1Col1, table1Col2) + stmt := table1.INSERT(table1Col1, table1ColFloat) stmt.Add(Literal(1), Literal(2)) stmt.AddOnDuplicateKeyUpdate(table1Col1, nil) @@ -351,7 +351,7 @@ func (s *StmtSuite) TestOnDuplicateKeyUpdateNilExpr(c *gc.C) { } func (s *StmtSuite) TestOnDuplicateKeyUpdateSingle(c *gc.C) { - stmt := table1.INSERT(table1Col1, table1Col2) + stmt := table1.INSERT(table1Col1, table1ColFloat) stmt.Add(Literal(1), Literal(2)) stmt.AddOnDuplicateKeyUpdate(table1Col3, Literal(3)) @@ -368,10 +368,10 @@ func (s *StmtSuite) TestOnDuplicateKeyUpdateSingle(c *gc.C) { } func (s *StmtSuite) TestOnDuplicateKeyUpdateMulti(c *gc.C) { - stmt := table1.INSERT(table1Col1, table1Col2) + stmt := table1.INSERT(table1Col1, table1ColFloat) stmt.Add(Literal(1), Literal(2)) stmt.AddOnDuplicateKeyUpdate(table1Col3, Literal(3)) - stmt.AddOnDuplicateKeyUpdate(table1Col2, Literal(4)) + stmt.AddOnDuplicateKeyUpdate(table1ColFloat, Literal(4)) sql, err := stmt.String() c.Assert(err, gc.IsNil) @@ -431,7 +431,7 @@ func (s *StmtSuite) TestUnionLimitWithoutOrderBy(c *gc.C) { select_queries := make([]selectStatement, 0, 3) select_queries = append(select_queries, - table1.Select(table1Col1).Where(GtL(table1Col1, 123)).OrderBy(table1Col2), + table1.Select(table1Col1).Where(GtL(table1Col1, 123)).OrderBy(table1ColFloat), table1.Select(table1Col1).Where(GtL(table1Col1, 456)), table1.Select(table1Col1).Where(LtL(table1Col1, 23)), ) @@ -454,7 +454,7 @@ func (s *StmtSuite) TestUnionSelectWithMismatchedColumns(c *gc.C) { table1.Select( table1Col1, - table1Col2, + table1ColFloat, table1Col3, table1ColTime).AndWhere(GtL(table1Col1, 123)).AndWhere(LtL(table1Col1, 321)), table1.Select(table1Col1).Where(And(GtL(table1Col1, 123), LtL(table1Col1, 321))), diff --git a/sqlbuilder/string_expression.go b/sqlbuilder/string_expression.go index 14cdb61..59e023a 100644 --- a/sqlbuilder/string_expression.go +++ b/sqlbuilder/string_expression.go @@ -3,49 +3,49 @@ package sqlbuilder type stringExpression interface { expression - EQ(rhs stringExpression) boolExpression - NOT_EQ(rhs stringExpression) boolExpression - IS_DISTINCT_FROM(rhs stringExpression) boolExpression - IS_NOT_DISTINCT_FROM(rhs stringExpression) boolExpression + EQ(rhs stringExpression) BoolExpression + NOT_EQ(rhs stringExpression) BoolExpression + IS_DISTINCT_FROM(rhs stringExpression) BoolExpression + IS_NOT_DISTINCT_FROM(rhs stringExpression) BoolExpression - LT(rhs stringExpression) boolExpression - LT_EQ(rhs stringExpression) boolExpression - GT(rhs stringExpression) boolExpression - GT_EQ(rhs stringExpression) boolExpression + LT(rhs stringExpression) BoolExpression + LT_EQ(rhs stringExpression) BoolExpression + GT(rhs stringExpression) BoolExpression + GT_EQ(rhs stringExpression) BoolExpression } type stringInterfaceImpl struct { parent stringExpression } -func (s *stringInterfaceImpl) EQ(rhs stringExpression) boolExpression { +func (s *stringInterfaceImpl) EQ(rhs stringExpression) BoolExpression { return EQ(s.parent, rhs) } -func (s *stringInterfaceImpl) NOT_EQ(rhs stringExpression) boolExpression { +func (s *stringInterfaceImpl) NOT_EQ(rhs stringExpression) BoolExpression { return NOT_EQ(s.parent, rhs) } -func (s *stringInterfaceImpl) IS_DISTINCT_FROM(rhs stringExpression) boolExpression { +func (s *stringInterfaceImpl) IS_DISTINCT_FROM(rhs stringExpression) BoolExpression { return IS_DISTINCT_FROM(s.parent, rhs) } -func (s *stringInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs stringExpression) boolExpression { +func (s *stringInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs stringExpression) BoolExpression { return IS_NOT_DISTINCT_FROM(s.parent, rhs) } -func (s *stringInterfaceImpl) GT(rhs stringExpression) boolExpression { +func (s *stringInterfaceImpl) GT(rhs stringExpression) BoolExpression { return GT(s.parent, rhs) } -func (s *stringInterfaceImpl) GT_EQ(rhs stringExpression) boolExpression { +func (s *stringInterfaceImpl) GT_EQ(rhs stringExpression) BoolExpression { return GT_EQ(s.parent, rhs) } -func (s *stringInterfaceImpl) LT(rhs stringExpression) boolExpression { +func (s *stringInterfaceImpl) LT(rhs stringExpression) BoolExpression { return LT(s.parent, rhs) } -func (s *stringInterfaceImpl) LT_EQ(rhs stringExpression) boolExpression { +func (s *stringInterfaceImpl) LT_EQ(rhs stringExpression) BoolExpression { return LT_EQ(s.parent, rhs) } diff --git a/sqlbuilder/table.go b/sqlbuilder/table.go index a2b09e1..91d3842 100644 --- a/sqlbuilder/table.go +++ b/sqlbuilder/table.go @@ -23,15 +23,15 @@ type readableTable interface { SELECT(projections ...projection) selectStatement // Creates a inner join tableName expression using onCondition. - INNER_JOIN(table readableTable, onCondition boolExpression) readableTable + INNER_JOIN(table readableTable, onCondition BoolExpression) readableTable // Creates a left join tableName expression using onCondition. - LEFT_JOIN(table readableTable, onCondition boolExpression) readableTable + LEFT_JOIN(table readableTable, onCondition BoolExpression) readableTable // Creates a right join tableName expression using onCondition. - RIGHT_JOIN(table readableTable, onCondition boolExpression) readableTable + RIGHT_JOIN(table readableTable, onCondition BoolExpression) readableTable - FULL_JOIN(table readableTable, onCondition boolExpression) readableTable + FULL_JOIN(table readableTable, onCondition BoolExpression) readableTable CROSS_JOIN(table readableTable) readableTable } @@ -132,7 +132,7 @@ func (t *Table) SELECT(projections ...projection) selectStatement { // Creates a inner join tableName expression using onCondition. func (t *Table) INNER_JOIN( table readableTable, - onCondition boolExpression) readableTable { + onCondition BoolExpression) readableTable { return InnerJoinOn(t, table, onCondition) } @@ -140,7 +140,7 @@ func (t *Table) INNER_JOIN( // Creates a left join tableName expression using onCondition. func (t *Table) LEFT_JOIN( table readableTable, - onCondition boolExpression) readableTable { + onCondition BoolExpression) readableTable { return LeftJoinOn(t, table, onCondition) } @@ -148,12 +148,12 @@ func (t *Table) LEFT_JOIN( // Creates a right join tableName expression using onCondition. func (t *Table) RIGHT_JOIN( table readableTable, - onCondition boolExpression) readableTable { + onCondition BoolExpression) readableTable { return RightJoinOn(t, table, onCondition) } -func (t *Table) FULL_JOIN(table readableTable, onCondition boolExpression) readableTable { +func (t *Table) FULL_JOIN(table readableTable, onCondition BoolExpression) readableTable { return FullJoin(t, table, onCondition) } @@ -192,14 +192,14 @@ type joinTable struct { lhs readableTable rhs readableTable join_type joinType - onCondition boolExpression + onCondition BoolExpression } func newJoinTable( lhs readableTable, rhs readableTable, join_type joinType, - onCondition boolExpression) readableTable { + onCondition BoolExpression) readableTable { return &joinTable{ lhs: lhs, @@ -212,7 +212,7 @@ func newJoinTable( func InnerJoinOn( lhs readableTable, rhs readableTable, - onCondition boolExpression) readableTable { + onCondition BoolExpression) readableTable { return newJoinTable(lhs, rhs, INNER_JOIN, onCondition) } @@ -220,7 +220,7 @@ func InnerJoinOn( func LeftJoinOn( lhs readableTable, rhs readableTable, - onCondition boolExpression) readableTable { + onCondition BoolExpression) readableTable { return newJoinTable(lhs, rhs, LEFT_JOIN, onCondition) } @@ -228,7 +228,7 @@ func LeftJoinOn( func RightJoinOn( lhs readableTable, rhs readableTable, - onCondition boolExpression) readableTable { + onCondition BoolExpression) readableTable { return newJoinTable(lhs, rhs, RIGHT_JOIN, onCondition) } @@ -236,7 +236,7 @@ func RightJoinOn( func FullJoin( lhs readableTable, rhs readableTable, - onCondition boolExpression) readableTable { + onCondition BoolExpression) readableTable { return newJoinTable(lhs, rhs, FULL_JOIN, onCondition) } @@ -324,19 +324,19 @@ func (t *joinTable) SELECT(projections ...projection) selectStatement { func (t *joinTable) INNER_JOIN( table readableTable, - onCondition boolExpression) readableTable { + onCondition BoolExpression) readableTable { return InnerJoinOn(t, table, onCondition) } func (t *joinTable) LEFT_JOIN( table readableTable, - onCondition boolExpression) readableTable { + onCondition BoolExpression) readableTable { return LeftJoinOn(t, table, onCondition) } -func (t *joinTable) FULL_JOIN(table readableTable, onCondition boolExpression) readableTable { +func (t *joinTable) FULL_JOIN(table readableTable, onCondition BoolExpression) readableTable { return FullJoin(t, table, onCondition) } @@ -346,7 +346,7 @@ func (t *joinTable) CROSS_JOIN(table readableTable) readableTable { func (t *joinTable) RIGHT_JOIN( table readableTable, - onCondition boolExpression) readableTable { + onCondition BoolExpression) readableTable { return RightJoinOn(t, table, onCondition) } diff --git a/sqlbuilder/table_test.go b/sqlbuilder/table_test.go index aa6fe15..fb85357 100644 --- a/sqlbuilder/table_test.go +++ b/sqlbuilder/table_test.go @@ -20,7 +20,7 @@ func (s *TableSuite) TestBasicColumns(c *gc.C) { c.Assert(len(cols), gc.Equals, 4) c.Assert(cols[0], gc.Equals, table1Col1) - c.Assert(cols[1], gc.Equals, table1Col2) + c.Assert(cols[1], gc.Equals, table1ColFloat) c.Assert(cols[2], gc.Equals, table1Col3) c.Assert(cols[3], gc.Equals, table1ColTime) } @@ -126,7 +126,7 @@ func (s *TableSuite) TestRightJoin(c *gc.C) { // cols := join.Columns() // c.Assert(len(cols), gc.Equals, 6) // c.Assert(cols[0], gc.Equals, table1Col1) -// c.Assert(cols[1], gc.Equals, table1Col2) +// c.Assert(cols[1], gc.Equals, table1ColFloat) // c.Assert(cols[2], gc.Equals, table1Col3) // c.Assert(cols[3], gc.Equals, table1ColTime) // c.Assert(cols[4], gc.Equals, table2Col3) diff --git a/sqlbuilder/test_utils.go b/sqlbuilder/test_utils.go index 8023b29..987848b 100644 --- a/sqlbuilder/test_utils.go +++ b/sqlbuilder/test_utils.go @@ -6,7 +6,7 @@ import ( ) var table1Col1 = NewIntegerColumn("col1", Nullable) -var table1Col2 = NewIntegerColumn("col2", Nullable) +var table1ColFloat = NewFloatColumn("colFloat", Nullable) var table1Col3 = NewIntegerColumn("col3", Nullable) var table1ColTime = NewTimeColumn("colTime", Nullable) var table1ColBool = NewBoolColumn("colBool", Nullable) @@ -15,7 +15,7 @@ var table1 = NewTable( "db", "table1", table1Col1, - table1Col2, + table1ColFloat, table1Col3, table1ColTime, table1ColBool) diff --git a/sqlbuilder/time_expression.go b/sqlbuilder/time_expression.go index ab90a67..1990374 100644 --- a/sqlbuilder/time_expression.go +++ b/sqlbuilder/time_expression.go @@ -3,50 +3,50 @@ package sqlbuilder type timeExpression interface { expression - EQ(rhs timeExpression) boolExpression - NOT_EQ(rhs timeExpression) boolExpression - IS_DISTINCT_FROM(rhs timeExpression) boolExpression - IS_NOT_DISTINCT_FROM(rhs timeExpression) boolExpression + EQ(rhs timeExpression) BoolExpression + NOT_EQ(rhs timeExpression) BoolExpression + IS_DISTINCT_FROM(rhs timeExpression) BoolExpression + IS_NOT_DISTINCT_FROM(rhs timeExpression) BoolExpression - LT(rhs timeExpression) boolExpression - LT_EQ(rhs timeExpression) boolExpression - GT(rhs timeExpression) boolExpression - GT_EQ(rhs timeExpression) boolExpression + LT(rhs timeExpression) BoolExpression + LT_EQ(rhs timeExpression) BoolExpression + GT(rhs timeExpression) BoolExpression + GT_EQ(rhs timeExpression) BoolExpression } type timeInterfaceImpl struct { parent timeExpression } -func (t *timeInterfaceImpl) EQ(rhs timeExpression) boolExpression { +func (t *timeInterfaceImpl) EQ(rhs timeExpression) BoolExpression { return EQ(t.parent, rhs) } -func (t *timeInterfaceImpl) NOT_EQ(rhs timeExpression) boolExpression { +func (t *timeInterfaceImpl) NOT_EQ(rhs timeExpression) BoolExpression { return NOT_EQ(t.parent, rhs) } -func (t *timeInterfaceImpl) IS_DISTINCT_FROM(rhs timeExpression) boolExpression { +func (t *timeInterfaceImpl) IS_DISTINCT_FROM(rhs timeExpression) BoolExpression { return IS_DISTINCT_FROM(t.parent, rhs) } -func (t *timeInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs timeExpression) boolExpression { +func (t *timeInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs timeExpression) BoolExpression { return IS_NOT_DISTINCT_FROM(t.parent, rhs) } -func (t *timeInterfaceImpl) LT(rhs timeExpression) boolExpression { +func (t *timeInterfaceImpl) LT(rhs timeExpression) BoolExpression { return LT(t.parent, rhs) } -func (t *timeInterfaceImpl) LT_EQ(rhs timeExpression) boolExpression { +func (t *timeInterfaceImpl) LT_EQ(rhs timeExpression) BoolExpression { return LT_EQ(t.parent, rhs) } -func (t *timeInterfaceImpl) GT(rhs timeExpression) boolExpression { +func (t *timeInterfaceImpl) GT(rhs timeExpression) BoolExpression { return GT(t.parent, rhs) } -func (t *timeInterfaceImpl) GT_EQ(rhs timeExpression) boolExpression { +func (t *timeInterfaceImpl) GT_EQ(rhs timeExpression) BoolExpression { return GT_EQ(t.parent, rhs) } diff --git a/sqlbuilder/timestamp_expression.go b/sqlbuilder/timestamp_expression.go index f8ef4a3..78943f0 100644 --- a/sqlbuilder/timestamp_expression.go +++ b/sqlbuilder/timestamp_expression.go @@ -3,49 +3,49 @@ package sqlbuilder type TimestampExpression interface { expression - EQ(rhs TimestampExpression) boolExpression - NOT_EQ(rhs TimestampExpression) boolExpression - IS_DISTINCT_FROM(rhs TimestampExpression) boolExpression - IS_NOT_DISTINCT_FROM(rhs TimestampExpression) boolExpression + EQ(rhs TimestampExpression) BoolExpression + NOT_EQ(rhs TimestampExpression) BoolExpression + IS_DISTINCT_FROM(rhs TimestampExpression) BoolExpression + IS_NOT_DISTINCT_FROM(rhs TimestampExpression) BoolExpression - LT(rhs TimestampExpression) boolExpression - LT_EQ(rhs TimestampExpression) boolExpression - GT(rhs TimestampExpression) boolExpression - GT_EQ(rhs TimestampExpression) boolExpression + LT(rhs TimestampExpression) BoolExpression + LT_EQ(rhs TimestampExpression) BoolExpression + GT(rhs TimestampExpression) BoolExpression + GT_EQ(rhs TimestampExpression) BoolExpression } type timestampInterfaceImpl struct { parent TimestampExpression } -func (t *timestampInterfaceImpl) EQ(rhs TimestampExpression) boolExpression { +func (t *timestampInterfaceImpl) EQ(rhs TimestampExpression) BoolExpression { return EQ(t.parent, rhs) } -func (t *timestampInterfaceImpl) NOT_EQ(rhs TimestampExpression) boolExpression { +func (t *timestampInterfaceImpl) NOT_EQ(rhs TimestampExpression) BoolExpression { return NOT_EQ(t.parent, rhs) } -func (t *timestampInterfaceImpl) IS_DISTINCT_FROM(rhs TimestampExpression) boolExpression { +func (t *timestampInterfaceImpl) IS_DISTINCT_FROM(rhs TimestampExpression) BoolExpression { return IS_DISTINCT_FROM(t.parent, rhs) } -func (t *timestampInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs TimestampExpression) boolExpression { +func (t *timestampInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs TimestampExpression) BoolExpression { return IS_NOT_DISTINCT_FROM(t.parent, rhs) } -func (t *timestampInterfaceImpl) LT(rhs TimestampExpression) boolExpression { +func (t *timestampInterfaceImpl) LT(rhs TimestampExpression) BoolExpression { return LT(t.parent, rhs) } -func (t *timestampInterfaceImpl) LT_EQ(rhs TimestampExpression) boolExpression { +func (t *timestampInterfaceImpl) LT_EQ(rhs TimestampExpression) BoolExpression { return LT_EQ(t.parent, rhs) } -func (t *timestampInterfaceImpl) GT(rhs TimestampExpression) boolExpression { +func (t *timestampInterfaceImpl) GT(rhs TimestampExpression) BoolExpression { return GT(t.parent, rhs) } -func (t *timestampInterfaceImpl) GT_EQ(rhs TimestampExpression) boolExpression { +func (t *timestampInterfaceImpl) GT_EQ(rhs TimestampExpression) BoolExpression { return GT_EQ(t.parent, rhs) } diff --git a/sqlbuilder/timestampz_expression.go b/sqlbuilder/timestampz_expression.go index 40d96e0..bbc1183 100644 --- a/sqlbuilder/timestampz_expression.go +++ b/sqlbuilder/timestampz_expression.go @@ -3,49 +3,49 @@ package sqlbuilder type TimestampzExpression interface { expression - EQ(rhs TimestampzExpression) boolExpression - NOT_EQ(rhs TimestampzExpression) boolExpression - IS_DISTINCT_FROM(rhs TimestampzExpression) boolExpression - IS_NOT_DISTINCT_FROM(rhs TimestampzExpression) boolExpression + EQ(rhs TimestampzExpression) BoolExpression + NOT_EQ(rhs TimestampzExpression) BoolExpression + IS_DISTINCT_FROM(rhs TimestampzExpression) BoolExpression + IS_NOT_DISTINCT_FROM(rhs TimestampzExpression) BoolExpression - LT(rhs TimestampzExpression) boolExpression - LT_EQ(rhs TimestampzExpression) boolExpression - GT(rhs TimestampzExpression) boolExpression - GT_EQ(rhs TimestampzExpression) boolExpression + LT(rhs TimestampzExpression) BoolExpression + LT_EQ(rhs TimestampzExpression) BoolExpression + GT(rhs TimestampzExpression) BoolExpression + GT_EQ(rhs TimestampzExpression) BoolExpression } type timestampzInterfaceImpl struct { parent TimestampzExpression } -func (t *timestampzInterfaceImpl) EQ(rhs TimestampzExpression) boolExpression { +func (t *timestampzInterfaceImpl) EQ(rhs TimestampzExpression) BoolExpression { return EQ(t.parent, rhs) } -func (t *timestampzInterfaceImpl) NOT_EQ(rhs TimestampzExpression) boolExpression { +func (t *timestampzInterfaceImpl) NOT_EQ(rhs TimestampzExpression) BoolExpression { return NOT_EQ(t.parent, rhs) } -func (t *timestampzInterfaceImpl) IS_DISTINCT_FROM(rhs TimestampzExpression) boolExpression { +func (t *timestampzInterfaceImpl) IS_DISTINCT_FROM(rhs TimestampzExpression) BoolExpression { return IS_DISTINCT_FROM(t.parent, rhs) } -func (t *timestampzInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs TimestampzExpression) boolExpression { +func (t *timestampzInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs TimestampzExpression) BoolExpression { return IS_NOT_DISTINCT_FROM(t.parent, rhs) } -func (t *timestampzInterfaceImpl) LT(rhs TimestampzExpression) boolExpression { +func (t *timestampzInterfaceImpl) LT(rhs TimestampzExpression) BoolExpression { return LT(t.parent, rhs) } -func (t *timestampzInterfaceImpl) LT_EQ(rhs TimestampzExpression) boolExpression { +func (t *timestampzInterfaceImpl) LT_EQ(rhs TimestampzExpression) BoolExpression { return LT_EQ(t.parent, rhs) } -func (t *timestampzInterfaceImpl) GT(rhs TimestampzExpression) boolExpression { +func (t *timestampzInterfaceImpl) GT(rhs TimestampzExpression) BoolExpression { return GT(t.parent, rhs) } -func (t *timestampzInterfaceImpl) GT_EQ(rhs TimestampzExpression) boolExpression { +func (t *timestampzInterfaceImpl) GT_EQ(rhs TimestampzExpression) BoolExpression { return GT_EQ(t.parent, rhs) } diff --git a/sqlbuilder/timez_expression.go b/sqlbuilder/timez_expression.go index e00ade1..dbb38c6 100644 --- a/sqlbuilder/timez_expression.go +++ b/sqlbuilder/timez_expression.go @@ -3,50 +3,50 @@ package sqlbuilder type timezExpression interface { expression - EQ(rhs timezExpression) boolExpression - NOT_EQ(rhs timezExpression) boolExpression - IS_DISTINCT_FROM(rhs timezExpression) boolExpression - IS_NOT_DISTINCT_FROM(rhs timezExpression) boolExpression + EQ(rhs timezExpression) BoolExpression + NOT_EQ(rhs timezExpression) BoolExpression + IS_DISTINCT_FROM(rhs timezExpression) BoolExpression + IS_NOT_DISTINCT_FROM(rhs timezExpression) BoolExpression - LT(rhs timezExpression) boolExpression - LT_EQ(rhs timezExpression) boolExpression - GT(rhs timezExpression) boolExpression - GT_EQ(rhs timezExpression) boolExpression + LT(rhs timezExpression) BoolExpression + LT_EQ(rhs timezExpression) BoolExpression + GT(rhs timezExpression) BoolExpression + GT_EQ(rhs timezExpression) BoolExpression } type timezInterfaceImpl struct { parent timezExpression } -func (t *timezInterfaceImpl) EQ(rhs timezExpression) boolExpression { +func (t *timezInterfaceImpl) EQ(rhs timezExpression) BoolExpression { return EQ(t.parent, rhs) } -func (t *timezInterfaceImpl) NOT_EQ(rhs timezExpression) boolExpression { +func (t *timezInterfaceImpl) NOT_EQ(rhs timezExpression) BoolExpression { return NOT_EQ(t.parent, rhs) } -func (t *timezInterfaceImpl) IS_DISTINCT_FROM(rhs timezExpression) boolExpression { +func (t *timezInterfaceImpl) IS_DISTINCT_FROM(rhs timezExpression) BoolExpression { return IS_DISTINCT_FROM(t.parent, rhs) } -func (t *timezInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs timezExpression) boolExpression { +func (t *timezInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs timezExpression) BoolExpression { return IS_NOT_DISTINCT_FROM(t.parent, rhs) } -func (t *timezInterfaceImpl) LT(rhs timezExpression) boolExpression { +func (t *timezInterfaceImpl) LT(rhs timezExpression) BoolExpression { return LT(t.parent, rhs) } -func (t *timezInterfaceImpl) LT_EQ(rhs timezExpression) boolExpression { +func (t *timezInterfaceImpl) LT_EQ(rhs timezExpression) BoolExpression { return LT_EQ(t.parent, rhs) } -func (t *timezInterfaceImpl) GT(rhs timezExpression) boolExpression { +func (t *timezInterfaceImpl) GT(rhs timezExpression) BoolExpression { return GT(t.parent, rhs) } -func (t *timezInterfaceImpl) GT_EQ(rhs timezExpression) boolExpression { +func (t *timezInterfaceImpl) GT_EQ(rhs timezExpression) BoolExpression { return GT_EQ(t.parent, rhs) } diff --git a/sqlbuilder/update_statement.go b/sqlbuilder/update_statement.go index 58e0b99..9a60814 100644 --- a/sqlbuilder/update_statement.go +++ b/sqlbuilder/update_statement.go @@ -10,7 +10,7 @@ type updateStatement interface { Statement SET(values ...interface{}) updateStatement - WHERE(expression boolExpression) updateStatement + WHERE(expression BoolExpression) updateStatement RETURNING(projections ...projection) updateStatement } @@ -25,7 +25,7 @@ type updateStatementImpl struct { table writableTable columns []column updateValues []clause - where boolExpression + where BoolExpression returning []projection } @@ -42,7 +42,7 @@ func (u *updateStatementImpl) SET(values ...interface{}) updateStatement { return u } -func (u *updateStatementImpl) WHERE(expression boolExpression) updateStatement { +func (u *updateStatementImpl) WHERE(expression BoolExpression) updateStatement { u.where = expression return u } diff --git a/sqlbuilder/update_statement_test.go b/sqlbuilder/update_statement_test.go index 5f60882..1ff95ce 100644 --- a/sqlbuilder/update_statement_test.go +++ b/sqlbuilder/update_statement_test.go @@ -11,8 +11,8 @@ import ( // func TestUpdate(t *testing.T) { - stmt := table1.UPDATE(table1Col1, table1Col2). - SET(table1.SELECT(table1Col2, table2Col3)). + stmt := table1.UPDATE(table1Col1, table1ColFloat). + SET(table1.SELECT(table1ColFloat, table2Col3)). WHERE(table1Col1.EQ(Int(2))). RETURNING(table1Col1) @@ -23,8 +23,8 @@ func TestUpdate(t *testing.T) { fmt.Println(stmtStr) assert.Equal(t, stmtStr, ` -UPDATE db.table1 SET (col1,col2) = ( - SELECT table1.col2 AS "table1.col2", +UPDATE db.table1 SET (col1,colFloat) = ( + SELECT table1.colFloat AS "table1.colFloat", table2.col3 AS "table2.col3" FROM db.table1 ) @@ -53,7 +53,7 @@ RETURNING table1.col1 AS "table1.col1"; // //func (s *StmtSuite) TestUpdateSingleValue(c *gc.C) { // stmt := table1.UPDATE().SET(table1Col1, Literal(1)) -// stmt.WHERE(EqString(table1Col2, 2)) +// stmt.WHERE(EqString(table1ColFloat, 2)) // sql, err := stmt.String() // c.Assert(err, gc.IsNil) // @@ -65,7 +65,7 @@ RETURNING table1.col1 AS "table1.col1"; // //func (s *StmtSuite) TestUpdateUsingDeferredLookupColumns(c *gc.C) { // stmt := table1.UPDATE().SET(table1.C("col1"), Literal(1)) -// stmt.WHERE(EqString(table1Col2, 2)) +// stmt.WHERE(EqString(table1ColFloat, 2)) // sql, err := stmt.String() // c.Assert(err, gc.IsNil) // @@ -78,8 +78,8 @@ RETURNING table1.col1 AS "table1.col1"; //func (s *StmtSuite) TestUpdateMultiValues(c *gc.C) { // stmt := table1.UPDATE() // stmt.SET(table1Col1, Literal(1)) -// stmt.SET(table1Col2, Literal(2)) -// stmt.WHERE(EqString(table1Col2, 3)) +// stmt.SET(table1ColFloat, Literal(2)) +// stmt.WHERE(EqString(table1ColFloat, 3)) // sql, err := stmt.String() // c.Assert(err, gc.IsNil) // @@ -93,8 +93,8 @@ RETURNING table1.col1 AS "table1.col1"; // //func (s *StmtSuite) TestUpdateWithOrderBy(c *gc.C) { // stmt := table1.UPDATE().SET(table1Col1, Literal(1)) -// stmt.WHERE(EqString(table1Col2, 2)) -// stmt.ORDER_BY(table1Col2) +// stmt.WHERE(EqString(table1ColFloat, 2)) +// stmt.ORDER_BY(table1ColFloat) // sql, err := stmt.String() // c.Assert(err, gc.IsNil) // @@ -109,7 +109,7 @@ RETURNING table1.col1 AS "table1.col1"; // //func (s *StmtSuite) TestUpdateWithLimit(c *gc.C) { // stmt := table1.UPDATE().SET(table1Col1, Literal(1)) -// stmt.WHERE(EqString(table1Col2, 2)) +// stmt.WHERE(EqString(table1ColFloat, 2)) // stmt.LIMIT(5) // sql, err := stmt.String() // c.Assert(err, gc.IsNil) diff --git a/tests/select_test.go b/tests/select_test.go index 20fe0b6..3309ec7 100644 --- a/tests/select_test.go +++ b/tests/select_test.go @@ -612,7 +612,7 @@ LIMIT 1000; f1 := Film.AS("f1") f2 := Film.AS("f2") - f1.FilmID.EQ(Float(11)) + f1.FilmID.EQ(Int(11)) query := f1. INNER_JOIN(f2, f1.FilmID.NOT_EQ(f2.FilmID).AND(f1.Length.EQ(f2.Length))). @@ -770,7 +770,9 @@ func TestSelectFunctions(t *testing.T) { SELECT MAX(film.rental_rate) AS "max_film_rate" FROM dvds.film; ` - query := Film.SELECT(MAX(Film.RentalRate).AS("max_film_rate")) + query := Film.SELECT( + MAXf(Film.RentalRate).AS("max_film_rate"), + ) assertQuery(t, query, expectedQuery) @@ -807,7 +809,7 @@ WHERE film.rental_rate = ( ORDER BY film.film_id ASC; ` - maxFilmRentalRate := NumExp(Film.SELECT(MAX(Film.RentalRate))) + maxFilmRentalRate := NumExp(Film.SELECT(MAXf(Film.RentalRate))) query := Film. SELECT(Film.AllColumns). @@ -855,17 +857,17 @@ ORDER BY SUM(payment.amount) ASC; customersPaymentQuery := Payment. SELECT( Payment.CustomerID.AS("customer_payment_sum.customer_id"), - SUM(Payment.Amount).AS("customer_payment_sum.amount_sum"), + SUMf(Payment.Amount).AS("customer_payment_sum.amount_sum"), ). GROUP_BY(Payment.CustomerID). ORDER_BY( - SUM(Payment.Amount).ASC(), + SUMf(Payment.Amount).ASC(), ). HAVING( - SUM(Payment.Amount).GT(Int(100)), + SUMf(Payment.Amount).GT(Float(100)), ) - assertQuery(t, customersPaymentQuery, expectedSql, 100) + assertQuery(t, customersPaymentQuery, expectedSql, float64(100)) type CustomerPaymentSum struct { CustomerID int16 @@ -911,7 +913,7 @@ ORDER BY customer_payment_sum.amount_sum ASC; customersPaymentSubQuery := Payment. SELECT( Payment.CustomerID, - SUM(Payment.Amount).AS("amount_sum"), + SUMf(Payment.Amount).AS("amount_sum"), ). GROUP_BY(Payment.CustomerID) @@ -1024,10 +1026,10 @@ OFFSET 20; query := UNION_ALL( Payment. SELECT(Payment.PaymentID.AS("payment.payment_id"), Payment.Amount). - WHERE(Payment.Amount.LT_EQ(Int(100))), + WHERE(Payment.Amount.LT_EQ(Float(100))), Payment. SELECT(Payment.PaymentID, Payment.Amount). - WHERE(Payment.Amount.GT_EQ(Int(200))), + WHERE(Payment.Amount.GT_EQ(Float(200))), ). ORDER_BY(RefColumn("payment.payment_id").ASC(), Payment.Amount.DESC()). LIMIT(10). @@ -1036,7 +1038,7 @@ OFFSET 20; queryStr, _, _ := query.Sql() fmt.Println("-" + queryStr + "-") - assertQuery(t, query, expectedQuery, int(100), int(200), int64(10), int64(20)) + assertQuery(t, query, expectedQuery, float64(100), float64(200), int64(10), int64(20)) dest := []model.Payment{} diff --git a/tests/types_test.go b/tests/types_test.go index 52846db..73887fe 100644 --- a/tests/types_test.go +++ b/tests/types_test.go @@ -91,29 +91,29 @@ func TestBoolOperators(t *testing.T) { func TestNumericOperators(t *testing.T) { query := AllTypes.SELECT( AllTypes.Numeric.EQ(AllTypes.Numeric), - AllTypes.Decimal.EQ(Int(12)), + AllTypes.Decimal.EQ(Float(12)), AllTypes.Real.EQ(Float(12.12)), - AllTypes.Smallint.NOT_EQ(AllTypes.Real), + //AllTypes.Smallint.NOT_EQ(AllTypes.Real), AllTypes.Integer.NOT_EQ(Int(12)), - AllTypes.Bigint.NOT_EQ(Float(12)), + AllTypes.Bigint.NOT_EQ(Int(12)), AllTypes.Numeric.IS_DISTINCT_FROM(AllTypes.Numeric), - AllTypes.Decimal.IS_DISTINCT_FROM(Int(12)), + AllTypes.Decimal.IS_DISTINCT_FROM(Float(12)), AllTypes.Real.IS_DISTINCT_FROM(Float(12.12)), AllTypes.Numeric.IS_NOT_DISTINCT_FROM(AllTypes.Numeric), - AllTypes.Decimal.IS_NOT_DISTINCT_FROM(Int(12)), + AllTypes.Decimal.IS_NOT_DISTINCT_FROM(Float(12)), AllTypes.Real.IS_NOT_DISTINCT_FROM(Float(12.12)), - AllTypes.Numeric.LT(AllTypes.Integer), - AllTypes.Numeric.LT(Int(124)), + //AllTypes.Numeric.LT(AllTypes.Integer), + AllTypes.Numeric.LT(Float(124)), AllTypes.Numeric.LT(Float(34.56)), - AllTypes.Smallint.LT_EQ(AllTypes.Numeric), + //AllTypes.Smallint.LT_EQ(AllTypes.Numeric), AllTypes.Integer.LT_EQ(Int(45)), - AllTypes.Bigint.LT_EQ(Float(65)), - AllTypes.Numeric.GT(AllTypes.Smallint), - AllTypes.Numeric.GT(Int(124)), + AllTypes.Bigint.LT_EQ(Int(65)), + //AllTypes.Numeric.GT(AllTypes.Smallint), + AllTypes.Numeric.GT(Float(124)), AllTypes.Numeric.GT(Float(34.56)), - AllTypes.Smallint.GT_EQ(AllTypes.Numeric), + //AllTypes.Smallint.GT_EQ(AllTypes.Numeric), AllTypes.Integer.GT_EQ(Int(45)), - AllTypes.Bigint.GT_EQ(Float(65)), + AllTypes.Bigint.GT_EQ(Int(65)), ) fmt.Println(query.DebugSql())