Skip to content

Commit

Permalink
Merge pull request #16 from jbowens/jackson/bool-expr-slices
Browse files Browse the repository at this point in the history
Use slices for AND and OR expressions
  • Loading branch information
petermattis committed Apr 6, 2015
2 parents 5f89812 + f4bbe62 commit 7a92503
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 26 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Expand Up @@ -7,7 +7,7 @@ GitHub by forking the repository and sending a pull request.
When submitting code, please make every effort to follow existing
conventions and style in order to keep the code as readable as
possible. Please also make sure your code compiles and the tests pass
by running `./integration_test.sh`. The code must also be formmatted
by running `./integration_test.sh`. The code must also be formatted
with `go fmt`.

Before your code can be accepted into the project you must also sign the
Expand Down
52 changes: 42 additions & 10 deletions ast.go
Expand Up @@ -681,18 +681,34 @@ const (

// AndExpr represents an AND expression.
type AndExpr struct {
Op string
Left, Right BoolExpr
Op string
Exprs []BoolExpr
}

func (node *AndExpr) Serialize(w io.Writer) error {
if err := node.Left.Serialize(w); err != nil {
if len(node.Exprs) == 0 {
_, err := w.Write(astBoolTrue)
return err
} else if len(node.Exprs) == 1 {
return node.Exprs[0].Serialize(w)
}
if _, err := io.WriteString(w, node.Op); err != nil {

if _, err := w.Write(astOpenParen); err != nil {
return err
}
return node.Right.Serialize(w)
if err := node.Exprs[0].Serialize(w); err != nil {
return err
}
for _, expr := range node.Exprs[1:] {
if _, err := io.WriteString(w, node.Op); err != nil {
return err
}
if err := expr.Serialize(w); err != nil {
return err
}
}
_, err := w.Write(astCloseParen)
return err
}

const (
Expand All @@ -701,18 +717,34 @@ const (

// OrExpr represents an OR expression.
type OrExpr struct {
Op string
Left, Right BoolExpr
Op string
Exprs []BoolExpr
}

func (node *OrExpr) Serialize(w io.Writer) error {
if err := node.Left.Serialize(w); err != nil {
if len(node.Exprs) == 0 {
_, err := w.Write(astBoolFalse)
return err
} else if len(node.Exprs) == 1 {
return node.Exprs[0].Serialize(w)
}
if _, err := io.WriteString(w, node.Op); err != nil {

if _, err := w.Write(astOpenParen); err != nil {
return err
}
return node.Right.Serialize(w)
if err := node.Exprs[0].Serialize(w); err != nil {
return err
}
for _, expr := range node.Exprs[1:] {
if _, err := io.WriteString(w, node.Op); err != nil {
return err
}
if err := expr.Serialize(w); err != nil {
return err
}
}
_, err := w.Write(astCloseParen)
return err
}

const (
Expand Down
36 changes: 32 additions & 4 deletions builder.go
Expand Up @@ -796,21 +796,49 @@ func unwrapBoolExpr(expr BoolExpr) BoolExpr {

// And creates an AND expression.
func (e BoolExprBuilder) And(expr BoolExpr) BoolExprBuilder {
var conditions []BoolExpr

if andExpr, ok := e.BoolExpr.(*AndExpr); ok {
conditions = append(conditions, andExpr.Exprs...)
} else {
conditions = append(conditions, e.BoolExpr)
}

unwrapped := unwrapBoolExpr(expr)
if andExpr, ok := unwrapped.(*AndExpr); ok {
conditions = append(conditions, andExpr.Exprs...)
} else {
conditions = append(conditions, unwrapped)
}

return BoolExprBuilder{
&AndExpr{
Op: astAndExpr,
Left: &ParenBoolExpr{Expr: e.BoolExpr},
Right: unwrapBoolExpr(expr),
Exprs: conditions,
}}
}

// Or creates an OR expression.
func (e BoolExprBuilder) Or(expr BoolExpr) BoolExprBuilder {
var conditions []BoolExpr

if orExpr, ok := e.BoolExpr.(*OrExpr); ok {
conditions = append(conditions, orExpr.Exprs...)
} else {
conditions = append(conditions, e.BoolExpr)
}

unwrapped := unwrapBoolExpr(expr)
if orExpr, ok := unwrapped.(*OrExpr); ok {
conditions = append(conditions, orExpr.Exprs...)
} else {
conditions = append(conditions, unwrapped)
}

return BoolExprBuilder{
&OrExpr{
Op: astOrExpr,
Left: &ParenBoolExpr{Expr: e.BoolExpr},
Right: unwrapBoolExpr(expr),
Exprs: conditions,
}}
}

Expand Down
8 changes: 5 additions & 3 deletions builder_test.go
Expand Up @@ -345,11 +345,13 @@ func TestSelectBuilder(t *testing.T) {
{users.Select("*").Where(foo.Eq("bar").Not()),
"SELECT * FROM `users` WHERE NOT (`users`.`foo` = 'bar')"},
{users.Select("*").Where(foo.Eq("bar").And(bar.Lt(2))),
"SELECT * FROM `users` WHERE (`users`.`foo` = 'bar') AND `users`.`bar` < 2"},
"SELECT * FROM `users` WHERE (`users`.`foo` = 'bar' AND `users`.`bar` < 2)"},
{users.Select("*").Where(foo.Eq("bar").Or(bar.Lte(2))),
"SELECT * FROM `users` WHERE (`users`.`foo` = 'bar') OR `users`.`bar` <= 2"},
"SELECT * FROM `users` WHERE (`users`.`foo` = 'bar' OR `users`.`bar` <= 2)"},
{users.Select("*").Where(foo.Eq("bar").And(bar.Gt(2)).Or(qux.Eq(false))),
"SELECT * FROM `users` WHERE ((`users`.`foo` = 'bar') AND `users`.`bar` > 2) OR `users`.`qux` = 0"},
"SELECT * FROM `users` WHERE ((`users`.`foo` = 'bar' AND `users`.`bar` > 2) OR `users`.`qux` = 0)"},
{users.Select("*").Where(foo.Eq("bar").And(bar.Eq("baz")).And(qux.IsNull().Or(qux.Gt(5)))),
"SELECT * FROM `users` WHERE (`users`.`foo` = 'bar' AND `users`.`bar` = 'baz' AND (`users`.`qux` IS NULL OR `users`.`qux` > 5))"},
// GroupBy
{users.Select(foo).Where(foo.Eq("bar")).GroupBy(bar),
"SELECT `users`.`foo` FROM `users` WHERE `users`.`foo` = 'bar' GROUP BY `users`.`bar`"},
Expand Down
16 changes: 8 additions & 8 deletions db_internal_test.go
Expand Up @@ -120,18 +120,18 @@ func TestDBDeleteStatements(t *testing.T) {
},
{[]interface{}{&multiCol{1, 2, 3, 4}},
[]string{
"DELETE FROM `multi` WHERE ((`multi`.`a` = 1) AND `multi`.`b` = 2) AND `multi`.`c` IN (3)",
"DELETE FROM `multi` WHERE (`multi`.`a` = 1 AND `multi`.`b` = 2 AND `multi`.`c` IN (3))",
},
},
{[]interface{}{&multiCol{1, 2, 3, 4}, &multiCol{1, 2, 4, 5}},
[]string{
"DELETE FROM `multi` WHERE ((`multi`.`a` = 1) AND `multi`.`b` = 2) AND `multi`.`c` IN (3, 4)",
"DELETE FROM `multi` WHERE (`multi`.`a` = 1 AND `multi`.`b` = 2 AND `multi`.`c` IN (3, 4))",
},
},
{[]interface{}{&multiCol{1, 2, 3, 4}, &multiCol{1, 3, 4, 5}},
[]string{
"DELETE FROM `multi` WHERE ((`multi`.`a` = 1) AND `multi`.`b` = 2) AND `multi`.`c` IN (3)",
"DELETE FROM `multi` WHERE ((`multi`.`a` = 1) AND `multi`.`b` = 3) AND `multi`.`c` IN (4)",
"DELETE FROM `multi` WHERE (`multi`.`a` = 1 AND `multi`.`b` = 2 AND `multi`.`c` IN (3))",
"DELETE FROM `multi` WHERE (`multi`.`a` = 1 AND `multi`.`b` = 3 AND `multi`.`c` IN (4))",
},
},
}
Expand Down Expand Up @@ -166,7 +166,7 @@ func TestDBGetStatements(t *testing.T) {
},
{&multiCol{}, []interface{}{1, 2, 3},
"SELECT `multi`.`a`, `multi`.`b`, `multi`.`c`, `multi`.`d` " +
"FROM `multi` WHERE ((`multi`.`a` = 1) AND `multi`.`b` = 2) AND `multi`.`c` = 3",
"FROM `multi` WHERE (`multi`.`a` = 1 AND `multi`.`b` = 2 AND `multi`.`c` = 3)",
},
}

Expand Down Expand Up @@ -283,15 +283,15 @@ func TestDBUpdateStatements(t *testing.T) {
{[]interface{}{&multiCol{1, 2, 3, 4}},
[]string{
"UPDATE `multi` SET `multi`.`d` = 4 " +
"WHERE ((`multi`.`a` = 1) AND `multi`.`b` = 2) AND `multi`.`c` = 3",
"WHERE (`multi`.`a` = 1 AND `multi`.`b` = 2 AND `multi`.`c` = 3)",
},
},
{[]interface{}{&multiCol{1, 2, 3, 4}, &multiCol{5, 6, 7, 8}},
[]string{
"UPDATE `multi` SET `multi`.`d` = 4 " +
"WHERE ((`multi`.`a` = 1) AND `multi`.`b` = 2) AND `multi`.`c` = 3",
"WHERE (`multi`.`a` = 1 AND `multi`.`b` = 2 AND `multi`.`c` = 3)",
"UPDATE `multi` SET `multi`.`d` = 8 " +
"WHERE ((`multi`.`a` = 5) AND `multi`.`b` = 6) AND `multi`.`c` = 7",
"WHERE (`multi`.`a` = 5 AND `multi`.`b` = 6 AND `multi`.`c` = 7)",
},
},
}
Expand Down

0 comments on commit 7a92503

Please sign in to comment.