Repository: timshannon/bolthold
Pull request #140 (2024-03-14 19:32:35)

Added missing key handling in sort queries
Fixes issue #139 


Patch:
diff --git a/query.go b/query.go
index 7869374..3195387 100644
--- a/query.go
+++ b/query.go
@@ -144,6 +144,19 @@ func (s *Store) runQuerySort(source BucketSource, dataType interface{}, query *Q
 		}
 	}
 
+	tp := query.dataType
+
+	var keyType reflect.Type
+	var keyField string
+
+	for i := 0; i < tp.NumField(); i++ {
+		if strings.Contains(string(tp.Field(i).Tag), BoltholdKeyTag) {
+			keyType = tp.Field(i).Type
+			keyField = tp.Field(i).Name
+			break
+		}
+	}
+
 	// Run query without sort, skip or limit
 	// apply sort, skip and limit to entire dataset
 	qCopy := *query
@@ -154,6 +167,24 @@ func (s *Store) runQuerySort(source BucketSource, dataType interface{}, query *Q
 	var records []*record
 	err := s.runQuery(source, dataType, &qCopy, nil, 0,
 		func(r *record) error {
+			if keyType != nil {
+				var rowValue reflect.Value
+
+				// FIXME:
+				if tp.Kind() == reflect.Ptr {
+					rowValue = r.value
+				} else {
+					rowValue = r.value.Elem()
+				}
+				rowKey := rowValue
+				for rowKey.Kind() == reflect.Ptr {
+					rowKey = rowKey.Elem()
+				}
+				err := s.decode(r.key, rowKey.FieldByName(keyField).Addr().Interface())
+				if err != nil {
+					return err
+				}
+			}
 			records = append(records, r)
 
 			return nil


Test patch:
diff --git a/sort_test.go b/sort_test.go
index 95725e0..48723cb 100644
--- a/sort_test.go
+++ b/sort_test.go
@@ -72,6 +72,16 @@ var sortTests = []test{
 		query:  bolthold.Where("Category").Eq("animal").SortBy("Name").Skip(10),
 		result: []int{},
 	},
+	{
+		name:   "Sort By Key",
+		query:  bolthold.Where("Category").Eq("animal").SortBy("Key"),
+		result: []int{2, 5, 8, 9, 13, 14, 16},
+	},
+	{
+		name:   "Sort By Key Reversed",
+		query:  bolthold.Where("Category").Eq("animal").SortBy("Key").Reverse(),
+		result: []int{16, 14, 13, 9, 8, 5, 2},
+	},
 }
 
 func TestSortedFind(t *testing.T) {
@@ -259,3 +269,45 @@ func TestSortedFindWithNonSlicePtr(t *testing.T) {
 		_ = store.Find(result, bolthold.Where("Name").Eq("blah").SortBy("Name"))
 	})
 }
+
+func TestIssue139SortOnSequenceKey(t *testing.T) {
+	testWrap(t, func(store *bolthold.Store, t *testing.T) {
+
+		type Row struct {
+			ID uint64 `boltholdKey:"ID"`
+		}
+
+		ok(t, store.Insert(bolthold.NextSequence(), &Row{}))
+		ok(t, store.Insert(bolthold.NextSequence(), &Row{}))
+		ok(t, store.Insert(bolthold.NextSequence(), &Row{}))
+		ok(t, store.Insert(bolthold.NextSequence(), &Row{}))
+
+		var rows []*Row
+		ok(t, store.Find(&rows, (&bolthold.Query{}).SortBy("ID").Reverse()))
+		equals(t, uint64(4), rows[0].ID)
+		equals(t, uint64(3), rows[1].ID)
+		equals(t, uint64(2), rows[2].ID)
+		equals(t, uint64(1), rows[3].ID)
+
+	})
+
+	testWrap(t, func(store *bolthold.Store, t *testing.T) {
+
+		type Row struct {
+			ID *uint64 `boltholdKey:"ID"`
+		}
+
+		ok(t, store.Insert(bolthold.NextSequence(), &Row{}))
+		ok(t, store.Insert(bolthold.NextSequence(), &Row{}))
+		ok(t, store.Insert(bolthold.NextSequence(), &Row{}))
+		ok(t, store.Insert(bolthold.NextSequence(), &Row{}))
+
+		var rows []*Row
+		ok(t, store.Find(&rows, (&bolthold.Query{}).SortBy("ID").Reverse()))
+		equals(t, uint64(4), *rows[0].ID)
+		equals(t, uint64(3), *rows[1].ID)
+		equals(t, uint64(2), *rows[2].ID)
+		equals(t, uint64(1), *rows[3].ID)
+
+	})
+}