From df3697f3be86df0e764f5afd865ec4a4d457dcaf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Nieto?= <jose.carlos@menteslibres.net>
Date: Tue, 29 Jul 2014 22:25:26 -0500
Subject: [PATCH] Adding order by function on SQLite, PostgreSQL and MySQL
 adapters (#32).

---
 main.go              |  2 +-
 main_test.go         | 36 ++++++++++++++++++++++++++++++++++--
 mongo/result.go      |  8 ++++++--
 mysql/result.go      | 32 ++++++++++++++++++++------------
 postgresql/result.go | 32 ++++++++++++++++++++------------
 ql/result.go         | 32 ++++++++++++++++++++------------
 sqlite/result.go     | 32 ++++++++++++++++++++------------
 7 files changed, 121 insertions(+), 53 deletions(-)

diff --git a/main.go b/main.go
index 855e7b8d..44151672 100644
--- a/main.go
+++ b/main.go
@@ -289,7 +289,7 @@ type Result interface {
 	// Receives fields that define the order in which elements will be returned
 	// in a query, field names may be prefixed with a minus sign (-) indicating
 	// descending order; ascending order would be used by default.
-	Sort(...string) Result
+	Sort(...interface{}) Result
 
 	// Defines specific fields to be fulfilled on results in this result set.
 	Select(...interface{}) Result
diff --git a/main_test.go b/main_test.go
index ce689374..461d5257 100644
--- a/main_test.go
+++ b/main_test.go
@@ -517,6 +517,8 @@ func TestSimpleCRUD(t *testing.T) {
 
 func TestFibonacci(t *testing.T) {
 	var err error
+	var res db.Result
+	var total uint64
 
 	for _, wrapper := range wrappers {
 		if settings[wrapper] == nil {
@@ -551,9 +553,39 @@ func TestFibonacci(t *testing.T) {
 				}
 			}
 
+			// Testing sorting by function.
+			res = col.Find(
+				// 5, 6, 7, 3
+				db.Or{
+					db.And{
+						db.Cond{"input >=": 5},
+						db.Cond{"input <=": 7},
+					},
+					db.Cond{"input": 3},
+				},
+			)
+
+			// Testing sort by function.
+			switch wrapper {
+			case `postgresql`:
+				res = res.Sort(db.Raw{`RANDOM()`})
+			case `sqlite`:
+				res = res.Sort(db.Raw{`RANDOM()`})
+			case `mysql`:
+				res = res.Sort(db.Raw{`RAND()`})
+			}
+
+			total, err = res.Count()
+
+			if err != nil {
+				t.Fatalf(`%s: %s`, wrapper, err.Error())
+			}
+
+			if total != 4 {
+				t.Fatalf("%s: Expecting a count of 4, got %d.", wrapper, total)
+			}
+
 			// Find() with IN/$in
-			var res db.Result
-			var total uint64
 			var whereIn db.Cond
 
 			switch wrapper {
diff --git a/mongo/result.go b/mongo/result.go
index a18034d4..0655eeb0 100644
--- a/mongo/result.go
+++ b/mongo/result.go
@@ -75,8 +75,12 @@ func (self *Result) Skip(n uint) db.Result {
 // Determines sorting of results according to the provided names. Fields may be
 // prefixed by - (minus) which means descending order, ascending order would be
 // used otherwise.
-func (self *Result) Sort(fields ...string) db.Result {
-	self.queryChunks.Sort = fields
+func (self *Result) Sort(fields ...interface{}) db.Result {
+	ss := make([]string, len(fields))
+	for i, field := range fields {
+		ss[i] = fmt.Sprintf(`%v`, field)
+	}
+	self.queryChunks.Sort = ss
 	return self
 }
 
diff --git a/mysql/result.go b/mysql/result.go
index 685dde30..afe77ec2 100644
--- a/mysql/result.go
+++ b/mysql/result.go
@@ -86,27 +86,35 @@ func (self *Result) Skip(n uint) db.Result {
 // Determines sorting of results according to the provided names. Fields may be
 // prefixed by - (minus) which means descending order, ascending order would be
 // used otherwise.
-func (self *Result) Sort(fields ...string) db.Result {
+func (self *Result) Sort(fields ...interface{}) db.Result {
 
 	sortColumns := make(sqlgen.SortColumns, 0, len(fields))
 
-	for _, field := range fields {
+	l := len(fields)
+	for i := 0; i < l; i++ {
 		var sort sqlgen.SortColumn
 
-		if strings.HasPrefix(field, `-`) {
-			// Explicit descending order.
-			sort = sqlgen.SortColumn{
-				sqlgen.Column{field[1:]},
-				sqlgen.SqlSortDesc,
-			}
-		} else {
-			// Ascending order.
+		switch value := fields[i].(type) {
+		case db.Raw:
 			sort = sqlgen.SortColumn{
-				sqlgen.Column{field},
+				sqlgen.Column{sqlgen.Raw{fmt.Sprintf(`%v`, value.Value)}},
 				sqlgen.SqlSortAsc,
 			}
+		case string:
+			if strings.HasPrefix(value, `-`) {
+				// Explicit descending order.
+				sort = sqlgen.SortColumn{
+					sqlgen.Column{value[1:]},
+					sqlgen.SqlSortDesc,
+				}
+			} else {
+				// Ascending order.
+				sort = sqlgen.SortColumn{
+					sqlgen.Column{value},
+					sqlgen.SqlSortAsc,
+				}
+			}
 		}
-
 		sortColumns = append(sortColumns, sort)
 	}
 
diff --git a/postgresql/result.go b/postgresql/result.go
index c17fdc49..24b3f16b 100644
--- a/postgresql/result.go
+++ b/postgresql/result.go
@@ -86,27 +86,35 @@ func (self *result) Skip(n uint) db.Result {
 // Determines sorting of results according to the provided names. Fields may be
 // prefixed by - (minus) which means descending order, ascending order would be
 // used otherwise.
-func (self *result) Sort(fields ...string) db.Result {
+func (self *result) Sort(fields ...interface{}) db.Result {
 
 	sortColumns := make(sqlgen.SortColumns, 0, len(fields))
 
-	for _, field := range fields {
+	l := len(fields)
+	for i := 0; i < l; i++ {
 		var sort sqlgen.SortColumn
 
-		if strings.HasPrefix(field, `-`) {
-			// Explicit descending order.
-			sort = sqlgen.SortColumn{
-				sqlgen.Column{field[1:]},
-				sqlgen.SqlSortDesc,
-			}
-		} else {
-			// Ascending order.
+		switch value := fields[i].(type) {
+		case db.Raw:
 			sort = sqlgen.SortColumn{
-				sqlgen.Column{field},
+				sqlgen.Column{sqlgen.Raw{fmt.Sprintf(`%v`, value.Value)}},
 				sqlgen.SqlSortAsc,
 			}
+		case string:
+			if strings.HasPrefix(value, `-`) {
+				// Explicit descending order.
+				sort = sqlgen.SortColumn{
+					sqlgen.Column{value[1:]},
+					sqlgen.SqlSortDesc,
+				}
+			} else {
+				// Ascending order.
+				sort = sqlgen.SortColumn{
+					sqlgen.Column{value},
+					sqlgen.SqlSortAsc,
+				}
+			}
 		}
-
 		sortColumns = append(sortColumns, sort)
 	}
 
diff --git a/ql/result.go b/ql/result.go
index de5aa120..4c9dc638 100644
--- a/ql/result.go
+++ b/ql/result.go
@@ -86,27 +86,35 @@ func (self *result) Skip(n uint) db.Result {
 // Determines sorting of results according to the provided names. Fields may be
 // prefixed by - (minus) which means descending order, ascending order would be
 // used otherwise.
-func (self *result) Sort(fields ...string) db.Result {
+func (self *result) Sort(fields ...interface{}) db.Result {
 
 	sortColumns := make(sqlgen.SortColumns, 0, len(fields))
 
-	for _, field := range fields {
+	l := len(fields)
+	for i := 0; i < l; i++ {
 		var sort sqlgen.SortColumn
 
-		if strings.HasPrefix(field, `-`) {
-			// Explicit descending order.
-			sort = sqlgen.SortColumn{
-				sqlgen.Column{field[1:]},
-				sqlgen.SqlSortDesc,
-			}
-		} else {
-			// Ascending order.
+		switch value := fields[i].(type) {
+		case db.Raw:
 			sort = sqlgen.SortColumn{
-				sqlgen.Column{field},
+				sqlgen.Column{sqlgen.Raw{fmt.Sprintf(`%v`, value.Value)}},
 				sqlgen.SqlSortAsc,
 			}
+		case string:
+			if strings.HasPrefix(value, `-`) {
+				// Explicit descending order.
+				sort = sqlgen.SortColumn{
+					sqlgen.Column{value[1:]},
+					sqlgen.SqlSortDesc,
+				}
+			} else {
+				// Ascending order.
+				sort = sqlgen.SortColumn{
+					sqlgen.Column{value},
+					sqlgen.SqlSortAsc,
+				}
+			}
 		}
-
 		sortColumns = append(sortColumns, sort)
 	}
 
diff --git a/sqlite/result.go b/sqlite/result.go
index c396daa8..79f14063 100644
--- a/sqlite/result.go
+++ b/sqlite/result.go
@@ -86,27 +86,35 @@ func (self *result) Skip(n uint) db.Result {
 // Determines sorting of results according to the provided names. Fields may be
 // prefixed by - (minus) which means descending order, ascending order would be
 // used otherwise.
-func (self *result) Sort(fields ...string) db.Result {
+func (self *result) Sort(fields ...interface{}) db.Result {
 
 	sortColumns := make(sqlgen.SortColumns, 0, len(fields))
 
-	for _, field := range fields {
+	l := len(fields)
+	for i := 0; i < l; i++ {
 		var sort sqlgen.SortColumn
 
-		if strings.HasPrefix(field, `-`) {
-			// Explicit descending order.
-			sort = sqlgen.SortColumn{
-				sqlgen.Column{field[1:]},
-				sqlgen.SqlSortDesc,
-			}
-		} else {
-			// Ascending order.
+		switch value := fields[i].(type) {
+		case db.Raw:
 			sort = sqlgen.SortColumn{
-				sqlgen.Column{field},
+				sqlgen.Column{sqlgen.Raw{fmt.Sprintf(`%v`, value.Value)}},
 				sqlgen.SqlSortAsc,
 			}
+		case string:
+			if strings.HasPrefix(value, `-`) {
+				// Explicit descending order.
+				sort = sqlgen.SortColumn{
+					sqlgen.Column{value[1:]},
+					sqlgen.SqlSortDesc,
+				}
+			} else {
+				// Ascending order.
+				sort = sqlgen.SortColumn{
+					sqlgen.Column{value},
+					sqlgen.SqlSortAsc,
+				}
+			}
 		}
-
 		sortColumns = append(sortColumns, sort)
 	}
 
-- 
GitLab