From 90f373981dc20ef95ecf740103c692e2ba54b72b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Nieto?= <jose.carlos@menteslibres.net>
Date: Sat, 7 Jun 2014 13:53:54 -0500
Subject: [PATCH] Adding tests for value, where, column_value.

---
 util/sqlgen/column_test.go       |  40 +++++++
 util/sqlgen/column_value_test.go |  51 +++++++++
 util/sqlgen/main.go              |  14 ++-
 util/sqlgen/main_test.go         | 181 +++++++++++++------------------
 util/sqlgen/raw.go               |   4 +
 util/sqlgen/value_test.go        |  29 +++++
 util/sqlgen/where.go             |  51 +++++++++
 util/sqlgen/where_test.go        |  91 ++++++++++++++++
 8 files changed, 351 insertions(+), 110 deletions(-)
 create mode 100644 util/sqlgen/column_test.go
 create mode 100644 util/sqlgen/column_value_test.go
 create mode 100644 util/sqlgen/value_test.go
 create mode 100644 util/sqlgen/where.go
 create mode 100644 util/sqlgen/where_test.go

diff --git a/util/sqlgen/column_test.go b/util/sqlgen/column_test.go
new file mode 100644
index 00000000..a34de670
--- /dev/null
+++ b/util/sqlgen/column_test.go
@@ -0,0 +1,40 @@
+package sqlgen
+
+import (
+	"testing"
+)
+
+func TestColumnString(t *testing.T) {
+	var s, e string
+
+	column := Column{"role.name"}
+
+	s = column.String()
+	e = `"role"."name"`
+
+	if s != e {
+		t.Fatalf("Got: %s, Expecting: %s", s, e)
+	}
+}
+
+func TestColumns(t *testing.T) {
+	var s, e string
+
+	columns := Columns{
+		[]Column{
+			{"id"},
+			{"customer"},
+			{"service_id"},
+			{"role.name"},
+			{"role.id"},
+		},
+	}
+
+	s = columns.String()
+	e = `"id", "customer", "service_id", "role"."name", "role"."id"`
+
+	if s != e {
+		t.Fatalf("Got: %s, Expecting: %s", s, e)
+	}
+
+}
diff --git a/util/sqlgen/column_value_test.go b/util/sqlgen/column_value_test.go
new file mode 100644
index 00000000..39fdc30b
--- /dev/null
+++ b/util/sqlgen/column_value_test.go
@@ -0,0 +1,51 @@
+package sqlgen
+
+import (
+	"testing"
+)
+
+func TestColumnValue(t *testing.T) {
+	var s, e string
+	var cv ColumnValue
+
+	cv = ColumnValue{Column{"id"}, "=", Value{1}}
+
+	s = cv.String()
+	e = `"id" = "1"`
+
+	if s != e {
+		t.Fatalf("Got: %s, Expecting: %s", s, e)
+	}
+
+	cv = ColumnValue{Column{"date"}, "=", Value{Raw{"NOW()"}}}
+
+	s = cv.String()
+	e = `"date" = NOW()`
+
+	if s != e {
+		t.Fatalf("Got: %s, Expecting: %s", s, e)
+	}
+}
+
+func TestColumnValues(t *testing.T) {
+	var s, e string
+	var cvs ColumnValues
+
+	cvs = ColumnValues{
+		[]ColumnValue{
+			{Column{"id"}, ">", Value{8}},
+			{Column{"other.id"}, "<", Value{Raw{"100"}}},
+			{Column{"name"}, "=", Value{"Haruki Murakami"}},
+			{Column{"created"}, ">=", Value{Raw{"NOW()"}}},
+			{Column{"modified"}, "<=", Value{Raw{"NOW()"}}},
+		},
+	}
+
+	s = cvs.String()
+	e = `"id" > "8", "other"."id" < 100, "name" = "Haruki Murakami", "created" >= NOW(), "modified" <= NOW()`
+
+	if s != e {
+		t.Fatalf("Got: %s, Expecting: %s", s, e)
+	}
+
+}
diff --git a/util/sqlgen/main.go b/util/sqlgen/main.go
index d3b3aa6d..c7144463 100644
--- a/util/sqlgen/main.go
+++ b/util/sqlgen/main.go
@@ -16,9 +16,11 @@ const (
 			ORDER BY {{.Columns}} {{.Sort}}
 		{{end}}
 	`
-
 	sqlSelectLayout = `
-		SELECT {{.Columns}} FROM {{.Source}}
+		SELECT {{.Columns}}
+
+			FROM {{.Source}}
+
 			{{if .Where}}
 				WHERE {{.Where}}
 			{{end}}
@@ -34,7 +36,8 @@ const (
 			{{end}}
 	`
 	sqlDeleteLayout = `
-		DELETE FROM {{.Source}}
+		DELETE
+			FROM {{.Source}}
 			{{if .Where}}
 				WHERE {{.Where}}
 			{{end}}
@@ -75,11 +78,12 @@ const (
 
 	sqlTautology       = `1 = 1`
 	sqlAllFields       = `*`
-	sqlAnd             = `AND`
-	sqlOr              = `OR`
+	sqlAndKeyword      = `AND`
+	sqlOrKeyword       = `OR`
 	sqlDefaultOperator = `=`
 	sqlDescKeyword     = `DESC`
 	sqlAscKeyword      = `ASC`
+	sqlConditionGroup  = `({{.}})`
 
 	sqlColumnValue = `{{.Column}} {{.Operator}} {{.Value}}`
 
diff --git a/util/sqlgen/main_test.go b/util/sqlgen/main_test.go
index 6303ca00..67eed3d7 100644
--- a/util/sqlgen/main_test.go
+++ b/util/sqlgen/main_test.go
@@ -15,111 +15,6 @@ func trim(a string) string {
 	return a
 }
 
-func TestColumnString(t *testing.T) {
-	var s, e string
-
-	column := Column{"role.name"}
-
-	s = column.String()
-	e = `"role"."name"`
-
-	if s != e {
-		t.Fatalf("Got: %s, Expecting: %s", s, e)
-	}
-}
-
-func TestColumns(t *testing.T) {
-	var s, e string
-
-	columns := Columns{
-		[]Column{
-			{"id"},
-			{"customer"},
-			{"service_id"},
-			{"role.name"},
-			{"role.id"},
-		},
-	}
-
-	s = columns.String()
-	e = `"id", "customer", "service_id", "role"."name", "role"."id"`
-
-	if s != e {
-		t.Fatalf("Got: %s, Expecting: %s", s, e)
-	}
-
-}
-
-func TestValue(t *testing.T) {
-	var s, e string
-	var val Value
-
-	val = Value{1}
-
-	s = val.String()
-	e = `"1"`
-
-	if s != e {
-		t.Fatalf("Got: %s, Expecting: %s", s, e)
-	}
-
-	val = Value{Raw{"NOW()"}}
-
-	s = val.String()
-	e = `NOW()`
-
-	if s != e {
-		t.Fatalf("Got: %s, Expecting: %s", s, e)
-	}
-
-}
-
-func TestColumnValue(t *testing.T) {
-	var s, e string
-	var cv ColumnValue
-
-	cv = ColumnValue{Column{"id"}, "=", Value{1}}
-
-	s = cv.String()
-	e = `"id" = "1"`
-
-	if s != e {
-		t.Fatalf("Got: %s, Expecting: %s", s, e)
-	}
-
-	cv = ColumnValue{Column{"date"}, "=", Value{Raw{"NOW()"}}}
-
-	s = cv.String()
-	e = `"date" = NOW()`
-
-	if s != e {
-		t.Fatalf("Got: %s, Expecting: %s", s, e)
-	}
-}
-
-func TestColumnValues(t *testing.T) {
-	var s, e string
-	var cvs ColumnValues
-
-	cvs = ColumnValues{
-		[]ColumnValue{
-			{Column{"id"}, ">", Value{8}},
-			{Column{"other.id"}, "<", Value{Raw{"100"}}},
-			{Column{"name"}, "=", Value{"Haruki Murakami"}},
-			{Column{"created"}, ">=", Value{Raw{"NOW()"}}},
-			{Column{"modified"}, "<=", Value{Raw{"NOW()"}}},
-		},
-	}
-
-	s = cvs.String()
-	e = `"id" > "8", "other"."id" < 100, "name" = "Haruki Murakami", "created" >= NOW(), "modified" <= NOW()`
-
-	if s != e {
-		t.Fatalf("Got: %s, Expecting: %s", s, e)
-	}
-
-}
-
 func TestTruncateTable(t *testing.T) {
 	var s, e string
 	var stmt Statement
@@ -188,6 +83,26 @@ func TestSelectCount(t *testing.T) {
 	}
 }
 
+func TestSelectCountWhere(t *testing.T) {
+	var s, e string
+	var stmt Statement
+
+	stmt = Statement{
+		Type:   SqlSelectCount,
+		Source: Source{"source name"},
+		Where: Where{
+			ColumnValue{Column{"a"}, "=", Value{Raw{"7"}}},
+		},
+	}
+
+	s = trim(stmt.Compile())
+	e = `SELECT COUNT(1) AS _t FROM "source name" WHERE ("a" = 7)`
+
+	if s != e {
+		t.Fatalf("Got: %s, Expecting: %s", s, e)
+	}
+}
+
 func TestSelectFieldsFrom(t *testing.T) {
 	var s, e string
 	var stmt Statement
@@ -368,3 +283,59 @@ func TestSelectFieldsFromWithOrderBy(t *testing.T) {
 		t.Fatalf("Got: %s, Expecting: %s", s, e)
 	}
 }
+
+func TestSelectFieldsFromWhere(t *testing.T) {
+	var s, e string
+	var stmt Statement
+
+	stmt = Statement{
+		Type: SqlSelect,
+		Columns: Columns{
+			[]Column{
+				{"foo"},
+				{"bar"},
+				{"baz"},
+			},
+		},
+		Source: Source{"source name"},
+		Where: Where{
+			ColumnValue{Column{"baz"}, "=", Value{99}},
+		},
+	}
+
+	s = trim(stmt.Compile())
+	e = `SELECT "foo", "bar", "baz" FROM "source name" WHERE ("baz" = "99")`
+
+	if s != e {
+		t.Fatalf("Got: %s, Expecting: %s", s, e)
+	}
+}
+
+func TestSelectFieldsFromWhereLimitOffset(t *testing.T) {
+	var s, e string
+	var stmt Statement
+
+	stmt = Statement{
+		Type: SqlSelect,
+		Columns: Columns{
+			[]Column{
+				{"foo"},
+				{"bar"},
+				{"baz"},
+			},
+		},
+		Source: Source{"source name"},
+		Where: Where{
+			ColumnValue{Column{"baz"}, "=", Value{99}},
+		},
+		Limit:  10,
+		Offset: 23,
+	}
+
+	s = trim(stmt.Compile())
+	e = `SELECT "foo", "bar", "baz" FROM "source name" WHERE ("baz" = "99") LIMIT 10 OFFSET 23`
+
+	if s != e {
+		t.Fatalf("Got: %s, Expecting: %s", s, e)
+	}
+}
diff --git a/util/sqlgen/raw.go b/util/sqlgen/raw.go
index f675c805..d62a3aca 100644
--- a/util/sqlgen/raw.go
+++ b/util/sqlgen/raw.go
@@ -3,3 +3,7 @@ package sqlgen
 type Raw struct {
 	Raw string
 }
+
+func (self Raw) String() string {
+	return self.Raw
+}
diff --git a/util/sqlgen/value_test.go b/util/sqlgen/value_test.go
new file mode 100644
index 00000000..f7d02827
--- /dev/null
+++ b/util/sqlgen/value_test.go
@@ -0,0 +1,29 @@
+package sqlgen
+
+import (
+	"testing"
+)
+
+func TestValue(t *testing.T) {
+	var s, e string
+	var val Value
+
+	val = Value{1}
+
+	s = val.String()
+	e = `"1"`
+
+	if s != e {
+		t.Fatalf("Got: %s, Expecting: %s", s, e)
+	}
+
+	val = Value{Raw{"NOW()"}}
+
+	s = val.String()
+	e = `NOW()`
+
+	if s != e {
+		t.Fatalf("Got: %s, Expecting: %s", s, e)
+	}
+
+}
diff --git a/util/sqlgen/where.go b/util/sqlgen/where.go
new file mode 100644
index 00000000..830c02b0
--- /dev/null
+++ b/util/sqlgen/where.go
@@ -0,0 +1,51 @@
+package sqlgen
+
+import (
+	"strings"
+)
+
+type (
+	Or    []interface{}
+	And   []interface{}
+	Where []interface{}
+)
+
+func (self Or) String() string {
+	return groupCondition(self, sqlOrKeyword)
+}
+
+func (self And) String() string {
+	return groupCondition(self, sqlAndKeyword)
+}
+
+func (self Where) String() string {
+	return groupCondition(self, sqlAndKeyword)
+}
+
+func groupCondition(terms []interface{}, joinKeyword string) string {
+	l := len(terms)
+
+	chunks := make([]string, 0, l)
+
+	if l > 0 {
+		var i int
+		for i = 0; i < l; i++ {
+			switch v := terms[i].(type) {
+			case ColumnValue:
+				chunks = append(chunks, v.String())
+			case Or:
+				chunks = append(chunks, v.String())
+			case And:
+				chunks = append(chunks, v.String())
+			case Raw:
+				chunks = append(chunks, v.String())
+			}
+		}
+	}
+
+	if len(chunks) > 0 {
+		return mustParse(sqlConditionGroup, strings.Join(chunks, " "+joinKeyword+" "))
+	}
+
+	return ""
+}
diff --git a/util/sqlgen/where_test.go b/util/sqlgen/where_test.go
new file mode 100644
index 00000000..3605fc92
--- /dev/null
+++ b/util/sqlgen/where_test.go
@@ -0,0 +1,91 @@
+package sqlgen
+
+import (
+	"testing"
+)
+
+func TestWhereAnd(t *testing.T) {
+	var s, e string
+	var and And
+
+	and = And{
+		ColumnValue{Column{"id"}, ">", Value{Raw{"8"}}},
+		ColumnValue{Column{"id"}, "<", Value{Raw{"99"}}},
+		ColumnValue{Column{"name"}, "=", Value{"John"}},
+	}
+
+	s = and.String()
+	e = `("id" > 8 AND "id" < 99 AND "name" = "John")`
+
+	if s != e {
+		t.Fatalf("Got: %s, Expecting: %s", s, e)
+	}
+}
+
+func TestWhereOr(t *testing.T) {
+	var s, e string
+	var or Or
+
+	or = Or{
+		ColumnValue{Column{"id"}, "=", Value{Raw{"8"}}},
+		ColumnValue{Column{"id"}, "=", Value{Raw{"99"}}},
+	}
+
+	s = or.String()
+	e = `("id" = 8 OR "id" = 99)`
+
+	if s != e {
+		t.Fatalf("Got: %s, Expecting: %s", s, e)
+	}
+}
+
+func TestWhereAndOr(t *testing.T) {
+	var s, e string
+	var and And
+
+	and = And{
+		ColumnValue{Column{"id"}, ">", Value{Raw{"8"}}},
+		ColumnValue{Column{"id"}, "<", Value{Raw{"99"}}},
+		ColumnValue{Column{"name"}, "=", Value{"John"}},
+		Or{
+			ColumnValue{Column{"last_name"}, "=", Value{"Smith"}},
+			ColumnValue{Column{"last_name"}, "=", Value{"Reyes"}},
+		},
+	}
+
+	s = and.String()
+	e = `("id" > 8 AND "id" < 99 AND "name" = "John" AND ("last_name" = "Smith" OR "last_name" = "Reyes"))`
+
+	if s != e {
+		t.Fatalf("Got: %s, Expecting: %s", s, e)
+	}
+}
+
+func TestWhereAndRawOrAnd(t *testing.T) {
+	var s, e string
+	var where Where
+
+	where = Where{
+		And{
+			ColumnValue{Column{"id"}, ">", Value{Raw{"8"}}},
+			ColumnValue{Column{"id"}, "<", Value{Raw{"99"}}},
+		},
+		ColumnValue{Column{"name"}, "=", Value{"John"}},
+		Raw{"city_id = 728"},
+		Or{
+			ColumnValue{Column{"last_name"}, "=", Value{"Smith"}},
+			ColumnValue{Column{"last_name"}, "=", Value{"Reyes"}},
+		},
+		And{
+			ColumnValue{Column{"age"}, ">", Value{Raw{"18"}}},
+			ColumnValue{Column{"age"}, "<", Value{Raw{"41"}}},
+		},
+	}
+
+	s = where.String()
+	e = `(("id" > 8 AND "id" < 99) AND "name" = "John" AND city_id = 728 AND ("last_name" = "Smith" OR "last_name" = "Reyes") AND ("age" > 18 AND "age" < 41))`
+
+	if s != e {
+		t.Fatalf("Got: %s, Expecting: %s", s, e)
+	}
+}
-- 
GitLab