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 {
expression
Eq(expression boolExpression) boolExpression
NotEq(expression boolExpression) boolExpression
GtEq(rhs expression) boolExpression
LtEq(rhs expression) boolExpression
EQ(expression boolExpression) boolExpression
NOT_EQ(expression boolExpression) 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
IS_TRUE() boolExpression
IS_FALSE() boolExpression
}
type boolInterfaceImpl struct {
parent boolExpression
}
func (b *boolInterfaceImpl) Eq(expression boolExpression) boolExpression {
return Eq(b.parent, expression)
func (b *boolInterfaceImpl) EQ(expression boolExpression) boolExpression {
return EQ(b.parent, expression)
}
func (b *boolInterfaceImpl) NotEq(expression boolExpression) boolExpression {
return NotEq(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) NOT_EQ(expression boolExpression) boolExpression {
return NOT_EQ(b.parent, expression)
}
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 {
return Or(b.parent, expression)
}
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 {
return nil
return IS_FALSE(b.parent)
}
//---------------------------------------------------//
type boolLiteralExpression struct {
boolInterfaceImpl
literalExpression
func (b *boolInterfaceImpl) IS_NOT_FALSE() boolExpression {
return IS_NOT_FALSE(b.parent)
}
func newBoolLiteralExpression(value bool) boolExpression {
boolLiteralExpression := boolLiteralExpression{}
func (b *boolInterfaceImpl) IS_UNKNOWN() boolExpression {
return IS_UNKNOWN(b.parent)
}
boolLiteralExpression.literalExpression = *Literal(value)
boolLiteralExpression.boolInterfaceImpl.parent = &boolLiteralExpression
return &boolLiteralExpression
func (b *boolInterfaceImpl) IS_NOT_UNKNOWN() boolExpression {
return IS_NOT_UNKNOWN(b.parent)
}
//---------------------------------------------------//
@ -69,13 +66,13 @@ type binaryBoolExpression struct {
expressionInterfaceImpl
boolInterfaceImpl
binaryExpression
binaryOpExpression
}
func newBinaryBoolExpression(lhs, rhs expression, operator string) boolExpression {
boolExpression := binaryBoolExpression{}
boolExpression.binaryExpression = newBinaryExpression(lhs, rhs, operator)
boolExpression.binaryOpExpression = newBinaryExpression(lhs, rhs, operator)
boolExpression.expressionInterfaceImpl.parent = &boolExpression
boolExpression.boolInterfaceImpl.parent = &boolExpression
@ -87,113 +84,33 @@ type prefixBoolExpression struct {
expressionInterfaceImpl
boolInterfaceImpl
prefixExpression
prefixOpExpression
}
func newPrefixBoolExpression(expression expression, operator string) boolExpression {
boolExpression := prefixBoolExpression{}
boolExpression.prefixExpression = newPrefixExpression(expression, operator)
exp := prefixBoolExpression{}
exp.prefixOpExpression = newPrefixExpression(expression, operator)
boolExpression.expressionInterfaceImpl.parent = &boolExpression
boolExpression.boolInterfaceImpl.parent = &boolExpression
exp.expressionInterfaceImpl.parent = &exp
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 Eq(lhs, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, "=")
}
func newPostifxBoolExpression(expression expression, operator string) boolExpression {
exp := postfixBoolOpExpression{}
exp.postfixOpExpression = newPostfixOpExpression(expression, operator)
// Returns a representation of "a=b", where b is a literal
func EqL(lhs expression, val interface{}) boolExpression {
return Eq(lhs, Literal(val))
}
exp.expressionInterfaceImpl.parent = &exp
exp.boolInterfaceImpl.parent = &exp
// Returns a representation of "a!=b"
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))
return &exp
}

View file

@ -6,8 +6,42 @@ import (
"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) {
boolExpression := Eq(Literal(2), Literal(3))
boolExpression := EQ(Literal(2), Literal(3))
out := queryData{}
err := boolExpression.serialize(select_statement, &out)
@ -28,7 +62,7 @@ func TestBinaryExpression(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{}
err := exp.serialize(select_statement, &out)
@ -38,7 +72,7 @@ func TestBinaryExpression(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{}
err := exp.serialize(select_statement, &out)
@ -49,7 +83,7 @@ func TestBinaryExpression(t *testing.T) {
}
func TestUnaryExpression(t *testing.T) {
notExpression := Not(Eq(Literal(2), Literal(1)))
notExpression := NOT(EQ(Literal(2), Literal(1)))
out := queryData{}
err := notExpression.serialize(select_statement, &out)
@ -68,7 +102,7 @@ func TestUnaryExpression(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{}
err := exp.serialize(select_statement, &out)
@ -79,27 +113,27 @@ func TestUnaryExpression(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)
err := exp.serialize(select_statement, &out)
assert.NilError(t, err)
assert.Equal(t, out.buff.String(), "IS TRUE $1 = $2")
assert.Equal(t, out.buff.String(), "$1 = $2 IS TRUE")
t.Run("and", func(t *testing.T) {
exp := notExpression.AND(Eq(Literal(4), Literal(5)))
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(), `(IS TRUE $1 = $2 AND $3 = $4)`)
assert.Equal(t, out.buff.String(), `($1 = $2 IS TRUE AND $3 = $4)`)
})
}
func TestBoolLiteral(t *testing.T) {
literal := newBoolLiteralExpression(true)
literal := Bool(true)
out := queryData{}
err := literal.serialize(select_statement, &out)
@ -113,7 +147,7 @@ func TestExists(t *testing.T) {
query := EXISTS(
table2.
SELECT(Literal(1)).
WHERE(table1Col1.Eq(table2Col3)),
WHERE(table1Col1.EQ(table2Col3)),
)
out := queryData{}

View file

@ -12,7 +12,7 @@ func TestDeleteUnconditionally(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)
fmt.Println(sql)

View file

@ -32,7 +32,7 @@ func Example() {
filename := t2.C("filename")
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(
And(EqL(ns_id2, 456), In(sjid, in)))
text, _ := q.String()

View file

@ -11,12 +11,16 @@ type expression interface {
groupByClause
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
NOT_IN(subQuery selectStatement) boolExpression
AS(alias string) projection
IS_DISTINCT_FROM(expression expression) boolExpression
IS_NULL() boolExpression
ASC() orderByClause
DESC() orderByClause
}
@ -25,6 +29,22 @@ type expressionInterfaceImpl struct {
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 {
return newBinaryBoolExpression(e.parent, subQuery, "IN")
}
@ -37,14 +57,6 @@ func (e *expressionInterfaceImpl) AS(alias string) projection {
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 {
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)
type binaryExpression struct {
type binaryOpExpression struct {
lhs, rhs expression
operator string
}
func newBinaryExpression(lhs, rhs expression, operator string, parent ...expression) binaryExpression {
binaryExpression := binaryExpression{
func newBinaryExpression(lhs, rhs expression, operator string, parent ...expression) binaryOpExpression {
binaryExpression := binaryOpExpression{
lhs: lhs,
rhs: rhs,
operator: operator,
@ -95,7 +107,7 @@ func isSimpleOperand(expression expression) bool {
return false
}
func (c *binaryExpression) serialize(statement statementType, out *queryData) error {
func (c *binaryOpExpression) serialize(statement statementType, out *queryData) error {
if c == nil {
return errors.New("Binary expression is nil.")
}
@ -129,14 +141,14 @@ func (c *binaryExpression) serialize(statement statementType, out *queryData) er
return nil
}
// A not expression which negates a expression value
type prefixExpression struct {
// A prefix operator expression
type prefixOpExpression struct {
expression expression
operator string
}
func newPrefixExpression(expression expression, operator string) prefixExpression {
prefixExpression := prefixExpression{
func newPrefixExpression(expression expression, operator string) prefixOpExpression {
prefixExpression := prefixOpExpression{
expression: expression,
operator: operator,
}
@ -144,7 +156,7 @@ func newPrefixExpression(expression expression, operator string) prefixExpressio
return prefixExpression
}
func (p *prefixExpression) serialize(statement statementType, out *queryData) error {
func (p *prefixOpExpression) serialize(statement statementType, out *queryData) error {
if p == nil {
return errors.New("Prefix expression is nil.")
}
@ -160,3 +172,35 @@ func (p *prefixExpression) serialize(statement statementType, out *queryData) er
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) {
expr := Gt(nil, table1Col1)
expr := GT(nil, table1Col1)
buf := &bytes.Buffer{}
@ -164,7 +164,7 @@ func (s *ExprSuite) TestBinaryExprNilLHS(c *gc.C) {
}
func (s *ExprSuite) TestNegateExpr(c *gc.C) {
expr := Not(EqL(table1Col1, 123))
expr := NOT(EqL(table1Col1, 123))
buf := &bytes.Buffer{}
@ -176,7 +176,7 @@ func (s *ExprSuite) TestNegateExpr(c *gc.C) {
}
func (s *ExprSuite) TestBinaryExprNilRHS(c *gc.C) {
expr := Lt(table1Col1, nil)
expr := LT(table1Col1, nil)
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 {
// return INNER_JOIN(s, table, col1.Eq(col2))
// return INNER_JOIN(s, table, col1.EQ(col2))
//}
// 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) {
query := CASE().
WHEN(table3Col1.EqL(1)).THEN(table3Col1.Add(IntLiteral(1))).
WHEN(table3Col1.EqL(2)).THEN(table3Col1.Add(IntLiteral(2)))
WHEN(table3Col1.EQ(Int(1))).THEN(table3Col1.ADD(Int(1))).
WHEN(table3Col1.EQ(Int(2))).THEN(table3Col1.ADD(Int(2)))
queryData := &queryData{}
@ -20,9 +20,9 @@ func TestCase1(t *testing.T) {
func TestCase2(t *testing.T) {
query := CASE(table3Col1).
WHEN(IntLiteral(1)).THEN(table3Col1.Add(IntLiteral(1))).
WHEN(IntLiteral(2)).THEN(table3Col1.Add(IntLiteral(2))).
ELSE(IntLiteral(0))
WHEN(Int(1)).THEN(table3Col1.ADD(Int(1))).
WHEN(Int(2)).THEN(table3Col1.ADD(Int(2))).
ELSE(Int(0))
queryData := &queryData{}

View file

@ -69,7 +69,7 @@ func (i *insertStatementImpl) VALUES(values ...interface{}) insertStatement {
func (i *insertStatementImpl) VALUES_MAPPING(data interface{}) insertStatement {
if data == nil {
i.addError("Add method data is nil.")
i.addError("ADD method data is nil.")
return i
}
@ -80,7 +80,7 @@ func (i *insertStatementImpl) VALUES_MAPPING(data interface{}) insertStatement {
}
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
}
@ -93,7 +93,7 @@ func (i *insertStatementImpl) VALUES_MAPPING(data interface{}) insertStatement {
structField := value.FieldByName(structFieldName)
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
}

View file

@ -56,11 +56,11 @@ INSERT INTO db.table1 (col1) VALUES
func TestInsertDate(t *testing.T) {
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.Equal(t, sql, `
INSERT INTO db.table1 (col4) VALUES
INSERT INTO db.table1 (colTime) VALUES
($1);
`)
}

View file

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

View file

@ -1,5 +1,7 @@
package sqlbuilder
import "time"
// Representation of an escaped literal
type literalExpression struct {
expressionInterfaceImpl
@ -24,7 +26,7 @@ type numLiteralExpression struct {
numericInterfaceImpl
}
func IntLiteral(value int) numericExpression {
func Int(value int) numericExpression {
numLiteral := &numLiteralExpression{}
numLiteral.literalExpression = *Literal(value)
@ -34,3 +36,63 @@ func IntLiteral(value int) numericExpression {
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 {
expression
Eq(expression numericExpression) boolExpression
EqL(literal interface{}) boolExpression
NotEq(expression numericExpression) boolExpression
NotEqL(literal interface{}) boolExpression
EQ(expression numericExpression) boolExpression
NOT_EQ(expression numericExpression) boolExpression
LT(rhs numericExpression) boolExpression
LT_EQ(rhs numericExpression) boolExpression
GT(rhs numericExpression) boolExpression
GT_EQ(rhs numericExpression) boolExpression
Gt(rhs numericExpression) boolExpression
GtEq(rhs numericExpression) boolExpression
GtEqL(literal interface{}) boolExpression
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
ADD(expression numericExpression) numericExpression
SUB(expression numericExpression) numericExpression
MUL(expression numericExpression) numericExpression
DIV(expression numericExpression) numericExpression
}
type numericInterfaceImpl struct {
parent numericExpression
}
func (n *numericInterfaceImpl) Eq(expression numericExpression) boolExpression {
return Eq(n.parent, expression)
func (n *numericInterfaceImpl) EQ(expression numericExpression) boolExpression {
return EQ(n.parent, expression)
}
func (n *numericInterfaceImpl) EqL(literal interface{}) boolExpression {
return Eq(n.parent, Literal(literal))
func (n *numericInterfaceImpl) NOT_EQ(expression numericExpression) boolExpression {
return NOT_EQ(n.parent, expression)
}
func (n *numericInterfaceImpl) NotEq(expression numericExpression) boolExpression {
return NotEq(n.parent, expression)
func (n *numericInterfaceImpl) GT(expression numericExpression) boolExpression {
return GT(n.parent, expression)
}
func (n *numericInterfaceImpl) NotEqL(literal interface{}) boolExpression {
return NotEq(n.parent, Literal(literal))
func (n *numericInterfaceImpl) GT_EQ(expression numericExpression) boolExpression {
return GT_EQ(n.parent, expression)
}
func (n *numericInterfaceImpl) Gt(expression numericExpression) boolExpression {
return Gt(n.parent, expression)
func (n *numericInterfaceImpl) LT(expression numericExpression) boolExpression {
return LT(n.parent, expression)
}
func (n *numericInterfaceImpl) GtEq(expression numericExpression) boolExpression {
return GtEq(n.parent, expression)
func (n *numericInterfaceImpl) LT_EQ(expression numericExpression) boolExpression {
return LT_EQ(n.parent, expression)
}
func (n *numericInterfaceImpl) GtEqL(literal interface{}) boolExpression {
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 {
func (n *numericInterfaceImpl) ADD(expression numericExpression) numericExpression {
return newBinaryNumericExpression(n.parent, expression, "+")
}
func (n *numericInterfaceImpl) Sub(expression numericExpression) numericExpression {
func (n *numericInterfaceImpl) SUB(expression numericExpression) numericExpression {
return newBinaryNumericExpression(n.parent, expression, "-")
}
func (n *numericInterfaceImpl) Mul(expression numericExpression) numericExpression {
func (n *numericInterfaceImpl) MUL(expression numericExpression) numericExpression {
return newBinaryNumericExpression(n.parent, expression, "*")
}
func (n *numericInterfaceImpl) Div(expression numericExpression) numericExpression {
func (n *numericInterfaceImpl) DIV(expression numericExpression) numericExpression {
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 {
expressionInterfaceImpl
numericInterfaceImpl
binaryExpression
binaryOpExpression
}
func newBinaryNumericExpression(lhs, rhs expression, operator string) numericExpression {
numericExpression := binaryNumericExpression{}
numericExpression.binaryExpression = newBinaryExpression(lhs, rhs, operator)
numericExpression.binaryOpExpression = newBinaryExpression(lhs, rhs, operator)
numericExpression.expressionInterfaceImpl.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) {
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()
c.Assert(err, gc.IsNil)
@ -196,7 +196,7 @@ func (s *StmtSuite) TestSelectMultiOrderBy(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()
c.Assert(err, gc.IsNil)
@ -279,7 +279,7 @@ func (s *StmtSuite) TestInsertSingleValue(c *gc.C) {
func (s *StmtSuite) TestInsertDate(c *gc.C) {
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(
@ -456,14 +456,14 @@ func (s *StmtSuite) TestUnionSelectWithMismatchedColumns(c *gc.C) {
table1Col1,
table1Col2,
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(LtL(table1Col1, 23)).OrderBy(table1Col4).Limit(20),
table1.Select(table1Col1).Where(LtL(table1Col1, 23)).OrderBy(table1ColTime).Limit(20),
)
q := UNION(select_queries...)
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)
_, err := q.String()
@ -496,15 +496,15 @@ func (s *StmtSuite) TestComplicatedUnionSelectWithWhereStatement(c *gc.C) {
).Where(And(GtL(table1Col1, 456), LtL(table1Col1, 654))),
table1.Select(
table1Col1,
).Where(LtL(table1Col1, 23)).OrderBy(table1Col4).Limit(20),
).Where(LtL(table1Col1, 23)).OrderBy(table1ColTime).Limit(20),
)
q := UNION(select_queries...)
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.GroupBy(table1Col4)
q = q.GroupBy(table1ColTime)
sql, err := q.String()

View file

@ -3,28 +3,38 @@ package sqlbuilder
type stringExpression interface {
expression
Eq(expression stringExpression) boolExpression
EqString(value string) boolExpression
NotEq(expression stringExpression) boolExpression
NotEqString(value string) boolExpression
EQ(rhs stringExpression) boolExpression
NOT_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 (b *stringInterfaceImpl) Eq(expression stringExpression) boolExpression {
return Eq(b.parent, expression)
func (s *stringInterfaceImpl) EQ(rhs stringExpression) boolExpression {
return EQ(s.parent, rhs)
}
func (b *stringInterfaceImpl) EqString(value string) boolExpression {
return EqL(b.parent, value)
func (s *stringInterfaceImpl) NOT_EQ(rhs stringExpression) boolExpression {
return NOT_EQ(s.parent, rhs)
}
func (b *stringInterfaceImpl) NotEq(expression stringExpression) boolExpression {
return NotEq(b.parent, expression)
func (s *stringInterfaceImpl) GT(rhs stringExpression) boolExpression {
return GT(s.parent, rhs)
}
func (b *stringInterfaceImpl) NotEqString(value string) boolExpression {
return NotEq(b.parent, Literal(value))
func (s *stringInterfaceImpl) GT_EQ(rhs stringExpression) boolExpression {
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[1], gc.Equals, table1Col2)
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) {
@ -74,7 +74,7 @@ func (s *TableSuite) TestJoinNilOnCondition(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{}
@ -89,7 +89,7 @@ func (s *TableSuite) TestInnerJoin(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{}
@ -105,7 +105,7 @@ func (s *TableSuite) TestLeftJoin(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{}
@ -121,21 +121,21 @@ func (s *TableSuite) TestRightJoin(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()
// c.Assert(len(cols), gc.Equals, 6)
// c.Assert(cols[0], gc.Equals, table1Col1)
// c.Assert(cols[1], gc.Equals, table1Col2)
// 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[5], gc.Equals, table2Col4)
//}
func (s *TableSuite) TestNestedInnerJoin(c *gc.C) {
join1 := table1.InnerJoinOn(table2, Eq(table1Col3, table2Col3))
join2 := join1.InnerJoinOn(table3, Eq(table1Col1, table3Col1))
join1 := table1.InnerJoinOn(table2, EQ(table1Col3, table2Col3))
join2 := join1.InnerJoinOn(table3, EQ(table1Col1, table3Col1))
buf := &bytes.Buffer{}
@ -152,8 +152,8 @@ func (s *TableSuite) TestNestedInnerJoin(c *gc.C) {
}
func (s *TableSuite) TestNestedLeftJoin(c *gc.C) {
join1 := table1.InnerJoinOn(table2, Eq(table1Col3, table2Col3))
join2 := join1.LeftJoinOn(table3, Eq(table1Col1, table3Col1))
join1 := table1.InnerJoinOn(table2, EQ(table1Col3, table2Col3))
join2 := join1.LeftJoinOn(table3, EQ(table1Col1, table3Col1))
buf := &bytes.Buffer{}
@ -170,8 +170,8 @@ func (s *TableSuite) TestNestedLeftJoin(c *gc.C) {
}
func (s *TableSuite) TestNestedRightJoin(c *gc.C) {
join1 := table1.InnerJoinOn(table2, Eq(table1Col3, table2Col3))
join2 := join1.RightJoinOn(table3, Eq(table1Col1, table3Col1))
join1 := table1.InnerJoinOn(table2, EQ(table1Col3, table2Col3))
join2 := join1.RightJoinOn(table3, EQ(table1Col1, table3Col1))
buf := &bytes.Buffer{}

View file

@ -1,29 +1,53 @@
package sqlbuilder
import (
"gotest.tools/assert"
"testing"
)
var table1Col1 = NewIntegerColumn("col1", Nullable)
var table1Col2 = NewIntegerColumn("col2", Nullable)
var table1Col3 = NewIntegerColumn("col3", Nullable)
var table1Col4 = NewTimeColumn("col4", Nullable)
var table1ColTime = NewTimeColumn("colTime", Nullable)
var table1ColBool = NewBoolColumn("colBool", Nullable)
var table1 = NewTable(
"db",
"table1",
table1Col1,
table1Col2,
table1Col3,
table1Col4)
table1ColTime,
table1ColBool)
var table2Col3 = NewIntegerColumn("col3", Nullable)
var table2Col4 = NewIntegerColumn("col4", Nullable)
var table2StrCol = NewStringColumn("col4", Nullable)
var table2ColBool = NewBoolColumn("colBool", Nullable)
var table2ColTime = NewTimeColumn("colTime", Nullable)
var table2 = NewTable(
"db",
"table2",
table2Col3,
table2Col4)
table2Col4,
table2StrCol,
table2ColBool,
table2ColTime)
var table3Col1 = NewIntegerColumn("col1", Nullable)
var table3Col2 = NewIntegerColumn("col2", Nullable)
var table3StrCol = NewStringColumn("col2", Nullable)
var table3 = NewTable(
"db",
"table3",
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 {
expression
Eq(expression timeExpression) boolExpression
EqL(literal string) boolExpression
NotEq(expression timeExpression) boolExpression
NotEqL(literal string) boolExpression
GtEq(rhs timeExpression) boolExpression
GtEqL(literal string) boolExpression
LtEq(rhs timeExpression) boolExpression
LtEqL(literal string) boolExpression
EQ(rhs timeExpression) boolExpression
NOT_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(expression timeExpression) boolExpression {
return Eq(t.parent, expression)
func (t *timeInterfaceImpl) EQ(rhs timeExpression) boolExpression {
return EQ(t.parent, rhs)
}
func (t *timeInterfaceImpl) EqL(literal string) boolExpression {
return Eq(t.parent, Literal(literal))
func (t *timeInterfaceImpl) NOT_EQ(rhs timeExpression) boolExpression {
return NOT_EQ(t.parent, rhs)
}
func (t *timeInterfaceImpl) NotEq(expression timeExpression) boolExpression {
return NotEq(t.parent, expression)
func (t *timeInterfaceImpl) LT(rhs timeExpression) boolExpression {
return LT(t.parent, rhs)
}
func (t *timeInterfaceImpl) NotEqL(literal string) boolExpression {
return NotEq(t.parent, Literal(literal))
func (t *timeInterfaceImpl) LT_EQ(rhs timeExpression) boolExpression {
return LT_EQ(t.parent, rhs)
}
func (t *timeInterfaceImpl) GtEq(expression timeExpression) boolExpression {
return GtEq(t.parent, expression)
func (t *timeInterfaceImpl) GT(rhs timeExpression) boolExpression {
return GT(t.parent, rhs)
}
func (t *timeInterfaceImpl) GtEqL(literal string) boolExpression {
return GtEq(t.parent, Literal(literal))
}
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))
func (t *timeInterfaceImpl) GT_EQ(rhs timeExpression) boolExpression {
return GT_EQ(t.parent, rhs)
}
//---------------------------------------------------//
@ -54,12 +44,12 @@ type prefixTimeExpression struct {
expressionInterfaceImpl
timeInterfaceImpl
prefixExpression
prefixOpExpression
}
func newPrefixTimeExpression(expression expression, operator string) timeExpression {
timeExpr := prefixTimeExpression{}
timeExpr.prefixExpression = newPrefixExpression(expression, operator)
timeExpr.prefixOpExpression = newPrefixExpression(expression, operator)
timeExpr.expressionInterfaceImpl.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) {
stmt := table1.UPDATE(table1Col1, table1Col2).
SET(table1.SELECT(table1Col2, table2Col3)).
WHERE(table1Col1.EqL(2)).
WHERE(table1Col1.EQ(Int(2))).
RETURNING(table1Col1)
stmtStr, _, err := stmt.Sql()

View file

@ -3,6 +3,7 @@ package tests
import (
"fmt"
"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/table"
"gotest.tools/assert"
@ -12,7 +13,7 @@ import (
func TestUUIDType(t *testing.T) {
query := table.AllTypes.
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()

View file

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

View file

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

View file

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