Comparison operators refactoring.

This commit is contained in:
zer0sub 2019-05-29 14:03:38 +02:00
parent 64ba909381
commit 7b89caa7e0
28 changed files with 694 additions and 384 deletions

View file

@ -3,35 +3,30 @@ package sqlbuilder
type boolExpression interface { type boolExpression interface {
expression expression
Eq(expression boolExpression) boolExpression EQ(expression boolExpression) boolExpression
NotEq(expression boolExpression) boolExpression NOT_EQ(expression boolExpression) boolExpression
GtEq(rhs expression) boolExpression
LtEq(rhs expression) 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 AND(expression boolExpression) boolExpression
OR(expression boolExpression) boolExpression OR(expression boolExpression) boolExpression
IS_TRUE() boolExpression
IS_FALSE() boolExpression
} }
type boolInterfaceImpl struct { 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) return EQ(b.parent, expression)
} }
func (b *boolInterfaceImpl) NotEq(expression boolExpression) boolExpression { func (b *boolInterfaceImpl) NOT_EQ(expression boolExpression) boolExpression {
return NotEq(b.parent, expression) return NOT_EQ(b.parent, expression)
}
func (b *boolInterfaceImpl) GtEq(rhs expression) boolExpression {
return GtEq(b.parent, rhs)
}
func (b *boolInterfaceImpl) LtEq(rhs expression) boolExpression {
return LtEq(b.parent, rhs)
} }
func (b *boolInterfaceImpl) AND(expression boolExpression) boolExpression { func (b *boolInterfaceImpl) AND(expression boolExpression) boolExpression {
@ -41,27 +36,29 @@ func (b *boolInterfaceImpl) AND(expression boolExpression) boolExpression {
func (b *boolInterfaceImpl) OR(expression boolExpression) boolExpression { func (b *boolInterfaceImpl) OR(expression boolExpression) boolExpression {
return Or(b.parent, expression) return Or(b.parent, expression)
} }
func (b *boolInterfaceImpl) IS_TRUE() boolExpression { func (b *boolInterfaceImpl) IS_TRUE() boolExpression {
return IsTrue(b.parent) return IS_TRUE(b.parent)
}
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 nil return IS_FALSE(b.parent)
} }
//---------------------------------------------------// func (b *boolInterfaceImpl) IS_NOT_FALSE() boolExpression {
type boolLiteralExpression struct { return IS_NOT_FALSE(b.parent)
boolInterfaceImpl
literalExpression
} }
func newBoolLiteralExpression(value bool) boolExpression { func (b *boolInterfaceImpl) IS_UNKNOWN() boolExpression {
boolLiteralExpression := boolLiteralExpression{} return IS_UNKNOWN(b.parent)
}
boolLiteralExpression.literalExpression = *Literal(value) func (b *boolInterfaceImpl) IS_NOT_UNKNOWN() boolExpression {
boolLiteralExpression.boolInterfaceImpl.parent = &boolLiteralExpression return IS_NOT_UNKNOWN(b.parent)
return &boolLiteralExpression
} }
//---------------------------------------------------// //---------------------------------------------------//
@ -69,13 +66,13 @@ type binaryBoolExpression struct {
expressionInterfaceImpl expressionInterfaceImpl
boolInterfaceImpl boolInterfaceImpl
binaryExpression binaryOpExpression
} }
func newBinaryBoolExpression(lhs, rhs expression, operator string) boolExpression { func newBinaryBoolExpression(lhs, rhs expression, operator string) boolExpression {
boolExpression := binaryBoolExpression{} boolExpression := binaryBoolExpression{}
boolExpression.binaryExpression = newBinaryExpression(lhs, rhs, operator) boolExpression.binaryOpExpression = newBinaryExpression(lhs, rhs, operator)
boolExpression.expressionInterfaceImpl.parent = &boolExpression boolExpression.expressionInterfaceImpl.parent = &boolExpression
boolExpression.boolInterfaceImpl.parent = &boolExpression boolExpression.boolInterfaceImpl.parent = &boolExpression
@ -87,113 +84,33 @@ type prefixBoolExpression struct {
expressionInterfaceImpl expressionInterfaceImpl
boolInterfaceImpl boolInterfaceImpl
prefixExpression prefixOpExpression
} }
func newPrefixBoolExpression(expression expression, operator string) boolExpression { func newPrefixBoolExpression(expression expression, operator string) boolExpression {
boolExpression := prefixBoolExpression{} exp := prefixBoolExpression{}
boolExpression.prefixExpression = newPrefixExpression(expression, operator) exp.prefixOpExpression = newPrefixExpression(expression, operator)
boolExpression.expressionInterfaceImpl.parent = &boolExpression exp.expressionInterfaceImpl.parent = &exp
boolExpression.boolInterfaceImpl.parent = &boolExpression exp.boolInterfaceImpl.parent = &exp
return &boolExpression return &exp
} }
func EXISTS(subQuery selectStatement) boolExpression { //---------------------------------------------------//
return newPrefixBoolExpression(subQuery, "EXISTS") type postfixBoolOpExpression struct {
expressionInterfaceImpl
boolInterfaceImpl
postfixOpExpression
} }
// Returns a representation of "a=b" func newPostifxBoolExpression(expression expression, operator string) boolExpression {
func Eq(lhs, rhs expression) boolExpression { exp := postfixBoolOpExpression{}
return newBinaryBoolExpression(lhs, rhs, "=") exp.postfixOpExpression = newPostfixOpExpression(expression, operator)
}
// Returns a representation of "a=b", where b is a literal exp.expressionInterfaceImpl.parent = &exp
func EqL(lhs expression, val interface{}) boolExpression { exp.boolInterfaceImpl.parent = &exp
return Eq(lhs, Literal(val))
}
// Returns a representation of "a!=b" return &exp
func NotEq(lhs, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, "!=")
}
// Returns a representation of "a!=b", where b is a literal
func NeqL(lhs expression, val interface{}) boolExpression {
return NotEq(lhs, Literal(val))
}
// Returns a representation of "a<b"
func Lt(lhs expression, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, "<")
}
// Returns a representation of "a<b", where b is a literal
func LtL(lhs expression, val interface{}) boolExpression {
return Lt(lhs, Literal(val))
}
// Returns a representation of "a<=b"
func LtEq(lhs, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, "<=")
}
// Returns a representation of "a<=b", where b is a literal
func LteL(lhs expression, val interface{}) boolExpression {
return LtEq(lhs, Literal(val))
}
// Returns a representation of "a>b"
func Gt(lhs, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, ">")
}
// Returns a representation of "a>b", where b is a literal
func GtL(lhs expression, val interface{}) boolExpression {
return Gt(lhs, Literal(val))
}
// Returns a representation of "a>=b"
func GtEq(lhs, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, ">=")
}
// Returns a representation of "a>=b", where b is a literal
func GteL(lhs expression, val interface{}) boolExpression {
return GtEq(lhs, Literal(val))
}
// Returns a representation of "not expr"
func Not(expr boolExpression) boolExpression {
return newPrefixBoolExpression(expr, "NOT")
}
func IsTrue(expr boolExpression) boolExpression {
return newPrefixBoolExpression(expr, "IS TRUE")
}
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 {
return newBinaryBoolExpression(lhs, rhs, "OR")
}
func Like(lhs, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, "LIKE")
}
func LikeL(lhs expression, val string) boolExpression {
return Like(lhs, Literal(val))
}
func Regexp(lhs, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, "REGEXP")
}
func RegexpL(lhs expression, val string) boolExpression {
return Regexp(lhs, Literal(val))
} }

View file

@ -6,8 +6,42 @@ import (
"testing" "testing"
) )
func TestBoolExpressionEQ(t *testing.T) {
assert.Equal(t, getTestSerialize(t, table1ColBool.EQ(table2ColBool)), "table1.colBool = table2.colBool")
assert.Equal(t, getTestSerialize(t, table1ColBool.AND(table2ColBool).EQ(table2ColBool)), "table1.colBool AND table2.colBool = table2.colBool")
}
func TestBoolExpressionNOT_EQ(t *testing.T) {
assert.Equal(t, getTestSerialize(t, table1ColBool.NOT_EQ(table2ColBool)), "table1.colBool != table2.colBool")
assert.Equal(t, getTestSerialize(t, table1ColBool.AND(table2ColBool).NOT_EQ(table2ColBool)), "table1.colBool AND table2.colBool != table2.colBool")
}
func TestBoolExpressionIS_TRUE(t *testing.T) {
assert.Equal(t, getTestSerialize(t, table1ColBool.IS_TRUE()), "table1.colBool IS TRUE")
}
func TestBoolExpressionIS_NOT_TRUE(t *testing.T) {
assert.Equal(t, getTestSerialize(t, table1ColBool.IS_NOT_TRUE()), "table1.colBool IS NOT TRUE")
}
func TestBoolExpressionIS_FALSE(t *testing.T) {
assert.Equal(t, getTestSerialize(t, table1ColBool.IS_FALSE()), "table1.colBool IS FALSE")
}
func TestBoolExpressionIS_NOT_FALSE(t *testing.T) {
assert.Equal(t, getTestSerialize(t, table1ColBool.IS_NOT_FALSE()), "table1.colBool IS NOT FALSE")
}
func TestBoolExpressionIS_UNKNOWN(t *testing.T) {
assert.Equal(t, getTestSerialize(t, table1ColBool.IS_UNKNOWN()), "table1.colBool IS UNKNOWN")
}
func TestBoolExpressionIS_NOT_UNKNOWN(t *testing.T) {
assert.Equal(t, getTestSerialize(t, table1ColBool.IS_NOT_UNKNOWN()), "table1.colBool IS NOT UNKNOWN")
}
func TestBinaryExpression(t *testing.T) { func TestBinaryExpression(t *testing.T) {
boolExpression := Eq(Literal(2), Literal(3)) boolExpression := EQ(Literal(2), Literal(3))
out := queryData{} out := queryData{}
err := boolExpression.serialize(select_statement, &out) err := boolExpression.serialize(select_statement, &out)
@ -28,7 +62,7 @@ func TestBinaryExpression(t *testing.T) {
}) })
t.Run("and", func(t *testing.T) { t.Run("and", func(t *testing.T) {
exp := boolExpression.AND(Eq(Literal(4), Literal(5))) exp := boolExpression.AND(EQ(Literal(4), Literal(5)))
out := queryData{} out := queryData{}
err := exp.serialize(select_statement, &out) err := exp.serialize(select_statement, &out)
@ -38,7 +72,7 @@ func TestBinaryExpression(t *testing.T) {
}) })
t.Run("or", func(t *testing.T) { t.Run("or", func(t *testing.T) {
exp := boolExpression.OR(Eq(Literal(4), Literal(5))) exp := boolExpression.OR(EQ(Literal(4), Literal(5)))
out := queryData{} out := queryData{}
err := exp.serialize(select_statement, &out) err := exp.serialize(select_statement, &out)
@ -49,7 +83,7 @@ func TestBinaryExpression(t *testing.T) {
} }
func TestUnaryExpression(t *testing.T) { func TestUnaryExpression(t *testing.T) {
notExpression := Not(Eq(Literal(2), Literal(1))) notExpression := NOT(EQ(Literal(2), Literal(1)))
out := queryData{} out := queryData{}
err := notExpression.serialize(select_statement, &out) err := notExpression.serialize(select_statement, &out)
@ -68,7 +102,7 @@ func TestUnaryExpression(t *testing.T) {
}) })
t.Run("and", func(t *testing.T) { t.Run("and", func(t *testing.T) {
exp := notExpression.AND(Eq(Literal(4), Literal(5))) exp := notExpression.AND(EQ(Literal(4), Literal(5)))
out := queryData{} out := queryData{}
err := exp.serialize(select_statement, &out) err := exp.serialize(select_statement, &out)
@ -79,27 +113,27 @@ func TestUnaryExpression(t *testing.T) {
} }
func TestUnaryIsTrueExpression(t *testing.T) { func TestUnaryIsTrueExpression(t *testing.T) {
notExpression := IsTrue(Eq(Literal(2), Literal(1))) exp := IS_TRUE(EQ(Literal(2), Literal(1)))
out := queryData{}
err := notExpression.serialize(select_statement, &out)
assert.NilError(t, err)
assert.Equal(t, out.buff.String(), "IS TRUE $1 = $2")
t.Run("and", func(t *testing.T) {
exp := notExpression.AND(Eq(Literal(4), Literal(5)))
out := queryData{} out := queryData{}
err := exp.serialize(select_statement, &out) err := exp.serialize(select_statement, &out)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.buff.String(), `(IS TRUE $1 = $2 AND $3 = $4)`) assert.Equal(t, out.buff.String(), "$1 = $2 IS TRUE")
t.Run("and", func(t *testing.T) {
exp := exp.AND(EQ(Literal(4), Literal(5)))
out := queryData{}
err := exp.serialize(select_statement, &out)
assert.NilError(t, err)
assert.Equal(t, out.buff.String(), `($1 = $2 IS TRUE AND $3 = $4)`)
}) })
} }
func TestBoolLiteral(t *testing.T) { func TestBoolLiteral(t *testing.T) {
literal := newBoolLiteralExpression(true) literal := Bool(true)
out := queryData{} out := queryData{}
err := literal.serialize(select_statement, &out) err := literal.serialize(select_statement, &out)
@ -113,7 +147,7 @@ func TestExists(t *testing.T) {
query := EXISTS( query := EXISTS(
table2. table2.
SELECT(Literal(1)). SELECT(Literal(1)).
WHERE(table1Col1.Eq(table2Col3)), WHERE(table1Col1.EQ(table2Col3)),
) )
out := queryData{} out := queryData{}

View file

@ -12,7 +12,7 @@ func TestDeleteUnconditionally(t *testing.T) {
} }
func TestDeleteWithWhere(t *testing.T) { func TestDeleteWithWhere(t *testing.T) {
sql, _, err := table1.DELETE().WHERE(table1Col1.EqL(1)).Sql() sql, _, err := table1.DELETE().WHERE(table1Col1.EQ(Int(1))).Sql()
assert.NilError(t, err) assert.NilError(t, err)
fmt.Println(sql) fmt.Println(sql)

View file

@ -32,7 +32,7 @@ func Example() {
filename := t2.C("filename") filename := t2.C("filename")
in := []int32{1, 2, 3} in := []int32{1, 2, 3}
join := t2.LEFT_JOIN(t1, Eq(ns_id1, ns_id2)) join := t2.LEFT_JOIN(t1, EQ(ns_id1, ns_id2))
q := join.Select(ns_id2, sjid, prefix, filename).Where( q := join.Select(ns_id2, sjid, prefix, filename).Where(
And(EqL(ns_id2, 456), In(sjid, in))) And(EqL(ns_id2, 456), In(sjid, in)))
text, _ := q.String() text, _ := q.String()

View file

@ -11,12 +11,16 @@ type expression interface {
groupByClause groupByClause
orderByClause orderByClause
IS_NULL() boolExpression
IS_NOT_NULL() boolExpression
IS_DISTINCT_FROM(expression expression) boolExpression
IS_NOT_DISTINCT_FROM(expression expression) boolExpression
IN(subQuery selectStatement) boolExpression IN(subQuery selectStatement) boolExpression
NOT_IN(subQuery selectStatement) boolExpression NOT_IN(subQuery selectStatement) boolExpression
AS(alias string) projection AS(alias string) projection
IS_DISTINCT_FROM(expression expression) boolExpression
IS_NULL() boolExpression
ASC() orderByClause ASC() orderByClause
DESC() orderByClause DESC() orderByClause
} }
@ -25,6 +29,22 @@ type expressionInterfaceImpl struct {
parent expression parent expression
} }
func (e *expressionInterfaceImpl) IS_NULL() boolExpression {
return newPostifxBoolExpression(e.parent, "IS NULL")
}
func (e *expressionInterfaceImpl) IS_NOT_NULL() boolExpression {
return newPostifxBoolExpression(e.parent, "IS NOT NULL")
}
func (e *expressionInterfaceImpl) IS_DISTINCT_FROM(expression expression) boolExpression {
return newBinaryBoolExpression(e.parent, expression, "IS DISTINCT FROM")
}
func (e *expressionInterfaceImpl) IS_NOT_DISTINCT_FROM(expression expression) boolExpression {
return newBinaryBoolExpression(e.parent, expression, "IS NOT DISTINCT FROM")
}
func (e *expressionInterfaceImpl) IN(subQuery selectStatement) boolExpression { func (e *expressionInterfaceImpl) IN(subQuery selectStatement) boolExpression {
return newBinaryBoolExpression(e.parent, subQuery, "IN") return newBinaryBoolExpression(e.parent, subQuery, "IN")
} }
@ -37,14 +57,6 @@ func (e *expressionInterfaceImpl) AS(alias string) projection {
return NewAlias(e.parent, alias) return NewAlias(e.parent, alias)
} }
func (e *expressionInterfaceImpl) IS_DISTINCT_FROM(expression expression) boolExpression {
return newBinaryBoolExpression(e.parent, expression, "IS DISTINCT FROM")
}
func (e *expressionInterfaceImpl) IS_NULL() boolExpression {
return nil
}
func (e *expressionInterfaceImpl) ASC() orderByClause { func (e *expressionInterfaceImpl) ASC() orderByClause {
return &orderByClauseImpl{expression: e.parent, ascent: true} return &orderByClauseImpl{expression: e.parent, ascent: true}
} }
@ -66,13 +78,13 @@ func (e *expressionInterfaceImpl) serializeAsOrderBy(statement statementType, ou
} }
// Representation of binary operations (e.g. comparisons, arithmetic) // Representation of binary operations (e.g. comparisons, arithmetic)
type binaryExpression struct { type binaryOpExpression struct {
lhs, rhs expression lhs, rhs expression
operator string operator string
} }
func newBinaryExpression(lhs, rhs expression, operator string, parent ...expression) binaryExpression { func newBinaryExpression(lhs, rhs expression, operator string, parent ...expression) binaryOpExpression {
binaryExpression := binaryExpression{ binaryExpression := binaryOpExpression{
lhs: lhs, lhs: lhs,
rhs: rhs, rhs: rhs,
operator: operator, operator: operator,
@ -95,7 +107,7 @@ func isSimpleOperand(expression expression) bool {
return false return false
} }
func (c *binaryExpression) serialize(statement statementType, out *queryData) error { func (c *binaryOpExpression) serialize(statement statementType, out *queryData) error {
if c == nil { if c == nil {
return errors.New("Binary expression is nil.") return errors.New("Binary expression is nil.")
} }
@ -129,14 +141,14 @@ func (c *binaryExpression) serialize(statement statementType, out *queryData) er
return nil return nil
} }
// A not expression which negates a expression value // A prefix operator expression
type prefixExpression struct { type prefixOpExpression struct {
expression expression expression expression
operator string operator string
} }
func newPrefixExpression(expression expression, operator string) prefixExpression { func newPrefixExpression(expression expression, operator string) prefixOpExpression {
prefixExpression := prefixExpression{ prefixExpression := prefixOpExpression{
expression: expression, expression: expression,
operator: operator, operator: operator,
} }
@ -144,7 +156,7 @@ func newPrefixExpression(expression expression, operator string) prefixExpressio
return prefixExpression return prefixExpression
} }
func (p *prefixExpression) serialize(statement statementType, out *queryData) error { func (p *prefixOpExpression) serialize(statement statementType, out *queryData) error {
if p == nil { if p == nil {
return errors.New("Prefix expression is nil.") return errors.New("Prefix expression is nil.")
} }
@ -160,3 +172,35 @@ func (p *prefixExpression) serialize(statement statementType, out *queryData) er
return nil return nil
} }
// A postifx operator expression
type postfixOpExpression struct {
expression expression
operator string
}
func newPostfixOpExpression(expression expression, operator string) postfixOpExpression {
postfixOpExpression := postfixOpExpression{
expression: expression,
operator: operator,
}
return postfixOpExpression
}
func (p *postfixOpExpression) serialize(statement statementType, out *queryData) error {
if p == nil {
return errors.New("Postifx operator expression is nil.")
}
if p.expression == nil {
return errors.Newf("nil prefix expression.")
}
if err := p.expression.serialize(statement, out); err != nil {
return err
}
out.writeString(p.operator)
return nil
}

View file

@ -155,7 +155,7 @@ func (s *ExprSuite) TestDivExpr(c *gc.C) {
} }
func (s *ExprSuite) TestBinaryExprNilLHS(c *gc.C) { func (s *ExprSuite) TestBinaryExprNilLHS(c *gc.C) {
expr := Gt(nil, table1Col1) expr := GT(nil, table1Col1)
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
@ -164,7 +164,7 @@ func (s *ExprSuite) TestBinaryExprNilLHS(c *gc.C) {
} }
func (s *ExprSuite) TestNegateExpr(c *gc.C) { func (s *ExprSuite) TestNegateExpr(c *gc.C) {
expr := Not(EqL(table1Col1, 123)) expr := NOT(EqL(table1Col1, 123))
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
@ -176,7 +176,7 @@ func (s *ExprSuite) TestNegateExpr(c *gc.C) {
} }
func (s *ExprSuite) TestBinaryExprNilRHS(c *gc.C) { func (s *ExprSuite) TestBinaryExprNilRHS(c *gc.C) {
expr := Lt(table1Col1, nil) expr := LT(table1Col1, nil)
buf := &bytes.Buffer{} buf := &bytes.Buffer{}

View file

@ -76,7 +76,7 @@ func (e *expressionTableImpl) INNER_JOIN(table readableTable, onCondition boolEx
} }
//func (s *expressionTableImpl) InnerJoinUsing(table readableTable, col1 column, col2 column) readableTable { //func (s *expressionTableImpl) InnerJoinUsing(table readableTable, col1 column, col2 column) readableTable {
// return INNER_JOIN(s, table, col1.Eq(col2)) // return INNER_JOIN(s, table, col1.EQ(col2))
//} //}
// Creates a left join tableName expression using onCondition. // Creates a left join tableName expression using onCondition.

View file

@ -0,0 +1,26 @@
package sqlbuilder
import (
"gotest.tools/assert"
"testing"
)
func TestExpressionIS_NULL(t *testing.T) {
assert.Equal(t, getTestSerialize(t, table2Col3.IS_NULL()), "table2.col3 IS NULL")
assert.Equal(t, getTestSerialize(t, table2Col3.ADD(table2Col3).IS_NULL()), "table2.col3 + table2.col3 IS NULL")
}
func TestExpressionIS_NOT_NULL(t *testing.T) {
assert.Equal(t, getTestSerialize(t, table2Col3.IS_NOT_NULL()), "table2.col3 IS NOT NULL")
assert.Equal(t, getTestSerialize(t, table2Col3.ADD(table2Col3).IS_NOT_NULL()), "table2.col3 + table2.col3 IS NOT NULL")
}
func TestExpressionIS_DISTINCT_FROM(t *testing.T) {
assert.Equal(t, getTestSerialize(t, table2Col3.IS_DISTINCT_FROM(table2StrCol)), "table2.col3 IS DISTINCT FROM table2.col4")
assert.Equal(t, getTestSerialize(t, table2Col3.ADD(table2Col3).IS_DISTINCT_FROM(Int(23))), "(table2.col3 + table2.col3 IS DISTINCT FROM $1)")
}
func TestExpressionIS_NOT_DISTINCT_FROM(t *testing.T) {
assert.Equal(t, getTestSerialize(t, table2Col3.IS_NOT_DISTINCT_FROM(table2StrCol)), "table2.col3 IS NOT DISTINCT FROM table2.col4")
assert.Equal(t, getTestSerialize(t, table2Col3.ADD(table2Col3).IS_NOT_DISTINCT_FROM(Int(23))), "(table2.col3 + table2.col3 IS NOT DISTINCT FROM $1)")
}

View file

@ -7,8 +7,8 @@ import (
func TestCase1(t *testing.T) { func TestCase1(t *testing.T) {
query := CASE(). query := CASE().
WHEN(table3Col1.EqL(1)).THEN(table3Col1.Add(IntLiteral(1))). WHEN(table3Col1.EQ(Int(1))).THEN(table3Col1.ADD(Int(1))).
WHEN(table3Col1.EqL(2)).THEN(table3Col1.Add(IntLiteral(2))) WHEN(table3Col1.EQ(Int(2))).THEN(table3Col1.ADD(Int(2)))
queryData := &queryData{} queryData := &queryData{}
@ -20,9 +20,9 @@ func TestCase1(t *testing.T) {
func TestCase2(t *testing.T) { func TestCase2(t *testing.T) {
query := CASE(table3Col1). query := CASE(table3Col1).
WHEN(IntLiteral(1)).THEN(table3Col1.Add(IntLiteral(1))). WHEN(Int(1)).THEN(table3Col1.ADD(Int(1))).
WHEN(IntLiteral(2)).THEN(table3Col1.Add(IntLiteral(2))). WHEN(Int(2)).THEN(table3Col1.ADD(Int(2))).
ELSE(IntLiteral(0)) ELSE(Int(0))
queryData := &queryData{} queryData := &queryData{}

View file

@ -69,7 +69,7 @@ func (i *insertStatementImpl) VALUES(values ...interface{}) insertStatement {
func (i *insertStatementImpl) VALUES_MAPPING(data interface{}) insertStatement { func (i *insertStatementImpl) VALUES_MAPPING(data interface{}) insertStatement {
if data == nil { if data == nil {
i.addError("Add method data is nil.") i.addError("ADD method data is nil.")
return i return i
} }
@ -80,7 +80,7 @@ func (i *insertStatementImpl) VALUES_MAPPING(data interface{}) insertStatement {
} }
if value.Kind() != reflect.Struct { if value.Kind() != reflect.Struct {
i.addError("Add method data is not struct or pointer to struct.") i.addError("ADD method data is not struct or pointer to struct.")
return i return i
} }
@ -93,7 +93,7 @@ func (i *insertStatementImpl) VALUES_MAPPING(data interface{}) insertStatement {
structField := value.FieldByName(structFieldName) structField := value.FieldByName(structFieldName)
if !structField.IsValid() { if !structField.IsValid() {
i.addError("Add() : Data structure doesn't contain field : " + structFieldName + " for column " + columnName) i.addError("ADD() : Data structure doesn't contain field : " + structFieldName + " for column " + columnName)
return i return i
} }

View file

@ -56,11 +56,11 @@ INSERT INTO db.table1 (col1) VALUES
func TestInsertDate(t *testing.T) { func TestInsertDate(t *testing.T) {
date := time.Date(1999, 1, 2, 3, 4, 5, 0, time.UTC) date := time.Date(1999, 1, 2, 3, 4, 5, 0, time.UTC)
sql, _, err := table1.INSERT(table1Col4).VALUES(date).Sql() sql, _, err := table1.INSERT(table1ColTime).VALUES(date).Sql()
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, sql, ` assert.Equal(t, sql, `
INSERT INTO db.table1 (col4) VALUES INSERT INTO db.table1 (colTime) VALUES
($1); ($1);
`) `)
} }

View file

@ -3,9 +3,6 @@ package sqlbuilder
type integerExpression interface { type integerExpression interface {
numericExpression numericExpression
//AddInt(value int) integerExpression
//AddInt64(value int) integerExpression
BitAnd(expression integerExpression) integerExpression BitAnd(expression integerExpression) integerExpression
BitOr(expression integerExpression) integerExpression BitOr(expression integerExpression) integerExpression
BitXor(expression integerExpression) integerExpression BitXor(expression integerExpression) integerExpression
@ -16,14 +13,6 @@ type integerInterfaceImpl struct {
parent integerExpression parent integerExpression
} }
//func (i *integerInterfaceImpl) AddInt(expression integerExpression) integerExpression {
// return NewBinaryIntegerExpression(i.parent, expression, " & ")
//}
//
//func (i *integerInterfaceImpl) AddInt64(expression integerExpression) integerExpression {
// return NewBinaryIntegerExpression(i.parent, expression, " & ")
//}
func (i *integerInterfaceImpl) BitAnd(expression integerExpression) integerExpression { func (i *integerInterfaceImpl) BitAnd(expression integerExpression) integerExpression {
return NewBinaryIntegerExpression(i.parent, expression, " & ") return NewBinaryIntegerExpression(i.parent, expression, " & ")
} }
@ -46,7 +35,7 @@ type binaryIntegerExpression struct {
numericInterfaceImpl numericInterfaceImpl
integerInterfaceImpl integerInterfaceImpl
binaryExpression binaryOpExpression
} }
func NewBinaryIntegerExpression(lhs, rhs integerExpression, operator string) integerExpression { func NewBinaryIntegerExpression(lhs, rhs integerExpression, operator string) integerExpression {
@ -56,7 +45,7 @@ func NewBinaryIntegerExpression(lhs, rhs integerExpression, operator string) int
integerExpression.numericInterfaceImpl.parent = &integerExpression integerExpression.numericInterfaceImpl.parent = &integerExpression
integerExpression.integerInterfaceImpl.parent = &integerExpression integerExpression.integerInterfaceImpl.parent = &integerExpression
integerExpression.binaryExpression = newBinaryExpression(lhs, rhs, operator) integerExpression.binaryOpExpression = newBinaryExpression(lhs, rhs, operator)
return &integerExpression return &integerExpression
} }
@ -67,12 +56,12 @@ type prefixIntegerExpression struct {
numericInterfaceImpl numericInterfaceImpl
integerInterfaceImpl integerInterfaceImpl
prefixExpression prefixOpExpression
} }
func NewPrefixIntegerExpression(expression integerExpression, operator string) integerExpression { func NewPrefixIntegerExpression(expression integerExpression, operator string) integerExpression {
integerExpression := prefixIntegerExpression{} integerExpression := prefixIntegerExpression{}
integerExpression.prefixExpression = newPrefixExpression(expression, operator) integerExpression.prefixOpExpression = newPrefixExpression(expression, operator)
integerExpression.expressionInterfaceImpl.parent = &integerExpression integerExpression.expressionInterfaceImpl.parent = &integerExpression
integerExpression.numericInterfaceImpl.parent = &integerExpression integerExpression.numericInterfaceImpl.parent = &integerExpression

View file

@ -1,5 +1,7 @@
package sqlbuilder package sqlbuilder
import "time"
// Representation of an escaped literal // Representation of an escaped literal
type literalExpression struct { type literalExpression struct {
expressionInterfaceImpl expressionInterfaceImpl
@ -24,7 +26,7 @@ type numLiteralExpression struct {
numericInterfaceImpl numericInterfaceImpl
} }
func IntLiteral(value int) numericExpression { func Int(value int) numericExpression {
numLiteral := &numLiteralExpression{} numLiteral := &numLiteralExpression{}
numLiteral.literalExpression = *Literal(value) numLiteral.literalExpression = *Literal(value)
@ -34,3 +36,63 @@ func IntLiteral(value int) numericExpression {
return numLiteral return numLiteral
} }
//---------------------------------------------------//
type boolLiteralExpression struct {
boolInterfaceImpl
literalExpression
}
func Bool(value bool) boolExpression {
boolLiteralExpression := boolLiteralExpression{}
boolLiteralExpression.literalExpression = *Literal(value)
boolLiteralExpression.boolInterfaceImpl.parent = &boolLiteralExpression
return &boolLiteralExpression
}
//---------------------------------------------------//
type numericLiteral struct {
numericInterfaceImpl
literalExpression
}
func Float(value float64) numericExpression {
numericLiteral := numericLiteral{}
numericLiteral.literalExpression = *Literal(value)
numericLiteral.numericInterfaceImpl.parent = &numericLiteral
return &numericLiteral
}
//---------------------------------------------------//
type stringLiteral struct {
stringInterfaceImpl
literalExpression
}
func String(value string) stringExpression {
stringLiteral := stringLiteral{}
stringLiteral.literalExpression = *Literal(value)
stringLiteral.stringInterfaceImpl.parent = &stringLiteral
return &stringLiteral
}
//---------------------------------------------------//
type timeLiteral struct {
timeInterfaceImpl
literalExpression
}
func Time(value time.Time) timeExpression {
timeLiteral := timeLiteral{}
timeLiteral.literalExpression = *Literal(value)
timeLiteral.timeInterfaceImpl.parent = &timeLiteral
return &timeLiteral
}

View file

@ -5,112 +5,75 @@ import "errors"
type numericExpression interface { type numericExpression interface {
expression expression
Eq(expression numericExpression) boolExpression EQ(expression numericExpression) boolExpression
EqL(literal interface{}) boolExpression NOT_EQ(expression numericExpression) boolExpression
NotEq(expression numericExpression) boolExpression LT(rhs numericExpression) boolExpression
NotEqL(literal interface{}) boolExpression LT_EQ(rhs numericExpression) boolExpression
GT(rhs numericExpression) boolExpression
GT_EQ(rhs numericExpression) boolExpression
Gt(rhs numericExpression) boolExpression ADD(expression numericExpression) numericExpression
GtEq(rhs numericExpression) boolExpression SUB(expression numericExpression) numericExpression
GtEqL(literal interface{}) boolExpression MUL(expression numericExpression) numericExpression
DIV(expression numericExpression) numericExpression
Lt(rhs numericExpression) boolExpression
LtEq(rhs numericExpression) boolExpression
LtEqL(literal interface{}) boolExpression
Add(expression numericExpression) numericExpression
Sub(expression numericExpression) numericExpression
Mul(expression numericExpression) numericExpression
Div(expression numericExpression) numericExpression
} }
type numericInterfaceImpl struct { type numericInterfaceImpl struct {
parent numericExpression parent numericExpression
} }
func (n *numericInterfaceImpl) Eq(expression numericExpression) boolExpression { func (n *numericInterfaceImpl) EQ(expression numericExpression) boolExpression {
return Eq(n.parent, expression) return EQ(n.parent, expression)
} }
func (n *numericInterfaceImpl) EqL(literal interface{}) boolExpression { func (n *numericInterfaceImpl) NOT_EQ(expression numericExpression) boolExpression {
return Eq(n.parent, Literal(literal)) return NOT_EQ(n.parent, expression)
} }
func (n *numericInterfaceImpl) NotEq(expression numericExpression) boolExpression { func (n *numericInterfaceImpl) GT(expression numericExpression) boolExpression {
return NotEq(n.parent, expression) return GT(n.parent, expression)
} }
func (n *numericInterfaceImpl) NotEqL(literal interface{}) boolExpression { func (n *numericInterfaceImpl) GT_EQ(expression numericExpression) boolExpression {
return NotEq(n.parent, Literal(literal)) return GT_EQ(n.parent, expression)
} }
func (n *numericInterfaceImpl) Gt(expression numericExpression) boolExpression { func (n *numericInterfaceImpl) LT(expression numericExpression) boolExpression {
return Gt(n.parent, expression) return LT(n.parent, expression)
} }
func (n *numericInterfaceImpl) GtEq(expression numericExpression) boolExpression { func (n *numericInterfaceImpl) LT_EQ(expression numericExpression) boolExpression {
return GtEq(n.parent, expression) return LT_EQ(n.parent, expression)
} }
func (n *numericInterfaceImpl) GtEqL(literal interface{}) boolExpression { func (n *numericInterfaceImpl) ADD(expression numericExpression) numericExpression {
return GtEq(n.parent, Literal(literal))
}
func (n *numericInterfaceImpl) Lt(expression numericExpression) boolExpression {
return Lt(n.parent, expression)
}
func (n *numericInterfaceImpl) LtEq(expression numericExpression) boolExpression {
return LtEq(n.parent, expression)
}
func (n *numericInterfaceImpl) LtEqL(literal interface{}) boolExpression {
return LtEq(n.parent, Literal(literal))
}
func (n *numericInterfaceImpl) Add(expression numericExpression) numericExpression {
return newBinaryNumericExpression(n.parent, expression, "+") return newBinaryNumericExpression(n.parent, expression, "+")
} }
func (n *numericInterfaceImpl) Sub(expression numericExpression) numericExpression { func (n *numericInterfaceImpl) SUB(expression numericExpression) numericExpression {
return newBinaryNumericExpression(n.parent, expression, "-") return newBinaryNumericExpression(n.parent, expression, "-")
} }
func (n *numericInterfaceImpl) Mul(expression numericExpression) numericExpression { func (n *numericInterfaceImpl) MUL(expression numericExpression) numericExpression {
return newBinaryNumericExpression(n.parent, expression, "*") return newBinaryNumericExpression(n.parent, expression, "*")
} }
func (n *numericInterfaceImpl) Div(expression numericExpression) numericExpression { func (n *numericInterfaceImpl) DIV(expression numericExpression) numericExpression {
return newBinaryNumericExpression(n.parent, expression, "/") return newBinaryNumericExpression(n.parent, expression, "/")
} }
//---------------------------------------------------//
type numericLiteral struct {
numericInterfaceImpl
literalExpression
}
func NewNumericLiteral(value interface{}) numericExpression {
numericLiteral := numericLiteral{}
numericLiteral.literalExpression = *Literal(value)
numericLiteral.numericInterfaceImpl.parent = &numericLiteral
return &numericLiteral
}
//---------------------------------------------------// //---------------------------------------------------//
type binaryNumericExpression struct { type binaryNumericExpression struct {
expressionInterfaceImpl expressionInterfaceImpl
numericInterfaceImpl numericInterfaceImpl
binaryExpression binaryOpExpression
} }
func newBinaryNumericExpression(lhs, rhs expression, operator string) numericExpression { func newBinaryNumericExpression(lhs, rhs expression, operator string) numericExpression {
numericExpression := binaryNumericExpression{} numericExpression := binaryNumericExpression{}
numericExpression.binaryExpression = newBinaryExpression(lhs, rhs, operator) numericExpression.binaryOpExpression = newBinaryExpression(lhs, rhs, operator)
numericExpression.expressionInterfaceImpl.parent = &numericExpression numericExpression.expressionInterfaceImpl.parent = &numericExpression
numericExpression.numericInterfaceImpl.parent = &numericExpression numericExpression.numericInterfaceImpl.parent = &numericExpression

View file

@ -0,0 +1,38 @@
package sqlbuilder
import (
"gotest.tools/assert"
"testing"
)
func TestNumericEQColumn(t *testing.T) {
assert.Equal(t, getTestSerialize(t, table1Col1.EQ(table2Col3)), "table1.col1 = table2.col3")
}
func TestNumericEQInt(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 TestNumericNOT_EQ(t *testing.T) {
assert.Equal(t, getTestSerialize(t, table1Col1.NOT_EQ(table2Col3)), "table1.col1 != table2.col3")
}
func TestNumericGT(t *testing.T) {
assert.Equal(t, getTestSerialize(t, table1Col1.GT(table2Col3)), "table1.col1 > table2.col3")
}
func TestNumericGT_EQ(t *testing.T) {
assert.Equal(t, getTestSerialize(t, table1Col1.GT_EQ(table2Col3)), "table1.col1 >= table2.col3")
}
func TestNumericLT(t *testing.T) {
assert.Equal(t, getTestSerialize(t, table1Col1.LT(table2Col3)), "table1.col1 < table2.col3")
}
func TestNumericLT_EQ(t *testing.T) {
assert.Equal(t, getTestSerialize(t, table1Col1.LT_EQ(table2Col3)), "table1.col1 <= table2.col3")
}

93
sqlbuilder/operators.go Normal file
View file

@ -0,0 +1,93 @@
package sqlbuilder
//----------- Logical operators ---------------//
// Returns a representation of "not expr"
func NOT(expr boolExpression) boolExpression {
return newPrefixBoolExpression(expr, "NOT")
}
//----------- Comparison operators ---------------//
// Returns a representation of "a=b"
func EQ(lhs, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, "=")
}
// Returns a representation of "a!=b"
func NOT_EQ(lhs, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, "!=")
}
// Returns a representation of "a<b"
func LT(lhs expression, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, "<")
}
// Returns a representation of "a<=b"
func LT_EQ(lhs, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, "<=")
}
// Returns a representation of "a>b"
func GT(lhs, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, ">")
}
// Returns a representation of "a>=b"
func GT_EQ(lhs, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, ">=")
}
func IS_TRUE(expr boolExpression) boolExpression {
return newPostifxBoolExpression(expr, "IS TRUE")
}
func IS_NOT_TRUE(expr boolExpression) boolExpression {
return newPostifxBoolExpression(expr, "IS NOT TRUE")
}
func IS_FALSE(expr boolExpression) boolExpression {
return newPostifxBoolExpression(expr, "IS FALSE")
}
func IS_NOT_FALSE(expr boolExpression) boolExpression {
return newPostifxBoolExpression(expr, "IS NOT FALSE")
}
func IS_UNKNOWN(expr boolExpression) boolExpression {
return newPostifxBoolExpression(expr, "IS UNKNOWN")
}
func IS_NOT_UNKNOWN(expr boolExpression) boolExpression {
return newPostifxBoolExpression(expr, "IS NOT UNKNOWN")
}
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 {
return newBinaryBoolExpression(lhs, rhs, "OR")
}
func Like(lhs, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, "LIKE")
}
func LikeL(lhs expression, val string) boolExpression {
return Like(lhs, Literal(val))
}
func Regexp(lhs, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, "REGEXP")
}
func RegexpL(lhs expression, val string) boolExpression {
return Regexp(lhs, Literal(val))
}
func EXISTS(subQuery selectStatement) boolExpression {
return newPrefixBoolExpression(subQuery, "EXISTS")
}

View file

@ -61,7 +61,7 @@ func (s *StmtSuite) TestSelectWhere(c *gc.C) {
func (s *StmtSuite) TestSelectWhereDate(c *gc.C) { func (s *StmtSuite) TestSelectWhereDate(c *gc.C) {
date := time.Date(1999, 1, 2, 3, 4, 5, 0, time.UTC) date := time.Date(1999, 1, 2, 3, 4, 5, 0, time.UTC)
q := table1.Select(table1Col1).Where(GtL(table1Col4, date)) q := table1.Select(table1Col1).Where(GtL(table1ColTime, date))
sql, err := q.String() sql, err := q.String()
c.Assert(err, gc.IsNil) c.Assert(err, gc.IsNil)
@ -196,7 +196,7 @@ func (s *StmtSuite) TestSelectMultiOrderBy(c *gc.C) {
func (s *StmtSuite) TestSelectOnJoin(c *gc.C) { func (s *StmtSuite) TestSelectOnJoin(c *gc.C) {
join := table1.InnerJoinOn(table2, Eq(table1Col3, table2Col3)) join := table1.InnerJoinOn(table2, EQ(table1Col3, table2Col3))
sql, err := join.Select(table1Col1, table2Col4).String() sql, err := join.Select(table1Col1, table2Col4).String()
c.Assert(err, gc.IsNil) c.Assert(err, gc.IsNil)
@ -279,7 +279,7 @@ func (s *StmtSuite) TestInsertSingleValue(c *gc.C) {
func (s *StmtSuite) TestInsertDate(c *gc.C) { func (s *StmtSuite) TestInsertDate(c *gc.C) {
date := time.Date(1999, 1, 2, 3, 4, 5, 0, time.UTC) date := time.Date(1999, 1, 2, 3, 4, 5, 0, time.UTC)
sql, err := table1.INSERT(table1Col4).Add(Literal(date)).String() sql, err := table1.INSERT(table1ColTime).Add(Literal(date)).String()
c.Assert(err, gc.IsNil) c.Assert(err, gc.IsNil)
c.Assert( c.Assert(
@ -456,14 +456,14 @@ func (s *StmtSuite) TestUnionSelectWithMismatchedColumns(c *gc.C) {
table1Col1, table1Col1,
table1Col2, table1Col2,
table1Col3, table1Col3,
table1Col4).AndWhere(GtL(table1Col1, 123)).AndWhere(LtL(table1Col1, 321)), table1ColTime).AndWhere(GtL(table1Col1, 123)).AndWhere(LtL(table1Col1, 321)),
table1.Select(table1Col1).Where(And(GtL(table1Col1, 123), LtL(table1Col1, 321))), table1.Select(table1Col1).Where(And(GtL(table1Col1, 123), LtL(table1Col1, 321))),
table1.Select(table1Col1).Where(LtL(table1Col1, 23)).OrderBy(table1Col4).Limit(20), table1.Select(table1Col1).Where(LtL(table1Col1, 23)).OrderBy(table1ColTime).Limit(20),
) )
q := UNION(select_queries...) q := UNION(select_queries...)
q = q.Where(And(LtL(table1Col1, 1000), GtL(table1Col1, 15))) q = q.Where(And(LtL(table1Col1, 1000), GtL(table1Col1, 15)))
q = q.ORDER_BY(DESC(table1Col4), ASC(table1Col3)) q = q.ORDER_BY(DESC(table1ColTime), ASC(table1Col3))
q = q.LIMIT(5) q = q.LIMIT(5)
_, err := q.String() _, err := q.String()
@ -496,15 +496,15 @@ func (s *StmtSuite) TestComplicatedUnionSelectWithWhereStatement(c *gc.C) {
).Where(And(GtL(table1Col1, 456), LtL(table1Col1, 654))), ).Where(And(GtL(table1Col1, 456), LtL(table1Col1, 654))),
table1.Select( table1.Select(
table1Col1, table1Col1,
).Where(LtL(table1Col1, 23)).OrderBy(table1Col4).Limit(20), ).Where(LtL(table1Col1, 23)).OrderBy(table1ColTime).Limit(20),
) )
q := UNION(select_queries...) q := UNION(select_queries...)
q = q.Where(And(LtL(table1Col1, 1000), GtL(table1Col1, 15))) q = q.Where(And(LtL(table1Col1, 1000), GtL(table1Col1, 15)))
q = q.ORDER_BY(DESC(table1Col4), ASC(table1Col3)) q = q.ORDER_BY(DESC(table1ColTime), ASC(table1Col3))
q = q.LIMIT(5) q = q.LIMIT(5)
q = q.GroupBy(table1Col4) q = q.GroupBy(table1ColTime)
sql, err := q.String() sql, err := q.String()

View file

@ -3,28 +3,38 @@ package sqlbuilder
type stringExpression interface { type stringExpression interface {
expression expression
Eq(expression stringExpression) boolExpression EQ(rhs stringExpression) boolExpression
EqString(value string) boolExpression NOT_EQ(rhs stringExpression) boolExpression
NotEq(expression stringExpression) boolExpression LT(rhs stringExpression) boolExpression
NotEqString(value string) boolExpression LT_EQ(rhs stringExpression) boolExpression
GT(rhs stringExpression) boolExpression
GT_EQ(rhs stringExpression) boolExpression
} }
type stringInterfaceImpl struct { type stringInterfaceImpl struct {
parent stringExpression parent stringExpression
} }
func (b *stringInterfaceImpl) Eq(expression stringExpression) boolExpression { func (s *stringInterfaceImpl) EQ(rhs stringExpression) boolExpression {
return Eq(b.parent, expression) return EQ(s.parent, rhs)
} }
func (b *stringInterfaceImpl) EqString(value string) boolExpression { func (s *stringInterfaceImpl) NOT_EQ(rhs stringExpression) boolExpression {
return EqL(b.parent, value) return NOT_EQ(s.parent, rhs)
} }
func (b *stringInterfaceImpl) NotEq(expression stringExpression) boolExpression { func (s *stringInterfaceImpl) GT(rhs stringExpression) boolExpression {
return NotEq(b.parent, expression) return GT(s.parent, rhs)
} }
func (b *stringInterfaceImpl) NotEqString(value string) boolExpression { func (s *stringInterfaceImpl) GT_EQ(rhs stringExpression) boolExpression {
return NotEq(b.parent, Literal(value)) return GT_EQ(s.parent, rhs)
}
func (s *stringInterfaceImpl) LT(rhs stringExpression) boolExpression {
return LT(s.parent, rhs)
}
func (s *stringInterfaceImpl) LT_EQ(rhs stringExpression) boolExpression {
return LT_EQ(s.parent, rhs)
} }

View file

@ -0,0 +1,76 @@
package sqlbuilder
import (
"gotest.tools/assert"
"testing"
)
func TestStringEQColumn(t *testing.T) {
exp := table3StrCol.EQ(table2StrCol)
out := queryData{}
err := exp.serialize(select_statement, &out)
assert.NilError(t, err)
assert.Equal(t, out.buff.String(), "table3.col2 = table2.col4")
}
func TestStringEQString(t *testing.T) {
exp := table3StrCol.EQ(String("JOHN"))
out := queryData{}
err := exp.serialize(select_statement, &out)
assert.NilError(t, err)
assert.Equal(t, out.buff.String(), "table3.col2 = $1")
}
func TestStringNOT_EQ(t *testing.T) {
exp := table3StrCol.NOT_EQ(table2StrCol)
out := queryData{}
err := exp.serialize(select_statement, &out)
assert.NilError(t, err)
assert.Equal(t, out.buff.String(), "table3.col2 != table2.col4")
}
func TestStringGT(t *testing.T) {
exp := table3StrCol.GT(table2StrCol)
out := queryData{}
err := exp.serialize(select_statement, &out)
assert.NilError(t, err)
assert.Equal(t, out.buff.String(), "table3.col2 > table2.col4")
}
func TestStringGT_EQ(t *testing.T) {
exp := table3StrCol.GT_EQ(table2StrCol)
out := queryData{}
err := exp.serialize(select_statement, &out)
assert.NilError(t, err)
assert.Equal(t, out.buff.String(), "table3.col2 >= table2.col4")
}
func TestStringLT(t *testing.T) {
exp := table3StrCol.LT(table2StrCol)
out := queryData{}
err := exp.serialize(select_statement, &out)
assert.NilError(t, err)
assert.Equal(t, out.buff.String(), "table3.col2 < table2.col4")
}
func TestStringLT_EQ(t *testing.T) {
exp := table3StrCol.LT_EQ(table2StrCol)
out := queryData{}
err := exp.serialize(select_statement, &out)
assert.NilError(t, err)
assert.Equal(t, out.buff.String(), "table3.col2 <= table2.col4")
}

View file

@ -22,7 +22,7 @@ func (s *TableSuite) TestBasicColumns(c *gc.C) {
c.Assert(cols[0], gc.Equals, table1Col1) c.Assert(cols[0], gc.Equals, table1Col1)
c.Assert(cols[1], gc.Equals, table1Col2) c.Assert(cols[1], gc.Equals, table1Col2)
c.Assert(cols[2], gc.Equals, table1Col3) c.Assert(cols[2], gc.Equals, table1Col3)
c.Assert(cols[3], gc.Equals, table1Col4) c.Assert(cols[3], gc.Equals, table1ColTime)
} }
func (s *TableSuite) TestCValidLookup(c *gc.C) { func (s *TableSuite) TestCValidLookup(c *gc.C) {
@ -74,7 +74,7 @@ func (s *TableSuite) TestJoinNilOnCondition(c *gc.C) {
} }
func (s *TableSuite) TestInnerJoin(c *gc.C) { func (s *TableSuite) TestInnerJoin(c *gc.C) {
join := table1.InnerJoinOn(table2, Eq(table1Col3, table2Col3)) join := table1.InnerJoinOn(table2, EQ(table1Col3, table2Col3))
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
@ -89,7 +89,7 @@ func (s *TableSuite) TestInnerJoin(c *gc.C) {
} }
func (s *TableSuite) TestLeftJoin(c *gc.C) { func (s *TableSuite) TestLeftJoin(c *gc.C) {
join := table1.LEFT_JOIN(table2, Eq(table1Col3, table2Col3)) join := table1.LEFT_JOIN(table2, EQ(table1Col3, table2Col3))
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
@ -105,7 +105,7 @@ func (s *TableSuite) TestLeftJoin(c *gc.C) {
} }
func (s *TableSuite) TestRightJoin(c *gc.C) { func (s *TableSuite) TestRightJoin(c *gc.C) {
join := table1.RIGHT_JOIN(table2, Eq(table1Col3, table2Col3)) join := table1.RIGHT_JOIN(table2, EQ(table1Col3, table2Col3))
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
@ -121,21 +121,21 @@ func (s *TableSuite) TestRightJoin(c *gc.C) {
} }
//func (s *TableSuite) TestJoinColumns(c *gc.C) { //func (s *TableSuite) TestJoinColumns(c *gc.C) {
// join := table1.RIGHT_JOIN(table2, Eq(table1Col3, table2Col3)) // join := table1.RIGHT_JOIN(table2, EQ(table1Col3, table2Col3))
// //
// cols := join.Columns() // cols := join.Columns()
// c.Assert(len(cols), gc.Equals, 6) // c.Assert(len(cols), gc.Equals, 6)
// c.Assert(cols[0], gc.Equals, table1Col1) // c.Assert(cols[0], gc.Equals, table1Col1)
// c.Assert(cols[1], gc.Equals, table1Col2) // c.Assert(cols[1], gc.Equals, table1Col2)
// c.Assert(cols[2], gc.Equals, table1Col3) // c.Assert(cols[2], gc.Equals, table1Col3)
// c.Assert(cols[3], gc.Equals, table1Col4) // c.Assert(cols[3], gc.Equals, table1ColTime)
// c.Assert(cols[4], gc.Equals, table2Col3) // c.Assert(cols[4], gc.Equals, table2Col3)
// c.Assert(cols[5], gc.Equals, table2Col4) // c.Assert(cols[5], gc.Equals, table2Col4)
//} //}
func (s *TableSuite) TestNestedInnerJoin(c *gc.C) { func (s *TableSuite) TestNestedInnerJoin(c *gc.C) {
join1 := table1.InnerJoinOn(table2, Eq(table1Col3, table2Col3)) join1 := table1.InnerJoinOn(table2, EQ(table1Col3, table2Col3))
join2 := join1.InnerJoinOn(table3, Eq(table1Col1, table3Col1)) join2 := join1.InnerJoinOn(table3, EQ(table1Col1, table3Col1))
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
@ -152,8 +152,8 @@ func (s *TableSuite) TestNestedInnerJoin(c *gc.C) {
} }
func (s *TableSuite) TestNestedLeftJoin(c *gc.C) { func (s *TableSuite) TestNestedLeftJoin(c *gc.C) {
join1 := table1.InnerJoinOn(table2, Eq(table1Col3, table2Col3)) join1 := table1.InnerJoinOn(table2, EQ(table1Col3, table2Col3))
join2 := join1.LeftJoinOn(table3, Eq(table1Col1, table3Col1)) join2 := join1.LeftJoinOn(table3, EQ(table1Col1, table3Col1))
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
@ -170,8 +170,8 @@ func (s *TableSuite) TestNestedLeftJoin(c *gc.C) {
} }
func (s *TableSuite) TestNestedRightJoin(c *gc.C) { func (s *TableSuite) TestNestedRightJoin(c *gc.C) {
join1 := table1.InnerJoinOn(table2, Eq(table1Col3, table2Col3)) join1 := table1.InnerJoinOn(table2, EQ(table1Col3, table2Col3))
join2 := join1.RightJoinOn(table3, Eq(table1Col1, table3Col1)) join2 := join1.RightJoinOn(table3, EQ(table1Col1, table3Col1))
buf := &bytes.Buffer{} buf := &bytes.Buffer{}

View file

@ -1,29 +1,53 @@
package sqlbuilder package sqlbuilder
import (
"gotest.tools/assert"
"testing"
)
var table1Col1 = NewIntegerColumn("col1", Nullable) var table1Col1 = NewIntegerColumn("col1", Nullable)
var table1Col2 = NewIntegerColumn("col2", Nullable) var table1Col2 = NewIntegerColumn("col2", Nullable)
var table1Col3 = NewIntegerColumn("col3", Nullable) var table1Col3 = NewIntegerColumn("col3", Nullable)
var table1Col4 = NewTimeColumn("col4", Nullable) var table1ColTime = NewTimeColumn("colTime", Nullable)
var table1ColBool = NewBoolColumn("colBool", Nullable)
var table1 = NewTable( var table1 = NewTable(
"db", "db",
"table1", "table1",
table1Col1, table1Col1,
table1Col2, table1Col2,
table1Col3, table1Col3,
table1Col4) table1ColTime,
table1ColBool)
var table2Col3 = NewIntegerColumn("col3", Nullable) var table2Col3 = NewIntegerColumn("col3", Nullable)
var table2Col4 = NewIntegerColumn("col4", Nullable) var table2Col4 = NewIntegerColumn("col4", Nullable)
var table2StrCol = NewStringColumn("col4", Nullable)
var table2ColBool = NewBoolColumn("colBool", Nullable)
var table2ColTime = NewTimeColumn("colTime", Nullable)
var table2 = NewTable( var table2 = NewTable(
"db", "db",
"table2", "table2",
table2Col3, table2Col3,
table2Col4) table2Col4,
table2StrCol,
table2ColBool,
table2ColTime)
var table3Col1 = NewIntegerColumn("col1", Nullable) var table3Col1 = NewIntegerColumn("col1", Nullable)
var table3Col2 = NewIntegerColumn("col2", Nullable) var table3StrCol = NewStringColumn("col2", Nullable)
var table3 = NewTable( var table3 = NewTable(
"db", "db",
"table3", "table3",
table3Col1, table3Col1,
table3Col2) table3StrCol)
func getTestSerialize(t *testing.T, exp expression) string {
out := queryData{}
err := exp.serialize(select_statement, &out)
assert.NilError(t, err)
return out.buff.String()
}

View file

@ -3,50 +3,40 @@ package sqlbuilder
type timeExpression interface { type timeExpression interface {
expression expression
Eq(expression timeExpression) boolExpression EQ(rhs timeExpression) boolExpression
EqL(literal string) boolExpression NOT_EQ(rhs timeExpression) boolExpression
NotEq(expression timeExpression) boolExpression LT(rhs timeExpression) boolExpression
NotEqL(literal string) boolExpression LT_EQ(rhs timeExpression) boolExpression
GtEq(rhs timeExpression) boolExpression GT(rhs timeExpression) boolExpression
GtEqL(literal string) boolExpression GT_EQ(rhs timeExpression) boolExpression
LtEq(rhs timeExpression) boolExpression
LtEqL(literal string) boolExpression
} }
type timeInterfaceImpl struct { type timeInterfaceImpl struct {
parent timeExpression parent timeExpression
} }
func (t *timeInterfaceImpl) Eq(expression timeExpression) boolExpression { func (t *timeInterfaceImpl) EQ(rhs timeExpression) boolExpression {
return Eq(t.parent, expression) return EQ(t.parent, rhs)
} }
func (t *timeInterfaceImpl) EqL(literal string) boolExpression { func (t *timeInterfaceImpl) NOT_EQ(rhs timeExpression) boolExpression {
return Eq(t.parent, Literal(literal)) return NOT_EQ(t.parent, rhs)
} }
func (t *timeInterfaceImpl) NotEq(expression timeExpression) boolExpression { func (t *timeInterfaceImpl) LT(rhs timeExpression) boolExpression {
return NotEq(t.parent, expression) return LT(t.parent, rhs)
} }
func (t *timeInterfaceImpl) NotEqL(literal string) boolExpression { func (t *timeInterfaceImpl) LT_EQ(rhs timeExpression) boolExpression {
return NotEq(t.parent, Literal(literal)) return LT_EQ(t.parent, rhs)
} }
func (t *timeInterfaceImpl) GtEq(expression timeExpression) boolExpression { func (t *timeInterfaceImpl) GT(rhs timeExpression) boolExpression {
return GtEq(t.parent, expression) return GT(t.parent, rhs)
} }
func (t *timeInterfaceImpl) GtEqL(literal string) boolExpression { func (t *timeInterfaceImpl) GT_EQ(rhs timeExpression) boolExpression {
return GtEq(t.parent, Literal(literal)) return GT_EQ(t.parent, rhs)
}
func (t *timeInterfaceImpl) LtEq(expression timeExpression) boolExpression {
return LtEq(t.parent, expression)
}
func (t *timeInterfaceImpl) LtEqL(literal string) boolExpression {
return LtEq(t.parent, Literal(literal))
} }
//---------------------------------------------------// //---------------------------------------------------//
@ -54,12 +44,12 @@ type prefixTimeExpression struct {
expressionInterfaceImpl expressionInterfaceImpl
timeInterfaceImpl timeInterfaceImpl
prefixExpression prefixOpExpression
} }
func newPrefixTimeExpression(expression expression, operator string) timeExpression { func newPrefixTimeExpression(expression expression, operator string) timeExpression {
timeExpr := prefixTimeExpression{} timeExpr := prefixTimeExpression{}
timeExpr.prefixExpression = newPrefixExpression(expression, operator) timeExpr.prefixOpExpression = newPrefixExpression(expression, operator)
timeExpr.expressionInterfaceImpl.parent = &timeExpr timeExpr.expressionInterfaceImpl.parent = &timeExpr
timeExpr.timeInterfaceImpl.parent = &timeExpr timeExpr.timeInterfaceImpl.parent = &timeExpr

View file

@ -0,0 +1,37 @@
package sqlbuilder
import (
"gotest.tools/assert"
"testing"
"time"
)
func TestTimeExpressionEQ(t *testing.T) {
assert.Equal(t, getTestSerialize(t, table1ColTime.EQ(table2ColTime)), "table1.colTime = table2.colTime")
assert.Equal(t, getTestSerialize(t, table1ColTime.EQ(Time(time.Now()))), "table1.colTime = $1")
}
func TestTimeExpressionNOT_EQ(t *testing.T) {
assert.Equal(t, getTestSerialize(t, table1ColTime.NOT_EQ(table2ColTime)), "table1.colTime != table2.colTime")
assert.Equal(t, getTestSerialize(t, table1ColTime.NOT_EQ(Time(time.Now()))), "table1.colTime != $1")
}
func TestTimeExpressionLT(t *testing.T) {
assert.Equal(t, getTestSerialize(t, table1ColTime.LT(table2ColTime)), "table1.colTime < table2.colTime")
assert.Equal(t, getTestSerialize(t, table1ColTime.LT(Time(time.Now()))), "table1.colTime < $1")
}
func TestTimeExpressionLT_EQ(t *testing.T) {
assert.Equal(t, getTestSerialize(t, table1ColTime.LT_EQ(table2ColTime)), "table1.colTime <= table2.colTime")
assert.Equal(t, getTestSerialize(t, table1ColTime.LT_EQ(Time(time.Now()))), "table1.colTime <= $1")
}
func TestTimeExpressionGT(t *testing.T) {
assert.Equal(t, getTestSerialize(t, table1ColTime.GT(table2ColTime)), "table1.colTime > table2.colTime")
assert.Equal(t, getTestSerialize(t, table1ColTime.GT(Time(time.Now()))), "table1.colTime > $1")
}
func TestTimeExpressionGT_EQ(t *testing.T) {
assert.Equal(t, getTestSerialize(t, table1ColTime.GT_EQ(table2ColTime)), "table1.colTime >= table2.colTime")
assert.Equal(t, getTestSerialize(t, table1ColTime.GT_EQ(Time(time.Now()))), "table1.colTime >= $1")
}

View file

@ -13,7 +13,7 @@ import (
func TestUpdate(t *testing.T) { func TestUpdate(t *testing.T) {
stmt := table1.UPDATE(table1Col1, table1Col2). stmt := table1.UPDATE(table1Col1, table1Col2).
SET(table1.SELECT(table1Col2, table2Col3)). SET(table1.SELECT(table1Col2, table2Col3)).
WHERE(table1Col1.EqL(2)). WHERE(table1Col1.EQ(Int(2))).
RETURNING(table1Col1) RETURNING(table1Col1)
stmtStr, _, err := stmt.Sql() stmtStr, _, err := stmt.Sql()

View file

@ -3,6 +3,7 @@ package tests
import ( import (
"fmt" "fmt"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
. "github.com/sub0zero/go-sqlbuilder/sqlbuilder"
"github.com/sub0zero/go-sqlbuilder/tests/.test_files/dvd_rental/test_sample/model" "github.com/sub0zero/go-sqlbuilder/tests/.test_files/dvd_rental/test_sample/model"
"github.com/sub0zero/go-sqlbuilder/tests/.test_files/dvd_rental/test_sample/table" "github.com/sub0zero/go-sqlbuilder/tests/.test_files/dvd_rental/test_sample/table"
"gotest.tools/assert" "gotest.tools/assert"
@ -12,7 +13,7 @@ import (
func TestUUIDType(t *testing.T) { func TestUUIDType(t *testing.T) {
query := table.AllTypes. query := table.AllTypes.
SELECT(table.AllTypes.AllColumns). SELECT(table.AllTypes.AllColumns).
WHERE(table.AllTypes.UUID.EqString("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11")) WHERE(table.AllTypes.UUID.EQ(String("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11")))
queryStr, args, err := query.Sql() queryStr, args, err := query.Sql()

View file

@ -191,10 +191,10 @@ func TestScanToStruct(t *testing.T) {
func TestScanToNestedStruct(t *testing.T) { func TestScanToNestedStruct(t *testing.T) {
query := Inventory. query := Inventory.
INNER_JOIN(Film, Inventory.FilmID.Eq(Film.FilmID)). INNER_JOIN(Film, Inventory.FilmID.EQ(Film.FilmID)).
INNER_JOIN(Store, Inventory.StoreID.Eq(Store.StoreID)). INNER_JOIN(Store, Inventory.StoreID.EQ(Store.StoreID)).
SELECT(Inventory.AllColumns, Film.AllColumns, Store.AllColumns). SELECT(Inventory.AllColumns, Film.AllColumns, Store.AllColumns).
WHERE(Inventory.InventoryID.EqL(1)) WHERE(Inventory.InventoryID.EQ(Int(1)))
t.Run("embedded structs", func(t *testing.T) { t.Run("embedded structs", func(t *testing.T) {
dest := struct { dest := struct {
@ -267,10 +267,10 @@ func TestScanToNestedStruct(t *testing.T) {
t.Run("embedded pointer to selected column", func(t *testing.T) { t.Run("embedded pointer to selected column", func(t *testing.T) {
query := Inventory. query := Inventory.
INNER_JOIN(Film, Inventory.FilmID.Eq(Film.FilmID)). INNER_JOIN(Film, Inventory.FilmID.EQ(Film.FilmID)).
INNER_JOIN(Store, Inventory.StoreID.Eq(Store.StoreID)). INNER_JOIN(Store, Inventory.StoreID.EQ(Store.StoreID)).
SELECT(Inventory.AllColumns, Film.AllColumns, Store.AllColumns, Literal("").AS("actor.first_name")). SELECT(Inventory.AllColumns, Film.AllColumns, Store.AllColumns, Literal("").AS("actor.first_name")).
WHERE(Inventory.InventoryID.EqL(1)) WHERE(Inventory.InventoryID.EQ(Int(1)))
dest := struct { dest := struct {
model.Inventory model.Inventory
@ -358,11 +358,11 @@ func TestScanToNestedStruct(t *testing.T) {
t.Run("embedded structs", func(t *testing.T) { t.Run("embedded structs", func(t *testing.T) {
query := Inventory. query := Inventory.
INNER_JOIN(Film, Inventory.FilmID.Eq(Film.FilmID)). INNER_JOIN(Film, Inventory.FilmID.EQ(Film.FilmID)).
INNER_JOIN(Store, Inventory.StoreID.Eq(Store.StoreID)). INNER_JOIN(Store, Inventory.StoreID.EQ(Store.StoreID)).
INNER_JOIN(Language, Film.LanguageID.Eq(Language.LanguageID)). INNER_JOIN(Language, Film.LanguageID.EQ(Language.LanguageID)).
SELECT(Inventory.AllColumns, Film.AllColumns, Store.AllColumns, Language.AllColumns). SELECT(Inventory.AllColumns, Film.AllColumns, Store.AllColumns, Language.AllColumns).
WHERE(Inventory.InventoryID.EqL(1)) WHERE(Inventory.InventoryID.EQ(Int(1)))
dest := struct { dest := struct {
model.Inventory model.Inventory
@ -434,8 +434,8 @@ func TestScanToSlice(t *testing.T) {
t.Run("slice of complex structs", func(t *testing.T) { t.Run("slice of complex structs", func(t *testing.T) {
query := Inventory. query := Inventory.
INNER_JOIN(Film, Inventory.FilmID.Eq(Film.FilmID)). INNER_JOIN(Film, Inventory.FilmID.EQ(Film.FilmID)).
INNER_JOIN(Store, Inventory.StoreID.Eq(Store.StoreID)). INNER_JOIN(Store, Inventory.StoreID.EQ(Store.StoreID)).
SELECT(Inventory.AllColumns, Film.AllColumns, Store.AllColumns). SELECT(Inventory.AllColumns, Film.AllColumns, Store.AllColumns).
ORDER_BY(Inventory.InventoryID). ORDER_BY(Inventory.InventoryID).
LIMIT(10) LIMIT(10)
@ -589,9 +589,9 @@ func TestScanToSlice(t *testing.T) {
t.Run("slice of complex structs 2", func(t *testing.T) { t.Run("slice of complex structs 2", func(t *testing.T) {
query := Country. query := Country.
INNER_JOIN(City, City.CountryID.Eq(Country.CountryID)). INNER_JOIN(City, City.CountryID.EQ(Country.CountryID)).
INNER_JOIN(Address, Address.CityID.Eq(City.CityID)). INNER_JOIN(Address, Address.CityID.EQ(City.CityID)).
INNER_JOIN(Customer, Customer.AddressID.Eq(Address.AddressID)). INNER_JOIN(Customer, Customer.AddressID.EQ(Address.AddressID)).
SELECT(Country.AllColumns, City.AllColumns, Address.AllColumns, Customer.AllColumns). SELECT(Country.AllColumns, City.AllColumns, Address.AllColumns, Customer.AllColumns).
ORDER_BY(Country.CountryID.ASC(), City.CityID.ASC(), Address.AddressID.ASC(), Customer.CustomerID.ASC()). ORDER_BY(Country.CountryID.ASC(), City.CityID.ASC(), Address.AddressID.ASC(), Customer.CustomerID.ASC()).
LIMIT(1000) LIMIT(1000)

View file

@ -24,7 +24,7 @@ WHERE actor.actor_id = 1;
query := Actor. query := Actor.
SELECT(Actor.AllColumns). SELECT(Actor.AllColumns).
WHERE(Actor.ActorID.EqL(1)) WHERE(Actor.ActorID.EQ(Int(1)))
assertQuery(t, query, expectedSql, 1) assertQuery(t, query, expectedSql, 1)
@ -68,7 +68,7 @@ LIMIT 30;
` `
query := SELECT(Payment.AllColumns, Customer.AllColumns). query := SELECT(Payment.AllColumns, Customer.AllColumns).
FROM(Payment.INNER_JOIN(Customer, Payment.CustomerID.Eq(Customer.CustomerID))). FROM(Payment.INNER_JOIN(Customer, Payment.CustomerID.EQ(Customer.CustomerID))).
ORDER_BY(Payment.PaymentID.ASC()). ORDER_BY(Payment.PaymentID.ASC()).
LIMIT(30) LIMIT(30)
@ -206,11 +206,11 @@ LIMIT 50;
` `
for i := 0; i < 1; i++ { for i := 0; i < 1; i++ {
query := FilmActor. query := FilmActor.
INNER_JOIN(Actor, FilmActor.ActorID.Eq(Actor.ActorID)). INNER_JOIN(Actor, FilmActor.ActorID.EQ(Actor.ActorID)).
INNER_JOIN(Film, FilmActor.FilmID.Eq(Film.FilmID)). INNER_JOIN(Film, FilmActor.FilmID.EQ(Film.FilmID)).
INNER_JOIN(Language, Film.LanguageID.Eq(Language.LanguageID)). INNER_JOIN(Language, Film.LanguageID.EQ(Language.LanguageID)).
INNER_JOIN(Inventory, Inventory.FilmID.Eq(Film.FilmID)). INNER_JOIN(Inventory, Inventory.FilmID.EQ(Film.FilmID)).
INNER_JOIN(Rental, Rental.InventoryID.Eq(Inventory.InventoryID)). INNER_JOIN(Rental, Rental.InventoryID.EQ(Inventory.InventoryID)).
SELECT( SELECT(
FilmActor.AllColumns, FilmActor.AllColumns,
Film.AllColumns, Film.AllColumns,
@ -285,9 +285,9 @@ LIMIT 15;
limit := 15 limit := 15
query := Film. query := Film.
INNER_JOIN(Language, Film.LanguageID.Eq(Language.LanguageID)). INNER_JOIN(Language, Film.LanguageID.EQ(Language.LanguageID)).
SELECT(Language.AllColumns, Film.AllColumns). SELECT(Language.AllColumns, Film.AllColumns).
WHERE(Film.Rating.EqString(model.MpaaRating_NC17.String())). WHERE(Film.Rating.EQ(String(model.MpaaRating_NC17.String()))).
LIMIT(15) LIMIT(15)
assertQuery(t, query, expectedSql, model.MpaaRating_NC17.String(), int64(15)) assertQuery(t, query, expectedSql, model.MpaaRating_NC17.String(), int64(15))
@ -318,7 +318,7 @@ func TestJoinQuerySliceWithPtrs(t *testing.T) {
limit := int64(3) limit := int64(3)
query := Film.INNER_JOIN(Language, Film.LanguageID.Eq(Language.LanguageID)). query := Film.INNER_JOIN(Language, Film.LanguageID.EQ(Language.LanguageID)).
SELECT(Language.AllColumns, Film.AllColumns). SELECT(Language.AllColumns, Film.AllColumns).
LIMIT(limit) LIMIT(limit)
@ -417,7 +417,7 @@ FROM dvds.customer
ORDER BY customer.customer_id ASC; ORDER BY customer.customer_id ASC;
` `
query := Customer. query := Customer.
FULL_JOIN(Address, Customer.AddressID.Eq(Address.AddressID)). FULL_JOIN(Address, Customer.AddressID.EQ(Address.AddressID)).
SELECT(Customer.AllColumns, Address.AllColumns). SELECT(Customer.AllColumns, Address.AllColumns).
ORDER_BY(Customer.CustomerID.ASC()) ORDER_BY(Customer.CustomerID.ASC())
@ -506,7 +506,7 @@ ORDER BY employee.employee_id;
manager := Employee.AS("manager") manager := Employee.AS("manager")
query := Employee. query := Employee.
LEFT_JOIN(manager, manager.EmployeeID.Eq(Employee.ManagerID)). LEFT_JOIN(manager, manager.EmployeeID.EQ(Employee.ManagerID)).
SELECT(Employee.AllColumns, manager.AllColumns). SELECT(Employee.AllColumns, manager.AllColumns).
ORDER_BY(Employee.EmployeeID) ORDER_BY(Employee.EmployeeID)
@ -576,7 +576,7 @@ ORDER BY f1.film_id ASC;
f2 := Film.AS("f2") f2 := Film.AS("f2")
query := f1. query := f1.
INNER_JOIN(f2, f1.FilmID.Lt(f2.FilmID).AND(f1.Length.Eq(f2.Length))). INNER_JOIN(f2, f1.FilmID.LT(f2.FilmID).AND(f1.Length.EQ(f2.Length))).
SELECT(f1.AllColumns, f2.AllColumns). SELECT(f1.AllColumns, f2.AllColumns).
ORDER_BY(f1.FilmID.ASC()) ORDER_BY(f1.FilmID.ASC())
@ -612,8 +612,10 @@ LIMIT 1000;
f1 := Film.AS("f1") f1 := Film.AS("f1")
f2 := Film.AS("f2") f2 := Film.AS("f2")
f1.FilmID.EQ(Float(11))
query := f1. query := f1.
INNER_JOIN(f2, f1.FilmID.NotEq(f2.FilmID).AND(f1.Length.Eq(f2.Length))). INNER_JOIN(f2, f1.FilmID.NOT_EQ(f2.FilmID).AND(f1.Length.EQ(f2.Length))).
SELECT(f1.Title.AS("thesame_length_films.title1"), SELECT(f1.Title.AS("thesame_length_films.title1"),
f2.Title.AS("thesame_length_films.title2"), f2.Title.AS("thesame_length_films.title2"),
f1.Length.AS("thesame_length_films.length")). f1.Length.AS("thesame_length_films.length")).
@ -679,8 +681,8 @@ LIMIT 1000;
// manager := Staff.AS("manager") // manager := Staff.AS("manager")
// //
// query := Staff. // query := Staff.
// INNER_JOIN(Address, Staff.AddressID.Eq(Address.AddressID)). // INNER_JOIN(Address, Staff.AddressID.EQ(Address.AddressID)).
// INNER_JOIN(manager, Staff.StaffID.Eq(manager.StaffID)). // INNER_JOIN(manager, Staff.StaffID.EQ(manager.StaffID)).
// SELECT(Staff.StaffID, Staff.FirstName, Staff.LastName, Address.AllColumns, manager.StaffID, manager.FirstName). // SELECT(Staff.StaffID, Staff.FirstName, Staff.LastName, Address.AllColumns, manager.StaffID, manager.FirstName).
// DISTINCT() // DISTINCT()
// //
@ -714,7 +716,7 @@ func TestSubQuery(t *testing.T) {
//avrgCustomer := NumExp(Customer.SELECT(Customer.LastName).LIMIT(1)) //avrgCustomer := NumExp(Customer.SELECT(Customer.LastName).LIMIT(1))
// //
//Customer. //Customer.
// INNER_JOIN(selectStmtTable, Customer.LastName.Eq(selectStmtTable.RefStringColumn(Actor.FirstName))). // INNER_JOIN(selectStmtTable, Customer.LastName.EQ(selectStmtTable.RefStringColumn(Actor.FirstName))).
// SELECT(Customer.AllColumns, selectStmtTable.RefIntColumnName("first_name")). // SELECT(Customer.AllColumns, selectStmtTable.RefIntColumnName("first_name")).
// WHERE(Actor.LastName.Neq(avrgCustomer)) // WHERE(Actor.LastName.Neq(avrgCustomer))
@ -740,11 +742,11 @@ FROM dvds.actor
` `
rFilmsOnly := Film.SELECT(Film.FilmID, Film.Title, Film.Rating). rFilmsOnly := Film.SELECT(Film.FilmID, Film.Title, Film.Rating).
WHERE(Film.Rating.EqString("R")). WHERE(Film.Rating.EQ(String("R"))).
AsTable("films") AsTable("films")
query := Actor.INNER_JOIN(FilmActor, Actor.ActorID.Eq(FilmActor.FilmID)). query := Actor.INNER_JOIN(FilmActor, Actor.ActorID.EQ(FilmActor.FilmID)).
INNER_JOIN(rFilmsOnly, FilmActor.FilmID.Eq(rFilmsOnly.RefIntColumn(Film.FilmID))). INNER_JOIN(rFilmsOnly, FilmActor.FilmID.EQ(rFilmsOnly.RefIntColumn(Film.FilmID))).
SELECT( SELECT(
Actor.AllColumns, Actor.AllColumns,
FilmActor.AllColumns, FilmActor.AllColumns,
@ -809,7 +811,7 @@ ORDER BY film.film_id ASC;
query := Film. query := Film.
SELECT(Film.AllColumns). SELECT(Film.AllColumns).
WHERE(Film.RentalRate.Eq(maxFilmRentalRate)). WHERE(Film.RentalRate.EQ(maxFilmRentalRate)).
ORDER_BY(Film.FilmID.ASC()) ORDER_BY(Film.FilmID.ASC())
fmt.Println(query.Sql()) fmt.Println(query.Sql())
@ -856,8 +858,12 @@ ORDER BY SUM(payment.amount) ASC;
SUM(Payment.Amount).AS("customer_payment_sum.amount_sum"), SUM(Payment.Amount).AS("customer_payment_sum.amount_sum"),
). ).
GROUP_BY(Payment.CustomerID). GROUP_BY(Payment.CustomerID).
ORDER_BY(SUM(Payment.Amount).ASC()). ORDER_BY(
HAVING(SUM(Payment.Amount).Gt(NewNumericLiteral(100))) SUM(Payment.Amount).ASC(),
).
HAVING(
SUM(Payment.Amount).GT(Int(100)),
)
assertQuery(t, customersPaymentQuery, expectedSql, 100) assertQuery(t, customersPaymentQuery, expectedSql, 100)
@ -913,7 +919,7 @@ ORDER BY customer_payment_sum.amount_sum ASC;
amountSumColumn := customersPaymentTable.RefIntColumnName("amount_sum") amountSumColumn := customersPaymentTable.RefIntColumnName("amount_sum")
query := Customer. query := Customer.
INNER_JOIN(customersPaymentTable, Customer.CustomerID.Eq(customersPaymentTable.RefIntColumn(Payment.CustomerID))). INNER_JOIN(customersPaymentTable, Customer.CustomerID.EQ(customersPaymentTable.RefIntColumn(Payment.CustomerID))).
SELECT(Customer.AllColumns, amountSumColumn.AS("customer_with_amounts.amount_sum")). SELECT(Customer.AllColumns, amountSumColumn.AS("customer_with_amounts.amount_sum")).
ORDER_BY(amountSumColumn.ASC()) ORDER_BY(amountSumColumn.ASC())
@ -1018,10 +1024,10 @@ OFFSET 20;
query := UNION_ALL( query := UNION_ALL(
Payment. Payment.
SELECT(Payment.PaymentID.AS("payment.payment_id"), Payment.Amount). SELECT(Payment.PaymentID.AS("payment.payment_id"), Payment.Amount).
WHERE(Payment.Amount.LtEqL(100)), WHERE(Payment.Amount.LT_EQ(Int(100))),
Payment. Payment.
SELECT(Payment.PaymentID, Payment.Amount). SELECT(Payment.PaymentID, Payment.Amount).
WHERE(Payment.Amount.GtEqL(200)), WHERE(Payment.Amount.GT_EQ(Int(200))),
). ).
ORDER_BY(RefColumn("payment.payment_id").ASC(), Payment.Amount.DESC()). ORDER_BY(RefColumn("payment.payment_id").ASC(), Payment.Amount.DESC()).
LIMIT(10). LIMIT(10).
@ -1061,9 +1067,9 @@ LIMIT 20;
` `
query := Payment.SELECT( query := Payment.SELECT(
CASE(Payment.StaffID). CASE(Payment.StaffID).
WHEN(IntLiteral(1)).THEN(Literal("ONE")). WHEN(Int(1)).THEN(Literal("ONE")).
WHEN(IntLiteral(2)).THEN(Literal("TWO")). WHEN(Int(2)).THEN(Literal("TWO")).
WHEN(IntLiteral(3)).THEN(Literal("THREE")). WHEN(Int(3)).THEN(Literal("THREE")).
ELSE(Literal("OTHER")).AS("staff_id_num"), ELSE(Literal("OTHER")).AS("staff_id_num"),
). ).
ORDER_BY(Payment.PaymentID.ASC()). ORDER_BY(Payment.PaymentID.ASC()).

View file

@ -2,7 +2,7 @@ package tests
import ( import (
"fmt" "fmt"
"github.com/sub0zero/go-sqlbuilder/sqlbuilder" . "github.com/sub0zero/go-sqlbuilder/sqlbuilder"
"github.com/sub0zero/go-sqlbuilder/tests/.test_files/dvd_rental/test_sample/model" "github.com/sub0zero/go-sqlbuilder/tests/.test_files/dvd_rental/test_sample/model"
"github.com/sub0zero/go-sqlbuilder/tests/.test_files/dvd_rental/test_sample/table" "github.com/sub0zero/go-sqlbuilder/tests/.test_files/dvd_rental/test_sample/table"
"gotest.tools/assert" "gotest.tools/assert"
@ -11,9 +11,9 @@ import (
func TestUpdateValues(t *testing.T) { func TestUpdateValues(t *testing.T) {
_, err := table.Link.INSERT(table.Link.URL, table.Link.Name, table.Link.Rel). _, err := table.Link.INSERT(table.Link.URL, table.Link.Name, table.Link.Rel).
VALUES("http://www.postgresqltutorial.com", "PostgreSQL Tutorial", sqlbuilder.DEFAULT). VALUES("http://www.postgresqltutorial.com", "PostgreSQL Tutorial", DEFAULT).
VALUES("http://www.yahoo.com", "Yahoo", sqlbuilder.DEFAULT). VALUES("http://www.yahoo.com", "Yahoo", DEFAULT).
VALUES("http://www.bing.com", "Bing", sqlbuilder.DEFAULT). VALUES("http://www.bing.com", "Bing", DEFAULT).
RETURNING(table.Link.ID).Execute(db) RETURNING(table.Link.ID).Execute(db)
assert.NilError(t, err) assert.NilError(t, err)
@ -21,7 +21,7 @@ func TestUpdateValues(t *testing.T) {
query := table.Link. query := table.Link.
UPDATE(table.Link.Name, table.Link.URL). UPDATE(table.Link.Name, table.Link.URL).
SET("Bong", "http://bong.com"). SET("Bong", "http://bong.com").
WHERE(table.Link.Name.EqString("Bing")) WHERE(table.Link.Name.EQ(String("Bing")))
queryStr, args, err := query.Sql() queryStr, args, err := query.Sql()
@ -38,7 +38,7 @@ func TestUpdateValues(t *testing.T) {
links := []model.Link{} links := []model.Link{}
err = table.Link.SELECT(table.Link.AllColumns). err = table.Link.SELECT(table.Link.AllColumns).
WHERE(table.Link.Name.EqString("Bong")). WHERE(table.Link.Name.EQ(String("Bong"))).
Query(db, &links) Query(db, &links)
assert.NilError(t, err) assert.NilError(t, err)
@ -48,11 +48,11 @@ func TestUpdateValues(t *testing.T) {
func TestUpdateAndReturning(t *testing.T) { func TestUpdateAndReturning(t *testing.T) {
_, err := table.Link.INSERT(table.Link.URL, table.Link.Name, table.Link.Rel). _, err := table.Link.INSERT(table.Link.URL, table.Link.Name, table.Link.Rel).
VALUES("http://www.postgresqltutorial.com", "PostgreSQL Tutorial", sqlbuilder.DEFAULT). VALUES("http://www.postgresqltutorial.com", "PostgreSQL Tutorial", DEFAULT).
VALUES("http://www.ask.com", "Ask", sqlbuilder.DEFAULT). VALUES("http://www.ask.com", "Ask", DEFAULT).
VALUES("http://www.ask.com", "Ask", sqlbuilder.DEFAULT). VALUES("http://www.ask.com", "Ask", DEFAULT).
VALUES("http://www.yahoo.com", "Yahoo", sqlbuilder.DEFAULT). VALUES("http://www.yahoo.com", "Yahoo", DEFAULT).
VALUES("http://www.bing.com", "Bing", sqlbuilder.DEFAULT). VALUES("http://www.bing.com", "Bing", DEFAULT).
RETURNING(table.Link.ID).Execute(db) RETURNING(table.Link.ID).Execute(db)
assert.NilError(t, err) assert.NilError(t, err)
@ -60,7 +60,7 @@ func TestUpdateAndReturning(t *testing.T) {
stmt := table.Link. stmt := table.Link.
UPDATE(table.Link.Name, table.Link.URL). UPDATE(table.Link.Name, table.Link.URL).
SET("DuckDuckGo", "http://www.duckduckgo.com"). SET("DuckDuckGo", "http://www.duckduckgo.com").
WHERE(table.Link.Name.EqString("Ask")). WHERE(table.Link.Name.EQ(String("Ask"))).
RETURNING(table.Link.AllColumns) RETURNING(table.Link.AllColumns)
stmtStr, args, err := stmt.Sql() stmtStr, args, err := stmt.Sql()