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 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) + + }) +}